Warrior refactor completed

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
pull/28/head
parent 7388ffc923
commit d3454727cd
  1. 1
      Crawler/Ability.h
  2. 88
      Crawler/Animation.cpp
  3. 2
      Crawler/Bullet.cpp
  4. 2
      Crawler/Bullet.h
  5. 196
      Crawler/Class.cpp
  6. 6
      Crawler/Class.h
  7. 230
      Crawler/Crawler.cpp
  8. 5
      Crawler/Crawler.h
  9. 1
      Crawler/Crawler.vcxproj
  10. 6
      Crawler/Crawler.vcxproj.filters
  11. 11
      Crawler/DEFINES.h
  12. 4
      Crawler/LightningBolt.cpp
  13. 12
      Crawler/Monster.cpp
  14. 75
      Crawler/Player.cpp
  15. 79
      Crawler/Player.h
  16. 126
      Crawler/Warrior.cpp

@ -8,6 +8,7 @@ struct Ability{
float COOLDOWN_TIME=0;
int manaCost=0;
Pixel barColor1,barColor2;
std::function<bool()>action;
Ability();
Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED);
};

@ -298,48 +298,48 @@ void sig::Animation::InitializeAnimations(){
}
void sig::Animation::SetupPlayerAnimations(){
game->player.AddAnimation(AnimationState::WARRIOR_WALK_N);
game->player.AddAnimation(AnimationState::WARRIOR_WALK_E);
game->player.AddAnimation(AnimationState::WARRIOR_WALK_S);
game->player.AddAnimation(AnimationState::WARRIOR_WALK_W);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_N);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_E);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_S);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_W);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
game->player.AddAnimation(AnimationState::RANGER_WALK_N);
game->player.AddAnimation(AnimationState::RANGER_WALK_E);
game->player.AddAnimation(AnimationState::RANGER_WALK_S);
game->player.AddAnimation(AnimationState::RANGER_WALK_W);
game->player.AddAnimation(AnimationState::RANGER_IDLE_N);
game->player.AddAnimation(AnimationState::RANGER_IDLE_E);
game->player.AddAnimation(AnimationState::RANGER_IDLE_S);
game->player.AddAnimation(AnimationState::RANGER_IDLE_W);
game->player.AddAnimation(AnimationState::WIZARD_WALK_N);
game->player.AddAnimation(AnimationState::WIZARD_WALK_E);
game->player.AddAnimation(AnimationState::WIZARD_WALK_S);
game->player.AddAnimation(AnimationState::WIZARD_WALK_W);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_N);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_E);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_S);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_W);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_N);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_E);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_S);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_W);
game->player.AddAnimation(AnimationState::WIZARD_CAST_N);
game->player.AddAnimation(AnimationState::WIZARD_CAST_E);
game->player.AddAnimation(AnimationState::WIZARD_CAST_S);
game->player.AddAnimation(AnimationState::WIZARD_CAST_W);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_N);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_E);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_S);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_W);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_N);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_E);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_S);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_W);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_N);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_E);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_S);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_W);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_N);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_E);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_S);
game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_W);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_N);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_E);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_S);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_W);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_N);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_E);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_S);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_W);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_N);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_E);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_S);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_W);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_N);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_E);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_S);
game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_W);
}

@ -41,6 +41,6 @@ void Bullet::Draw(){
}
}
bool Bullet::PlayerHit(Player&player){return true;}
bool Bullet::PlayerHit(Player*player){return true;}
bool Bullet::MonsterHit(Monster&monster){return true;}
bool Bullet::OnUpperLevel(){return upperLevel;}

@ -34,7 +34,7 @@ public:
public:
virtual void Update(float fElapsedTime);
//Return true when the bullet should be destroyed. Return false to handle it otherwise (like deactivating it instead). You become responsible for getting rid of the bullet.
virtual bool PlayerHit(Player&player);
virtual bool PlayerHit(Player*player);
//Return true when the bullet should be destroyed. Return false to handle it otherwise (like deactivating it instead). You become responsible for getting rid of the bullet.
virtual bool MonsterHit(Monster&monster);
Animate2D::Frame GetFrame();

@ -1,4 +1,4 @@
#include "Class.h"
#include "DEFINES.h"
#include "Crawler.h"
#include "BulletTypes.h"
@ -11,10 +11,10 @@ std::map<Class,std::unique_ptr<ClassData>>CLASS_DATA;
void ClassData::InitializeClassData(){
CLASS_DATA[WARRIOR]=std::make_unique<Warrior>(Warrior("Warrior",WARRIOR,
{"Block",15,0,VERY_DARK_BLUE,DARK_BLUE},
{"Battlecry",12,40},
{"Ground Slam",15,50},
{"Sonic Slash",40,60},
,
,
,
,
WARRIOR_WALK_N,WARRIOR_WALK_E,WARRIOR_WALK_S,WARRIOR_WALK_W,
WARRIOR_IDLE_N,WARRIOR_IDLE_E,WARRIOR_IDLE_S,WARRIOR_IDLE_W));
CLASS_DATA[RANGER]=std::make_unique<Ranger>(Ranger("Ranger",RANGER,
@ -24,7 +24,7 @@ void ClassData::InitializeClassData(){
{"Multishot",25,50},
RANGER_WALK_N,RANGER_WALK_E,RANGER_WALK_S,RANGER_WALK_W,
RANGER_IDLE_N,RANGER_IDLE_E,RANGER_IDLE_S,RANGER_IDLE_W));
CLASS_DATA[BARD]=std::make_unique<Bard>(Bard("Bard",BARD,
CLASS_DATA[TRAPPER]=std::make_unique<Bard>(Bard("Bard",TRAPPER,
{"???",7,0,VERY_DARK_BLUE,DARK_BLUE},
{"???",12,0},
{"???",15,0},
@ -59,132 +59,6 @@ Warrior::Warrior(std::string name,Class cl,Ability rightClickAbility,Ability abi
walk_n,walk_e,walk_s,walk_w,idle_n,idle_e,idle_s,idle_w)
{}
void Warrior::Update(float fElapsedTime){
ACCESS_PLAYER
if(p.GetState()==State::SWING_SWORD){
switch(p.GetFacingDirection()){
case UP:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
}break;
case DOWN:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
}break;
case LEFT:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
}break;
case RIGHT:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
}break;
}
p.SetSwordSwingTimer(p.GetSwordSwingTimer()-fElapsedTime);
if(p.GetSwordSwingTimer()<=0){
p.SetSwordSwingTimer(0);
p.SetState(State::NORMAL);
}
}
}
bool Warrior::AutoAttack(){
ACCESS_PLAYER
if(p.state!=State::SPIN){
bool attack=false;
Monster*closest=nullptr;
float closest_dist=999999;
for(Monster&m:MONSTER_LIST){
if(m.IsAlive()
&&m.OnUpperLevel()==p.OnUpperLevel()
&&geom2d::overlaps(geom2d::circle<float>(p.pos-vf2d{p.GetSizeMult()*12,p.GetSizeMult()*12},p.attack_range*p.GetSizeMult()*12),geom2d::circle<float>(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12))
&&geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length()<closest_dist){
closest_dist=geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length();
closest=&m;
}
}
if(closest!=nullptr&&closest->Hurt(p.GetAttack())){
p.attack_cooldown_timer=p.ATTACK_COOLDOWN;
p.swordSwingTimer=0.2;
p.SetState(State::SWING_SWORD);
switch(p.facingDirection){
case DOWN:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
}break;
case RIGHT:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
}break;
case LEFT:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
}break;
case UP:{
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
}break;
}
}
}
return true;
}
bool Warrior::Ability1(){
ACCESS_PLAYER
game->AddEffect(std::make_unique<Effect>(p.pos,0.1,AnimationState::BATTLECRY_EFFECT,p.upperLevel,1,0.3));
p.AddBuff(BuffType::ATTACK_UP,10,0.1);
p.AddBuff(BuffType::DAMAGE_REDUCTION,10,0.1);
for(Monster&m:MONSTER_LIST){
if(m.GetSizeMult()<=1&&geom2d::overlaps(geom2d::circle<float>(p.pos,12*3.5),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
m.AddBuff(BuffType::SLOWDOWN,5,0.3);
}
}
return true;
}
bool Warrior::Ability2(){
ACCESS_PLAYER
p.Spin(p.GROUND_SLAM_SPIN_TIME,14*PI);
p.iframe_time=p.GROUND_SLAM_SPIN_TIME+0.1;
return true;
}
bool Warrior::Ability3(){
ACCESS_PLAYER
p.SetState(State::SWING_SONIC_SWORD);
p.AddBuff(BuffType::SLOWDOWN,0.5,1);
vf2d bulletVel={};
switch(p.GetFacingDirection()){
case UP:{
p.vel.y=70;
bulletVel.y=-400;
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
}break;
case LEFT:{
p.vel.x=70;
bulletVel.x=-400;
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
}break;
case RIGHT:{
p.vel.x=-70;
bulletVel.x=400;
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
}break;
case DOWN:{
p.vel.y=-70;
bulletVel.y=400;
p.UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
}break;
}
BULLET_LIST.push_back(std::make_unique<Bullet>(p.pos,bulletVel,30,p.GetAttack()*8,AnimationState::SONICSLASH,p.upperLevel,true,2.25,true,true,WHITE));
game->SetupWorldShake(0.5);
return true;
}
bool Warrior::RightClickAbility(){
ACCESS_PLAYER
if(p.GetState()==State::NORMAL){
rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
p.SetState(State::BLOCK);
p.AddBuff(BuffType::SLOWDOWN,3,0.3);
return true;
}
return false;
}
Thief::Thief(std::string name,Class cl,Ability rightClickAbility,Ability ability1,Ability ability2,Ability ability3,
AnimationState walk_n,AnimationState walk_e,AnimationState walk_s,AnimationState walk_w,AnimationState idle_n,AnimationState idle_e,AnimationState idle_s,AnimationState idle_w)
:ClassData(name,cl,rightClickAbility,ability1,ability2,ability3,
@ -280,7 +154,7 @@ Wizard::Wizard(std::string name,Class cl,Ability rightClickAbility,Ability abili
void Wizard::Update(float fElapsedTime){
ACCESS_PLAYER
if(p.attack_cooldown_timer>0){
if(p->attack_cooldown_timer>0){
CLASS_DATA[cl]->idle_n=AnimationState::WIZARD_IDLE_ATTACK_N;
CLASS_DATA[cl]->idle_e=AnimationState::WIZARD_IDLE_ATTACK_E;
CLASS_DATA[cl]->idle_s=AnimationState::WIZARD_IDLE_ATTACK_S;
@ -299,19 +173,19 @@ void Wizard::Update(float fElapsedTime){
CLASS_DATA[cl]->walk_s=AnimationState::WIZARD_WALK_S;
CLASS_DATA[cl]->walk_w=AnimationState::WIZARD_WALK_W;
}
if(p.GetState()==State::CASTING){
switch(p.GetFacingDirection()){
if(p->GetState()==State::CASTING){
switch(p->GetFacingDirection()){
case UP:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_N);
p->UpdateAnimation(AnimationState::WIZARD_CAST_N);
}break;
case DOWN:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_S);
p->UpdateAnimation(AnimationState::WIZARD_CAST_S);
}break;
case LEFT:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_W);
p->UpdateAnimation(AnimationState::WIZARD_CAST_W);
}break;
case RIGHT:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_E);
p->UpdateAnimation(AnimationState::WIZARD_CAST_E);
}break;
}
}
@ -319,56 +193,56 @@ void Wizard::Update(float fElapsedTime){
bool Wizard::AutoAttack(){
ACCESS_PLAYER
p.attack_cooldown_timer=p.MAGIC_ATTACK_COOLDOWN;
float angleToCursor=atan2(game->GetWorldMousePos().y-p.pos.y,game->GetWorldMousePos().x-p.pos.x);
BULLET_LIST.push_back(std::make_unique<EnergyBolt>(EnergyBolt(p.pos,{cos(angleToCursor)*200,sin(angleToCursor)*200},12,p.GetAttack(),p.upperLevel,true,WHITE)));
p->attack_cooldown_timer=p->MAGIC_ATTACK_COOLDOWN;
float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
BULLET_LIST.push_back(std::make_unique<EnergyBolt>(EnergyBolt(p->GetPos(),{cos(angleToCursor)*200,sin(angleToCursor)*200},12,p->GetAttack(),p->upperLevel,true,WHITE)));
return true;
}
bool Wizard::Ability1(){
ACCESS_PLAYER
float angleToCursor=atan2(game->GetWorldMousePos().y-p.pos.y,game->GetWorldMousePos().x-p.pos.x);
BULLET_LIST.push_back(std::make_unique<FireBolt>(FireBolt(p.pos,{cos(angleToCursor)*275,sin(angleToCursor)*275},12,p.GetAttack(),p.upperLevel,true,{240,120,60})));
float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
BULLET_LIST.push_back(std::make_unique<FireBolt>(FireBolt(p->GetPos(),{cos(angleToCursor)*275,sin(angleToCursor)*275},12,p->GetAttack(),p->upperLevel,true,{240,120,60})));
return true;
}
bool Wizard::Ability2(){
ACCESS_PLAYER
float angleToCursor=atan2(game->GetWorldMousePos().y-p.pos.y,game->GetWorldMousePos().x-p.pos.x);
BULLET_LIST.push_back(std::make_unique<LightningBolt>(LightningBolt(p.pos,{cos(angleToCursor)*230,sin(angleToCursor)*230},12,p.GetAttack()*4,p.upperLevel,true,WHITE)));
float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
BULLET_LIST.push_back(std::make_unique<LightningBolt>(LightningBolt(p->GetPos(),{cos(angleToCursor)*230,sin(angleToCursor)*230},12,p->GetAttack()*4,p->upperLevel,true,WHITE)));
return true;
}
bool Wizard::Ability3(){
ACCESS_PLAYER
p.SetState(State::CASTING);
game->AddEffect(std::make_unique<Meteor>(p.GetPos(),3,AnimationState::METEOR,p.OnUpperLevel(),vf2d{1,1},2));
p->SetState(State::CASTING);
game->AddEffect(std::make_unique<Meteor>(p->GetPos(),3,AnimationState::METEOR,p->OnUpperLevel(),vf2d{1,1},2));
return true;
}
bool Wizard::RightClickAbility(){
ACCESS_PLAYER
float pointMouseDirection=atan2(game->GetWorldMousePos().y-p.GetPos().y,game->GetWorldMousePos().x-p.GetPos().x);
float pointMouseDirection=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
vf2d pointTowardsMouse={cos(pointMouseDirection),sin(pointMouseDirection)};
float dist=std::clamp(geom2d::line<float>{p.GetPos(),game->GetWorldMousePos()}.length(),0.f,6.5f*24);
float dist=std::clamp(geom2d::line<float>{p->GetPos(),game->GetWorldMousePos()}.length(),0.f,6.5f*24);
if(dist<12)return false;
vf2d teleportPoint=p.GetPos()+pointTowardsMouse*dist;
while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p.CanPathfindTo(p.GetPos(),teleportPoint)){
vf2d teleportPoint=p->GetPos()+pointTowardsMouse*dist;
while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p->CanPathfindTo(p->GetPos(),teleportPoint)){
dist-=24;
teleportPoint=p.GetPos()+pointTowardsMouse*dist;
teleportPoint=p->GetPos()+pointTowardsMouse*dist;
}
if(dist>0&&p.CanPathfindTo(p.GetPos(),teleportPoint)){
p.SetState(State::TELEPORT);
p.teleportAnimationTimer=0.35;
p.teleportTarget=teleportPoint;
p.teleportStartPosition=p.GetPos();
p.iframe_time=0.35;
if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint)){
p->SetState(State::TELEPORT);
p->teleportAnimationTimer=0.35;
p->teleportTarget=teleportPoint;
p->teleportStartPosition=p->GetPos();
p->iframe_time=0.35;
for(int i=0;i<16;i++){
game->AddEffect(std::make_unique<Effect>(p.GetPos()+vf2d{(rand()%160-80)/10.f,(rand()%160-80)/10.f},float(rand()%300)/1000,AnimationState::DOT_PARTICLE,p.upperLevel,0.3,0.2,vf2d{float(rand()%1000-500)/100,float(rand()%1000-500)/100},BLACK));
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(rand()%160-80)/10.f,(rand()%160-80)/10.f},float(rand()%300)/1000,AnimationState::DOT_PARTICLE,p->upperLevel,0.3,0.2,vf2d{float(rand()%1000-500)/100,float(rand()%1000-500)/100},BLACK));
}
return true;
} else {
p.notificationDisplay={"Cannot Teleport to that location!",0.5};
p->notificationDisplay={"Cannot Teleport to that location!",0.5};
return false;
}
}

@ -4,13 +4,9 @@
#include "olcPixelGameEngine.h"
enum Class{
WARRIOR,THIEF,RANGER,BARD,WIZARD,WITCH
WARRIOR,THIEF,RANGER,TRAPPER,WIZARD,WITCH
};
struct ClassData{
std::string name;
Class cl;
Ability rightClickAbility,ability1,ability2,ability3;
AnimationState walk_n,walk_e,walk_s,walk_w,idle_n,idle_e,idle_s,idle_w;
static void InitializeClassData();
ClassData(std::string name,Class cl,Ability rightClickAbility,Ability ability1,Ability ability2,Ability ability3,
AnimationState walk_n,AnimationState walk_e,AnimationState walk_s,AnimationState walk_w,AnimationState idle_n,AnimationState idle_e,AnimationState idle_s,AnimationState idle_w);

@ -49,7 +49,7 @@ bool Crawler::OnUserCreate(){
//Initialize Camera.
camera=Camera2D{WINDOW_SIZE};
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
camera.SetTarget(player.GetPos());
camera.SetTarget(player->GetPos());
camera.SetWorldBoundary({0,0},WORLD_SIZE*24);
camera.EnableWorldBoundary(false);
@ -88,7 +88,7 @@ bool Crawler::OnUserCreate(){
LoadLevel(CAMPAIGN_1_1);
player.ChangeClass(WARRIOR);
player->ChangeClass(WARRIOR);
return true;
}
@ -97,7 +97,7 @@ bool Crawler::OnUserUpdate(float fElapsedTime){
fElapsedTime=std::min(1/60.f,fElapsedTime);
HandleUserInput(fElapsedTime);
UpdateEffects(fElapsedTime);
player.Update(fElapsedTime);
player->Update(fElapsedTime);
for(Monster&m:MONSTER_LIST){
m.Update(fElapsedTime);
}
@ -139,36 +139,36 @@ void Crawler::HandleUserInput(float fElapsedTime){
ConsoleShow(F1);
}
if(GetMouseWheel()>0){
switch(player.cl){
switch(player->GetClass()){
case WARRIOR:{
player.ChangeClass(RANGER);
player->ChangeClass(RANGER);
}break;
case RANGER:{
player.ChangeClass(WIZARD);
player->ChangeClass(WIZARD);
}break;
case WIZARD:{
player.ChangeClass(WARRIOR);
player->ChangeClass(WARRIOR);
}break;
}
}
if(GetMouseWheel()<0){
switch(player.cl){
switch(player->GetClass()){
case WARRIOR:{
player.ChangeClass(WIZARD);
player->ChangeClass(WIZARD);
}break;
case RANGER:{
player.ChangeClass(WARRIOR);
player->ChangeClass(WARRIOR);
}break;
case WIZARD:{
player.ChangeClass(RANGER);
player->ChangeClass(RANGER);
}break;
}
}
if(player.GetVelocity()==vf2d{0,0}&&player.CanMove()){
if(player->GetVelocity()==vf2d{0,0}&&player->CanMove()){
auto GetPlayerStaircaseDirection=[&](){
for(LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){
int truncatedPlayerX=int(player.GetX())/24;
int truncatedPlayerY=int(player.GetY())/24;
int truncatedPlayerX=int(player->GetX())/24;
int truncatedPlayerY=int(player->GetY())/24;
int tileID=layer.tiles[truncatedPlayerY][truncatedPlayerX];
TilesheetData dat=GetTileSheet(GetCurrentLevel(),tileID);
if (dat.tileset.staircaseTiles.find(tileID)!=dat.tileset.staircaseTiles.end()){
@ -179,133 +179,133 @@ void Crawler::HandleUserInput(float fElapsedTime){
};
std::string staircaseDirection=GetPlayerStaircaseDirection();
if(RightHeld()){
player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult());
player->SetX(player->GetX()+fElapsedTime*100*player->GetMoveSpdMult());
if(staircaseDirection=="RIGHT"){
player.SetY(player.GetY()-60*fElapsedTime*player.GetMoveSpdMult());
player->SetY(player->GetY()-60*fElapsedTime*player->GetMoveSpdMult());
} else
if(staircaseDirection=="LEFT"){
player.SetY(player.GetY()+60*fElapsedTime*player.GetMoveSpdMult());
player->SetY(player->GetY()+60*fElapsedTime*player->GetMoveSpdMult());
}
player.SetFacingDirection(RIGHT);
if(player.GetState()==State::NORMAL){
player.UpdateWalkingAnimation(RIGHT);
player->SetFacingDirection(RIGHT);
if(player->GetState()==State::NORMAL){
player->UpdateWalkingAnimation(RIGHT);
}
setIdleAnimation=false;
}
if(LeftHeld()){
player.SetX(player.GetX()-fElapsedTime*100*player.GetMoveSpdMult());
player->SetX(player->GetX()-fElapsedTime*100*player->GetMoveSpdMult());
if(staircaseDirection=="RIGHT"){
player.SetY(player.GetY()+60*fElapsedTime*player.GetMoveSpdMult());
player->SetY(player->GetY()+60*fElapsedTime*player->GetMoveSpdMult());
} else
if(staircaseDirection=="LEFT"){
player.SetY(player.GetY()-60*fElapsedTime*player.GetMoveSpdMult());
player->SetY(player->GetY()-60*fElapsedTime*player->GetMoveSpdMult());
}
if(setIdleAnimation){
player.SetFacingDirection(LEFT);
if(player.GetState()==State::NORMAL){
player.UpdateWalkingAnimation(LEFT);
player->SetFacingDirection(LEFT);
if(player->GetState()==State::NORMAL){
player->UpdateWalkingAnimation(LEFT);
}
}
setIdleAnimation=false;
}
if(UpHeld()){
player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult());
player->SetY(player->GetY()-fElapsedTime*100*player->GetMoveSpdMult());
if(setIdleAnimation){
player.SetFacingDirection(UP);
if(player.GetState()==State::NORMAL){
player.UpdateWalkingAnimation(UP);
player->SetFacingDirection(UP);
if(player->GetState()==State::NORMAL){
player->UpdateWalkingAnimation(UP);
}
}
setIdleAnimation=false;
}
if(DownHeld()){
player.SetY(player.GetY()+fElapsedTime*100*player.GetMoveSpdMult());
player->SetY(player->GetY()+fElapsedTime*100*player->GetMoveSpdMult());
if(setIdleAnimation){
player.SetFacingDirection(DOWN);
if(player.GetState()==State::NORMAL){
player.UpdateWalkingAnimation(DOWN);
player->SetFacingDirection(DOWN);
if(player->GetState()==State::NORMAL){
player->UpdateWalkingAnimation(DOWN);
}
}
setIdleAnimation=false;
}
}
if(UpReleased()){
player.SetLastReleasedMovementKey(UP);
if(player.GetState()==State::NORMAL){
player->SetLastReleasedMovementKey(UP);
if(player->GetState()==State::NORMAL){
if(RightHeld()){
player.UpdateWalkingAnimation(RIGHT);
player->UpdateWalkingAnimation(RIGHT);
} else
if(DownHeld()){
player.UpdateWalkingAnimation(DOWN);
player->UpdateWalkingAnimation(DOWN);
} else
if(LeftHeld()){
player.UpdateWalkingAnimation(LEFT);
player->UpdateWalkingAnimation(LEFT);
}
}
}
if(RightReleased()){
player.SetLastReleasedMovementKey(RIGHT);
if(player.GetState()==State::NORMAL){
player->SetLastReleasedMovementKey(RIGHT);
if(player->GetState()==State::NORMAL){
if(UpHeld()){
player.UpdateWalkingAnimation(UP);
player->UpdateWalkingAnimation(UP);
} else
if(DownHeld()){
player.UpdateWalkingAnimation(DOWN);
player->UpdateWalkingAnimation(DOWN);
} else
if(LeftHeld()){
player.UpdateWalkingAnimation(LEFT);
player->UpdateWalkingAnimation(LEFT);
}
}
}
if(LeftReleased()){
player.SetLastReleasedMovementKey(LEFT);
if(player.GetState()==State::NORMAL){
player->SetLastReleasedMovementKey(LEFT);
if(player->GetState()==State::NORMAL){
if(RightHeld()){
player.UpdateWalkingAnimation(RIGHT);
player->UpdateWalkingAnimation(RIGHT);
} else
if(DownHeld()){
player.UpdateWalkingAnimation(DOWN);
player->UpdateWalkingAnimation(DOWN);
} else
if(UpHeld()){
player.UpdateWalkingAnimation(UP);
player->UpdateWalkingAnimation(UP);
}
}
}
if(DownReleased()){
player.SetLastReleasedMovementKey(DOWN);
if(player.GetState()==State::NORMAL){
player->SetLastReleasedMovementKey(DOWN);
if(player->GetState()==State::NORMAL){
if(RightHeld()){
player.UpdateWalkingAnimation(RIGHT);
player->UpdateWalkingAnimation(RIGHT);
} else
if(UpHeld()){
player.UpdateWalkingAnimation(UP);
player->UpdateWalkingAnimation(UP);
} else
if(LeftHeld()){
player.UpdateWalkingAnimation(LEFT);
player->UpdateWalkingAnimation(LEFT);
}
}
}
if(player.GetState()!=State::NORMAL){
if(player->GetState()!=State::NORMAL){
setIdleAnimation=false;
}
if(setIdleAnimation){
switch(player.GetLastReleasedMovementKey()){
switch(player->GetLastReleasedMovementKey()){
case UP:{
player.UpdateIdleAnimation(UP);
player->UpdateIdleAnimation(UP);
}break;
case DOWN:{
player.UpdateIdleAnimation(DOWN);
player->UpdateIdleAnimation(DOWN);
}break;
case LEFT:{
player.UpdateIdleAnimation(LEFT);
player->UpdateIdleAnimation(LEFT);
}break;
case RIGHT:{
player.UpdateIdleAnimation(RIGHT);
player->UpdateIdleAnimation(RIGHT);
}break;
default:{
player.UpdateIdleAnimation(DOWN);
player->UpdateIdleAnimation(DOWN);
}
}
}
@ -326,7 +326,7 @@ void Crawler::UpdateCamera(float fElapsedTime){
}
worldShake+=worldShakeVel*fElapsedTime;
} else {
camera.SetTarget(player.GetPos());
camera.SetTarget(player->GetPos());
}
worldShakeTime=std::max(0.f,worldShakeTime-fElapsedTime);
camera.Update(fElapsedTime);
@ -388,9 +388,9 @@ void Crawler::UpdateBullets(float fElapsedTime){
}
}
} else {
if(b->OnUpperLevel()==player.OnUpperLevel()&&geom2d::overlaps(geom2d::circle(player.GetPos(),12*player.GetSizeMult()/2),geom2d::circle(b->pos,b->radius))){
if(player.Hurt(b->damage)){
if(b->PlayerHit(player)){
if(b->OnUpperLevel()==player->OnUpperLevel()&&geom2d::overlaps(geom2d::circle(player->GetPos(),12*player->GetSizeMult()/2),geom2d::circle(b->pos,b->radius))){
if(player->Hurt(b->damage)){
if(b->PlayerHit(GetPlayer())){
it=BULLET_LIST.erase(it);
if(it==BULLET_LIST.end()){
break;
@ -431,10 +431,10 @@ void Crawler::HurtEnemies(vf2d pos,float radius,int damage,bool upperLevel){
}
void Crawler::PopulateRenderLists(std::vector<Monster*>&monstersBeforeLower,std::vector<Monster*>&monstersBeforeUpper,std::vector<Monster*>&monstersAfterLower,std::vector<Monster*>&monstersAfterUpper,std::vector<Bullet*>&bulletsLower,std::vector<Bullet*>&bulletsUpper,std::vector<Effect*>&backgroundEffectsLower,std::vector<Effect*>&backgroundEffectsUpper,std::vector<Effect*>&foregroundEffectsLower,std::vector<Effect*>&foregroundEffectsUpper){
Player&pl=player;
Player*pl=GetPlayer();
for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){
Monster&m=*it;
if(m.GetPos().y<pl.GetPos().y){//This monster renders before the player does (behind the player)
if(m.GetPos().y<pl->GetPos().y){//This monster renders before the player does (behind the player)
if(m.OnUpperLevel()){
monstersBeforeUpper.push_back(&m);
}else{
@ -489,11 +489,11 @@ void Crawler::RenderWorld(float fElapsedTime){
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
if(IsBridgeLayer(layer)){
bridgeLayer=&layer;
if(!bridgeLayerFade&&!player.upperLevel){
if(!bridgeLayerFade&&!player->upperLevel){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
int playerXTruncated=int(player.GetPos().x)/24;
int playerYTruncated=int(player.GetPos().y)/24;
int playerXTruncated=int(player->GetPos().x)/24;
int playerYTruncated=int(player->GetPos().y)/24;
if(playerXTruncated==x&&playerYTruncated==y){
bridgeLayerFade=true;
}
@ -534,13 +534,13 @@ void Crawler::RenderWorld(float fElapsedTime){
std::vector<Monster*>monstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper;
std::vector<Bullet*>bulletsLower,bulletsUpper;
std::vector<Effect*>backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper;
Player&pl=player;
Player*pl=GetPlayer();
PopulateRenderLists(monstersBeforeLower,monstersBeforeUpper,monstersAfterLower,monstersAfterUpper,bulletsLower,bulletsUpper,backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper);
if(player.GetZ()>0){
vf2d shadowScale=vf2d{8/3.f,1}/std::max(1.f,player.GetZ()/4);
view.DrawDecal(player.GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6},GFX_Circle.Decal(),shadowScale);
if(player->GetZ()>0){
vf2d shadowScale=vf2d{8/3.f,1}/std::max(1.f,player->GetZ()/4);
view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6},GFX_Circle.Decal(),shadowScale);
}
for(Effect*e:backgroundEffectsLower){
e->Draw();
@ -548,20 +548,20 @@ void Crawler::RenderWorld(float fElapsedTime){
for(Monster*m:monstersBeforeLower){
m->Draw();
}
vf2d playerScale=vf2d(player.GetSizeMult(),player.GetSizeMult());
vf2d playerPosition=player.GetPos();
vf2d playerScale=vf2d(player->GetSizeMult(),player->GetSizeMult());
vf2d playerPosition=player->GetPos();
#define RENDER_PLAYER \
if(player.teleportAnimationTimer>0){ \
playerScale.x=120*abs(pow(player.teleportAnimationTimer-0.175,3)); \
playerPosition=player.teleportStartPosition.lerp(player.teleportTarget,(0.35-player.teleportAnimationTimer)/0.35); \
view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,playerScale,player.GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE); \
} else {view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,playerScale,player.GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE);}
if(player->teleportAnimationTimer>0){ \
playerScale.x=120*abs(pow(player->teleportAnimationTimer-0.175,3)); \
playerPosition=player->teleportStartPosition.lerp(player->teleportTarget,(0.35-player->teleportAnimationTimer)/0.35); \
view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player->GetZ()},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale,player->GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE); \
} else {view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player->GetZ()},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale,player->GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE);}
//define end
if(!player.upperLevel){
if(!player->upperLevel){
RENDER_PLAYER
}
if(player.GetState()==State::BLOCK){
view.DrawDecal(player.GetPos()-vf2d{12,12},GFX_BLOCK_BUBBLE.Decal());
if(player->GetState()==State::BLOCK){
view.DrawDecal(player->GetPos()-vf2d{12,12},GFX_BLOCK_BUBBLE.Decal());
}
for(Monster*m:monstersAfterLower){
m->Draw();
@ -575,7 +575,7 @@ void Crawler::RenderWorld(float fElapsedTime){
#pragma region Foreground Rendering
for(TileGroup&group:foregroundTileGroups){
if(view.IsRectVisible(group.GetRange().pos,group.GetRange().size)){
if(geom2d::overlaps(group.GetFadeRange(),player.pos)){
if(geom2d::overlaps(group.GetFadeRange(),player->pos)){
group.playerBehind=true;
group.fadeFactor=std::min(group.fadeFactor+fElapsedTime,TileGroup::FADE_TIME);
} else {
@ -621,7 +621,7 @@ void Crawler::RenderWorld(float fElapsedTime){
for(Monster*m:monstersBeforeUpper){
m->Draw();
}
if(player.upperLevel){
if(player->upperLevel){
RENDER_PLAYER
}
for(Monster*m:monstersAfterUpper){
@ -635,7 +635,7 @@ void Crawler::RenderWorld(float fElapsedTime){
}
#pragma region Upper Foreground Rendering
for(TileGroup&group:upperForegroundTileGroups){
if(geom2d::overlaps(group.GetFadeRange(),player.pos)){
if(geom2d::overlaps(group.GetFadeRange(),player->pos)){
group.playerBehind=true;
group.fadeFactor=std::min(group.fadeFactor+fElapsedTime,TileGroup::FADE_TIME);
} else {
@ -665,8 +665,8 @@ void Crawler::RenderWorld(float fElapsedTime){
}
}
Player&Crawler::GetPlayer(){
return player;
Player*Crawler::GetPlayer(){
return player.get();
}
void Crawler::RenderHud(){
@ -679,10 +679,10 @@ void Crawler::RenderHud(){
return newName;
};
std::vector<Ability>cooldowns{
player.rightClickAbility,
player.ability1,
player.ability2,
player.ability3
player->rightClickAbility,
player->ability1,
player->ability2,
player->ability3
};
std::vector<Ability>activeCooldowns;
std::copy_if(cooldowns.begin(),cooldowns.end(),std::back_inserter(activeCooldowns),[](Ability a){
@ -706,23 +706,23 @@ void Crawler::RenderHud(){
}
DrawDecal({2,2},GFX_Heart.Decal());
DrawDecal({2,20},GFX_Mana.Decal());
std::string text=player.GetHealth()>0?std::to_string(player.GetHealth()):"X";
std::string text_mana=std::to_string(player.GetMana());
std::string text=player->GetHealth()>0?std::to_string(player->GetHealth()):"X";
std::string text_mana=std::to_string(player->GetMana());
DrawShadowStringPropDecal({20,3},text,WHITE,BLACK,{2,2});
DrawShadowStringPropDecal({24,23},text_mana,{192,192,255},BLACK,{1.5,1.5});
if(player.notEnoughManaDisplay.second>0){
std::string displayText="Not enough mana for "+player.notEnoughManaDisplay.first+"!";
if(player->notEnoughManaDisplay.second>0){
std::string displayText="Not enough mana for "+player->notEnoughManaDisplay.first+"!";
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)}-GetTextSizeProp(displayText)/2,displayText,DARK_RED,VERY_DARK_RED);
}
if(player.notificationDisplay.second>0){
std::string displayText=player.notificationDisplay.first;
if(player->notificationDisplay.second>0){
std::string displayText=player->notificationDisplay.first;
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)-24}-GetTextSizeProp(displayText)/2,displayText,BLUE,VERY_DARK_BLUE);
}
std::string versionStr("v" + std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR) + "." + std::to_string(VERSION_PATCH) + "." + std::to_string(VERSION_BUILD));
DrawShadowStringDecal(vf2d{ GetScreenSize() } - vf2d{ GetTextSize(versionStr) }*0.4,versionStr,WHITE,BLACK,{0.4,0.4},0.4);
#ifdef DEBUG_POS
DrawShadowStringDecal({0,128},player.GetPos().str());
DrawShadowStringDecal({0,128},player->GetPos().str());
#endif
}
@ -745,7 +745,7 @@ vf2d Crawler::GetWorldMousePos(){
void Crawler::SetupWorldShake(float duration){
worldShakeTime=duration;
worldShake=player.GetPos();
worldShake=player->GetPos();
camera.SetTarget(worldShake);
}
@ -878,8 +878,8 @@ void Crawler::LoadLevel(MapName map){
}
counter++;
}
player.upperLevel=false; //Assume player starts on lower level.
player.SetPos(MAP_DATA[map].MapData.playerSpawnLocation);
player->upperLevel=false; //Assume player starts on lower level.
player->SetPos(MAP_DATA[map].MapData.playerSpawnLocation);
pathfinder.Initialize();
}
@ -969,6 +969,30 @@ std::map<std::string,std::vector<geom2d::rect<int>>>&Crawler::GetZoneData(MapNam
return MAP_DATA[map].ZoneData;
}
void Crawler::ChangePlayerClass(Class cl){
switch(cl){
case WARRIOR:{
player.reset(new Warrior());
}break;
case THIEF:{
player.reset(new Thief());
}break;
case TRAPPER:{
player.reset(new Trapper());
}break;
case RANGER:{
player.reset(new Ranger());
}break;
case WIZARD:{
player.reset(new Wizard());
}break;
case WITCH:{
player.reset(new Witch());
}break;
}
GetPlayer()->UpdateIdleAnimation(DOWN);
}
int main()
{
Crawler demo;

@ -20,7 +20,7 @@ class Crawler : public olc::PixelGameEngine
{
friend class sig::Animation;
Camera2D camera;
Player player;
std::unique_ptr<Player>player;
Renderable GFX_Warrior_Sheet,GFX_Slime_Sheet,
GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front,
GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet,
@ -75,7 +75,7 @@ public:
bool RightReleased();
bool UpReleased();
bool DownReleased();
Player&GetPlayer();
Player*GetPlayer();
void SetupWorldShake(float duration);
vi2d GetWorldSize();
//tileID is the tile number from the tilesets.
@ -92,4 +92,5 @@ public:
bool IsBridgeLayer(LayerTag&layer);
std::map<std::string,std::vector<geom2d::rect<int>>>&GetZoneData(MapName map);
void PopulateRenderLists(std::vector<Monster*>&monstersBeforeLower,std::vector<Monster*>&monstersBeforeUpper,std::vector<Monster*>&monstersAfterLower,std::vector<Monster*>&monstersAfterUpper,std::vector<Bullet*>&bulletsLower,std::vector<Bullet*>&bulletsUpper,std::vector<Effect*>&backgroundEffectsLower,std::vector<Effect*>&backgroundEffectsUpper,std::vector<Effect*>&foregroundEffectsLower,std::vector<Effect*>&foregroundEffectsUpper);
void ChangePlayerClass(Class cl);
};

@ -220,6 +220,7 @@
<ClCompile Include="Player.cpp" />
<ClCompile Include="Monster.cpp" />
<ClCompile Include="MonsterData.cpp" />
<ClCompile Include="Warrior.cpp" />
<ClCompile Include="utils.cpp" />
</ItemGroup>
<ItemGroup>

@ -25,6 +25,9 @@
<Filter Include="Source Files\Effects">
<UniqueIdentifier>{94ea6039-63ac-430d-bb96-317bf1b7a305}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Player Classes">
<UniqueIdentifier>{715c64c5-956a-4ed3-9205-64110409fbea}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="olcPixelGameEngine.h">
@ -164,6 +167,9 @@
<ClCompile Include="LightningBoltEmitter.cpp">
<Filter>Source Files\Emitters</Filter>
</ClCompile>
<ClCompile Include="Warrior.cpp">
<Filter>Source Files\Player Classes</Filter>
</ClCompile>
<ClCompile Include="Emitter.cpp">
<Filter>Source Files</Filter>
</ClCompile>

@ -10,6 +10,15 @@
#define INCLUDE_PARTICLE_LIST extern std::vector<Particle>PARTICLE_LIST;
#define INCLUDE_EMITTER_LIST extern std::vector<std::unique_ptr<Emitter>>EMITTER_LIST;
#define ACCESS_PLAYER Player&p=game->GetPlayer();
#define ACCESS_PLAYER Player*p=game->GetPlayer();
#define INFINITE 999999
#define SETUP_CLASS(class) \
Class class::GetClass(){return cl;} \
std::string class::GetClassName(){return name;} \
Ability&class::GetRightClickAbility(){return rightClickAbility;}; \
Ability&class::GetAbility1(){return ability1;}; \
Ability&class::GetAbility2(){return ability2;}; \
Ability&class::GetAbility3(){return ability3;}; \
Ability&class::GetAbility4(){return ability4;};

@ -52,8 +52,10 @@ bool LightningBolt::MonsterHit(Monster& monster)
if(&m==&monster||monster.OnUpperLevel()!=m.OnUpperLevel())continue;
geom2d::line<float>lineToTarget=geom2d::line<float>(monster.GetPos(),m.GetPos());
float dist=lineToTarget.length();
vf2d vec;
vec.norm();
if(dist<=72){
if(m.Hurt(game->GetPlayer().GetAttack()*2)){
if(m.Hurt(game->GetPlayer()->GetAttack()*2)){
EMITTER_LIST.push_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m.GetPos(),0.05,0.25,upperLevel)));
game->AddEffect(std::make_unique<Effect>(m.GetPos(),0.5,AnimationState::LIGHTNING_SPLASH,upperLevel,monster.GetSizeMult(),0.25,vf2d{},WHITE,util::random(PI)));
targetsHit++;

@ -119,14 +119,14 @@ bool Monster::Update(float fElapsedTime){
}
}
}
if(!game->GetPlayer().HasIframes()&&game->GetPlayer().OnUpperLevel()==OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(game->GetPlayer().GetPos(),12*game->GetPlayer().GetSizeMult()/2))){
geom2d::line line(pos,game->GetPlayer().GetPos());
if(!game->GetPlayer()->HasIframes()&&game->GetPlayer()->OnUpperLevel()==OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(game->GetPlayer()->GetPos(),12*game->GetPlayer()->GetSizeMult()/2))){
geom2d::line line(pos,game->GetPlayer()->GetPos());
float dist = line.length();
SetPosition(line.rpoint(-0.1));
vel=line.vector().norm()*-128;
}
if(state==NORMAL){
if(game->GetPlayer().GetX()>pos.x){
if(game->GetPlayer()->GetX()>pos.x){
facingDirection=RIGHT;
} else {
facingDirection=LEFT;
@ -137,7 +137,7 @@ bool Monster::Update(float fElapsedTime){
targetAcquireTimer=std::max(0.f,targetAcquireTimer-fElapsedTime);
if(targetAcquireTimer==0){
targetAcquireTimer=3;
target=geom2d::line(pos,game->GetPlayer().GetPos()).upoint(1.2);
target=geom2d::line(pos,game->GetPlayer()->GetPos()).upoint(1.2);
state=MOVE_TOWARDS;
hasHitPlayer=false;
}
@ -169,11 +169,11 @@ bool Monster::Update(float fElapsedTime){
if(queueShotTimer<0){
queueShotTimer=0;
{
BULLET_LIST.push_back(std::make_unique<Bullet>(Bullet(pos + vf2d{ 0,-4 }, geom2d::line(pos + vf2d{ 0,-4 }, game->GetPlayer().GetPos()).vector().norm() * 24 * 3.f, 2, GetAttack(),upperLevel,false, { 75 / 2,162 / 2,225 / 2 })));
BULLET_LIST.push_back(std::make_unique<Bullet>(Bullet(pos + vf2d{ 0,-4 }, geom2d::line(pos + vf2d{ 0,-4 }, game->GetPlayer()->GetPos()).vector().norm() * 24 * 3.f, 2, GetAttack(),upperLevel,false, { 75 / 2,162 / 2,225 / 2 })));
}
}
}
geom2d::line line(pos,game->GetPlayer().GetPos());
geom2d::line line(pos,game->GetPlayer()->GetPos());
if(targetAcquireTimer==0&&queueShotTimer==0){
targetAcquireTimer=1;
if(line.length()<24*6){

@ -10,6 +10,7 @@ INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
INCLUDE_ANIMATION_DATA
INCLUDE_SPAWNER_LIST
INCLUDE_BULLET_LIST
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_CLASS_DATA
INCLUDE_game
@ -19,15 +20,6 @@ const float Player::GROUND_SLAM_SPIN_TIME=0.6f;
Player::Player():
state(State::NORMAL),lastReleasedMovementKey(DOWN),facingDirection(DOWN){}
void Player::ChangeClass(Class cl){
this->cl=CLASS_DATA[cl]->cl;
rightClickAbility=CLASS_DATA[cl]->rightClickAbility;
ability1=CLASS_DATA[cl]->ability1;
ability2=CLASS_DATA[cl]->ability2;
ability3=CLASS_DATA[cl]->ability3;
UpdateIdleAnimation(DOWN);
}
bool Player::SetX(float x){
vf2d newPos={x,pos.y};
vi2d tilePos=vi2d(newPos/24)*24;
@ -158,6 +150,11 @@ State Player::GetState(){
}
void Player::Update(float fElapsedTime){
Ability&rightClickAbility=GetRightClickAbility(),
ability1=GetAbility1(),
ability2=GetAbility2(),
ability3=GetAbility3(),
ability4=GetAbility4();
attack_cooldown_timer=std::max(0.f,attack_cooldown_timer-fElapsedTime);
iframe_time=std::max(0.f,iframe_time-fElapsedTime);
notEnoughManaDisplay.second=std::max(0.f,notEnoughManaDisplay.second-fElapsedTime);
@ -176,7 +173,7 @@ void Player::Update(float fElapsedTime){
}
}
//Class-specific update events.
CLASS_DATA[cl]->Update(fElapsedTime);
Update(fElapsedTime);
switch(state){
case SPIN:{
switch(facingDirection){
@ -288,11 +285,10 @@ void Player::Update(float fElapsedTime){
SetY(newY);
}
if(attack_cooldown_timer==0&&game->GetMouse(0).bHeld){
CLASS_DATA[cl]->AutoAttack();
AutoAttack();
}
if(ability1.cooldown==0&&GetMana()>=ability1.manaCost&&game->GetKey(SHIFT).bHeld){
if(CLASS_DATA[cl]->Ability1()){
if(ability1.action()){
ability1.cooldown=ability1.COOLDOWN_TIME;
mana-=ability1.manaCost;
}
@ -302,7 +298,7 @@ void Player::Update(float fElapsedTime){
notEnoughManaDisplay={ability1.name,1};
}
if(ability2.cooldown==0&&GetMana()>=ability2.manaCost&&game->GetKey(SPACE).bPressed){
if(CLASS_DATA[cl]->Ability2()){
if(ability2.action()){
ability2.cooldown=ability2.COOLDOWN_TIME;
mana-=ability2.manaCost;
}
@ -311,7 +307,7 @@ void Player::Update(float fElapsedTime){
notEnoughManaDisplay={ability2.name,1};
}
if(ability3.cooldown==0&&GetMana()>=ability3.manaCost&&game->GetKey(CTRL).bPressed){
if(CLASS_DATA[cl]->Ability3()){
if(ability3.action()){
ability3.cooldown=ability3.COOLDOWN_TIME;
mana-=ability3.manaCost;
}
@ -320,7 +316,7 @@ void Player::Update(float fElapsedTime){
notEnoughManaDisplay={ability3.name,1};
}
if(rightClickAbility.cooldown==0&&GetMana()>=rightClickAbility.manaCost&&game->GetMouse(1).bHeld){
if(CLASS_DATA[cl]->RightClickAbility()){
if(rightClickAbility.action()){
rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
mana-=rightClickAbility.manaCost;
}
@ -328,6 +324,30 @@ void Player::Update(float fElapsedTime){
if(rightClickAbility.cooldown==0&&GetMana()<rightClickAbility.manaCost&&game->GetMouse(1).bPressed){
notEnoughManaDisplay={rightClickAbility.name,1};
}
switch(GetState()){
case SWING_SWORD:{
switch(GetFacingDirection()){
case UP:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
}break;
case DOWN:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
}break;
case LEFT:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
}break;
case RIGHT:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
}break;
}
SetSwordSwingTimer(GetSwordSwingTimer()-fElapsedTime);
if(GetSwordSwingTimer()<=0){
SetSwordSwingTimer(0);
SetState(State::NORMAL);
}
}break;
}
}
float Player::GetSwordSwingTimer(){
@ -413,13 +433,6 @@ void Player::Moved(){
}
}
float Player::GetAbility2Cooldown(){
return ability2.cooldown;
}
float Player::GetRightClickCooldown(){
return rightClickAbility.cooldown;
}
void Player::Spin(float duration,float spinSpd){
state=State::SPIN;
spin_attack_timer=duration;
@ -430,10 +443,10 @@ void Player::Spin(float duration,float spinSpd){
void Player::UpdateWalkingAnimation(Key direction){
AnimationState anim;
switch(direction){
case UP:anim=CLASS_DATA[cl]->walk_n;break;
case RIGHT:anim=CLASS_DATA[cl]->walk_e;break;
case DOWN:anim=CLASS_DATA[cl]->walk_s;break;
case LEFT:anim=CLASS_DATA[cl]->walk_w;break;
case UP:anim=GetWalkNAnimation();break;
case RIGHT:anim=GetWalkEAnimation();break;
case DOWN:anim=GetWalkSAnimation();break;
case LEFT:anim=GetWalkWAnimation();break;
}
UpdateAnimation(anim);
}
@ -441,10 +454,10 @@ void Player::UpdateWalkingAnimation(Key direction){
void Player::UpdateIdleAnimation(Key direction){
AnimationState anim;
switch(direction){
case UP:anim=CLASS_DATA[cl]->idle_n;break;
case RIGHT:anim=CLASS_DATA[cl]->idle_e;break;
case DOWN:anim=CLASS_DATA[cl]->idle_s;break;
case LEFT:anim=CLASS_DATA[cl]->idle_w;break;
case UP:anim=GetIdleNAnimation();break;
case RIGHT:anim=GetIdleEAnimation();break;
case DOWN:anim=GetIdleSAnimation();break;
case LEFT:anim=GetIdleWAnimation();break;
}
UpdateAnimation(anim);
}

@ -16,40 +16,27 @@ struct Player{
int mana=100,maxmana=mana;
int atk=10;
vf2d pos;
vf2d vel={0,0};
float friction=400;
float z=0;
float moveSpd=1.0f;
float size=1.0f;
float attack_range=1.5f;
Ability rightClickAbility,ability1,ability2,ability3;
const float ATTACK_COOLDOWN=0.35f;
const float MAGIC_ATTACK_COOLDOWN=0.85f;
float attack_cooldown_timer=0;
float spin_attack_timer=0;
float spin_spd=0;
float spin_angle=0;
float lastAnimationFlip=0;
float swordSwingTimer=0;
float iframe_time=0;
float manaTickTimer=0;
float teleportAnimationTimer=0;
vf2d teleportTarget={};
vf2d teleportStartPosition={};
std::pair<std::string,float> notEnoughManaDisplay={"",0};
std::pair<std::string,float> notificationDisplay={"",0};
float teleportAttemptWaitTime=0; //If a teleport fails, we wait awhile before trying again, it's expensive.
State state=State::NORMAL;
Animate2D::Animation<AnimationState>animation;
Animate2D::AnimationState internal_animState;
Key lastReleasedMovementKey;
Key facingDirection;
bool upperLevel=false;
void AddAnimation(AnimationState state);
void Update(float fElapsedTime);
void ChangeClass(Class cl);
std::vector<Buff>buffList;
protected:
const float ATTACK_COOLDOWN=0.35f;
const float MAGIC_ATTACK_COOLDOWN=0.85f;
void SetSwordSwingTimer(float val);
void SetState(State newState);
void SetFacingDirection(Key direction);
@ -62,6 +49,17 @@ protected:
void SetZ(float z);
//Returns true if the move was valid and successful.
bool SetPos(vf2d pos);
float attack_cooldown_timer=0;
float iframe_time=0;
float teleportAnimationTimer=0;
vf2d teleportTarget={};
vf2d teleportStartPosition={};
std::pair<std::string,float> notificationDisplay={"",0};
bool upperLevel=false;
vf2d vel={0,0};
float attack_range=1.5f;
Key facingDirection;
float swordSwingTimer=0;
public:
Player();
const static float GROUND_SLAM_SPIN_TIME;
@ -97,17 +95,48 @@ public:
Key GetLastReleasedMovementKey();
float GetSwordSwingTimer();
bool OnUpperLevel();
float GetAbility2Cooldown();
float GetRightClickCooldown();
//Triggers when the player has moved.
void Moved();
virtual ~Player()=default;
virtual Class GetClass();
virtual bool AutoAttack();
virtual bool Ability1();
virtual bool Ability2();
virtual bool Ability3();
virtual bool RightClickAbility();
virtual Class GetClass()=0;
virtual bool AutoAttack()=0;
virtual void InitializeClassAbilities()=0;
virtual std::string GetClassName()=0;
virtual Ability&GetRightClickAbility()=0;
virtual Ability&GetAbility1()=0;
virtual Ability&GetAbility2()=0;
virtual Ability&GetAbility3()=0;
virtual Ability&GetAbility4()=0;
virtual AnimationState GetWalkNAnimation()=0;
virtual AnimationState GetWalkEAnimation()=0;
virtual AnimationState GetWalkSAnimation()=0;
virtual AnimationState GetWalkWAnimation()=0;
virtual AnimationState GetIdleNAnimation()=0;
virtual AnimationState GetIdleEAnimation()=0;
virtual AnimationState GetIdleSAnimation()=0;
virtual AnimationState GetIdleWAnimation()=0;
};
struct Warrior:Player{
static std::string name;
static Class cl;
static Ability rightClickAbility,ability1,ability2,ability3,ability4;
static AnimationState walk_n,walk_e,walk_s,walk_w,idle_n,idle_e,idle_s,idle_w;
Class GetClass()override;
bool AutoAttack()override;
void InitializeClassAbilities()override;
std::string GetClassName()override;
Ability&GetRightClickAbility()override;
Ability&GetAbility1()override;
Ability&GetAbility2()override;
Ability&GetAbility3()override;
Ability&GetAbility4()override;
AnimationState GetWalkNAnimation()override;
AnimationState GetWalkEAnimation()override;
AnimationState GetWalkSAnimation()override;
AnimationState GetWalkWAnimation()override;
AnimationState GetIdleNAnimation()override;
AnimationState GetIdleEAnimation()override;
AnimationState GetIdleSAnimation()override;
AnimationState GetIdleWAnimation()override;
};

@ -0,0 +1,126 @@
#include "Class.h"
#include "olcPixelGameEngine.h"
#include "DEFINES.h"
#include "Player.h"
#include "Effect.h"
#include "Crawler.h"
INCLUDE_MONSTER_LIST
INCLUDE_BULLET_LIST
INCLUDE_game
std::string Warrior::name="Warrior";
Class Warrior::cl=WARRIOR;
Ability Warrior::rightClickAbility={"Block",15,0,VERY_DARK_BLUE,DARK_BLUE};
Ability Warrior::ability1={"Battlecry",12,40};
Ability Warrior::ability2={"Ground Slam",15,50};
Ability Warrior::ability3={"Sonic Slash",40,60};
Ability Warrior::ability4={"???",0,0};
SETUP_CLASS(Warrior)
bool Warrior::AutoAttack(){
if(GetState()!=State::SPIN){
bool attack=false;
Monster*closest=nullptr;
float closest_dist=999999;
for(Monster&m:MONSTER_LIST){
if(m.IsAlive()
&&m.OnUpperLevel()==OnUpperLevel()
&&geom2d::overlaps(geom2d::circle<float>(GetPos()-vf2d{GetSizeMult()*12,GetSizeMult()*12},attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12))
&&geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length()<closest_dist){
closest_dist=geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length();
closest=&m;
}
}
if(closest!=nullptr&&closest->Hurt(GetAttack())){
attack_cooldown_timer=ATTACK_COOLDOWN;
swordSwingTimer=0.2;
SetState(State::SWING_SWORD);
switch(facingDirection){
case DOWN:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
}break;
case RIGHT:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
}break;
case LEFT:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
}break;
case UP:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
}break;
}
}
}
return true;
}
void Warrior::InitializeClassAbilities(){
#pragma region Warrior Right-click Ability (Block)
Warrior::rightClickAbility.action=
[&](){
if(GetState()==State::NORMAL){
rightClickAbility.cooldown=rightClickAbility.COOLDOWN_TIME;
SetState(State::BLOCK);
AddBuff(BuffType::SLOWDOWN,3,0.3);
return true;
}
return false;
};
#pragma endregion
#pragma region Warrior Ability 1 (Battlecry)
Warrior::ability1.action=
[&](){
game->AddEffect(std::make_unique<Effect>(GetPos(),0.1,AnimationState::BATTLECRY_EFFECT,upperLevel,1,0.3));
AddBuff(BuffType::ATTACK_UP,10,0.1);
AddBuff(BuffType::DAMAGE_REDUCTION,10,0.1);
for(Monster&m:MONSTER_LIST){
if(m.GetSizeMult()<=1&&geom2d::overlaps(geom2d::circle<float>(GetPos(),12*3.5),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
m.AddBuff(BuffType::SLOWDOWN,5,0.3);
}
}
return true;
};
#pragma endregion
#pragma region Warrior Ability 2 (Ground Slam)
Warrior::ability2.action=
[&](){
Spin(GROUND_SLAM_SPIN_TIME,14*PI);
iframe_time=GROUND_SLAM_SPIN_TIME+0.1;
return true;
};
#pragma endregion
#pragma region Warrior Ability 3 (Sonic Slash)
Warrior::ability3.action=
[&](){
SetState(State::SWING_SONIC_SWORD);
AddBuff(BuffType::SLOWDOWN,0.5,1);
vf2d bulletVel={};
switch(GetFacingDirection()){
case UP:{
vel.y=70;
bulletVel.y=-400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
}break;
case LEFT:{
vel.x=70;
bulletVel.x=-400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
}break;
case RIGHT:{
vel.x=-70;
bulletVel.x=400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
}break;
case DOWN:{
vel.y=-70;
bulletVel.y=400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
}break;
}
BULLET_LIST.push_back(std::make_unique<Bullet>(GetPos(),bulletVel,30,GetAttack()*8,AnimationState::SONICSLASH,upperLevel,true,2.25,true,true,WHITE));
game->SetupWorldShake(0.5);
return true;
};
#pragma endregion
}
Loading…
Cancel
Save