From d3454727cddea0a69856318aa2df06c242d7b4eb Mon Sep 17 00:00:00 2001 From: "sigonasr2, Sig, Sigo" Date: Thu, 13 Jul 2023 20:24:47 +0000 Subject: [PATCH] Warrior refactor completed Co-authored-by: sigonasr2 --- Crawler/Ability.h | 1 + Crawler/Animation.cpp | 88 ++++++------ Crawler/Bullet.cpp | 2 +- Crawler/Bullet.h | 2 +- Crawler/Class.cpp | 196 +++++---------------------- Crawler/Class.h | 6 +- Crawler/Crawler.cpp | 230 ++++++++++++++++++-------------- Crawler/Crawler.h | 5 +- Crawler/Crawler.vcxproj | 1 + Crawler/Crawler.vcxproj.filters | 6 + Crawler/DEFINES.h | 13 +- Crawler/LightningBolt.cpp | 4 +- Crawler/Monster.cpp | 12 +- Crawler/Player.cpp | 75 ++++++----- Crawler/Player.h | 79 +++++++---- Crawler/Warrior.cpp | 126 +++++++++++++++++ 16 files changed, 464 insertions(+), 382 deletions(-) create mode 100644 Crawler/Warrior.cpp diff --git a/Crawler/Ability.h b/Crawler/Ability.h index 0213bf02..85a2f587 100644 --- a/Crawler/Ability.h +++ b/Crawler/Ability.h @@ -8,6 +8,7 @@ struct Ability{ float COOLDOWN_TIME=0; int manaCost=0; Pixel barColor1,barColor2; + std::functionaction; Ability(); Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED); }; \ No newline at end of file diff --git a/Crawler/Animation.cpp b/Crawler/Animation.cpp index 971778f2..72cc5c2c 100644 --- a/Crawler/Animation.cpp +++ b/Crawler/Animation.cpp @@ -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); } \ No newline at end of file diff --git a/Crawler/Bullet.cpp b/Crawler/Bullet.cpp index 7df99dfa..17a28204 100644 --- a/Crawler/Bullet.cpp +++ b/Crawler/Bullet.cpp @@ -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;} \ No newline at end of file diff --git a/Crawler/Bullet.h b/Crawler/Bullet.h index 08acf0a4..25ce5023 100644 --- a/Crawler/Bullet.h +++ b/Crawler/Bullet.h @@ -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(); diff --git a/Crawler/Class.cpp b/Crawler/Class.cpp index 45c42ef2..e924bd2f 100644 --- a/Crawler/Class.cpp +++ b/Crawler/Class.cpp @@ -1,4 +1,4 @@ -#include "Class.h" + #include "DEFINES.h" #include "Crawler.h" #include "BulletTypes.h" @@ -11,10 +11,10 @@ std::map>CLASS_DATA; void ClassData::InitializeClassData(){ CLASS_DATA[WARRIOR]=std::make_unique(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, @@ -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, + CLASS_DATA[TRAPPER]=std::make_unique(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(p.pos-vf2d{p.GetSizeMult()*12,p.GetSizeMult()*12},p.attack_range*p.GetSizeMult()*12),geom2d::circle(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12)) - &&geom2d::line(game->GetWorldMousePos(),m.GetPos()).length()(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(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(p.pos,12*3.5),geom2d::circle(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(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(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(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(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(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(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(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(p.GetPos(),3,AnimationState::METEOR,p.OnUpperLevel(),vf2d{1,1},2)); + p->SetState(State::CASTING); + game->AddEffect(std::make_unique(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{p.GetPos(),game->GetWorldMousePos()}.length(),0.f,6.5f*24); + float dist=std::clamp(geom2d::line{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(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(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; } } diff --git a/Crawler/Class.h b/Crawler/Class.h index d3103d7a..b88846a2 100644 --- a/Crawler/Class.h +++ b/Crawler/Class.h @@ -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); diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index d6832356..37d56521 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -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&monstersBeforeLower,std::vector&monstersBeforeUpper,std::vector&monstersAfterLower,std::vector&monstersAfterUpper,std::vector&bulletsLower,std::vector&bulletsUpper,std::vector&backgroundEffectsLower,std::vector&backgroundEffectsUpper,std::vector&foregroundEffectsLower,std::vector&foregroundEffectsUpper){ - Player&pl=player; + Player*pl=GetPlayer(); for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){ Monster&m=*it; - if(m.GetPos().yGetPos().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::vectormonstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper; std::vectorbulletsLower,bulletsUpper; std::vectorbackgroundEffectsLower,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::vectorcooldowns{ - player.rightClickAbility, - player.ability1, - player.ability2, - player.ability3 + player->rightClickAbility, + player->ability1, + player->ability2, + player->ability3 }; std::vectoractiveCooldowns; 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>>&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; diff --git a/Crawler/Crawler.h b/Crawler/Crawler.h index e9d8ba3e..7bf0c2b9 100644 --- a/Crawler/Crawler.h +++ b/Crawler/Crawler.h @@ -20,7 +20,7 @@ class Crawler : public olc::PixelGameEngine { friend class sig::Animation; Camera2D camera; - Player player; + std::unique_ptrplayer; 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>>&GetZoneData(MapName map); void PopulateRenderLists(std::vector&monstersBeforeLower,std::vector&monstersBeforeUpper,std::vector&monstersAfterLower,std::vector&monstersAfterUpper,std::vector&bulletsLower,std::vector&bulletsUpper,std::vector&backgroundEffectsLower,std::vector&backgroundEffectsUpper,std::vector&foregroundEffectsLower,std::vector&foregroundEffectsUpper); + void ChangePlayerClass(Class cl); }; \ No newline at end of file diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj index 5ede7407..64f4a6a1 100644 --- a/Crawler/Crawler.vcxproj +++ b/Crawler/Crawler.vcxproj @@ -220,6 +220,7 @@ + diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index 6b2a78ff..c2fde05b 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -25,6 +25,9 @@ {94ea6039-63ac-430d-bb96-317bf1b7a305} + + {715c64c5-956a-4ed3-9205-64110409fbea} + @@ -164,6 +167,9 @@ Source Files\Emitters + + Source Files\Player Classes + Source Files diff --git a/Crawler/DEFINES.h b/Crawler/DEFINES.h index 5db4cc4d..e1f5c37a 100644 --- a/Crawler/DEFINES.h +++ b/Crawler/DEFINES.h @@ -10,6 +10,15 @@ #define INCLUDE_PARTICLE_LIST extern std::vectorPARTICLE_LIST; #define INCLUDE_EMITTER_LIST extern std::vector>EMITTER_LIST; -#define ACCESS_PLAYER Player&p=game->GetPlayer(); +#define ACCESS_PLAYER Player*p=game->GetPlayer(); -#define INFINITE 999999 \ No newline at end of file +#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;}; \ No newline at end of file diff --git a/Crawler/LightningBolt.cpp b/Crawler/LightningBolt.cpp index 9452d15c..e7d248b3 100644 --- a/Crawler/LightningBolt.cpp +++ b/Crawler/LightningBolt.cpp @@ -52,8 +52,10 @@ bool LightningBolt::MonsterHit(Monster& monster) if(&m==&monster||monster.OnUpperLevel()!=m.OnUpperLevel())continue; geom2d::linelineToTarget=geom2d::line(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(monster.GetPos(),m.GetPos(),0.05,0.25,upperLevel))); game->AddEffect(std::make_unique(m.GetPos(),0.5,AnimationState::LIGHTNING_SPLASH,upperLevel,monster.GetSizeMult(),0.25,vf2d{},WHITE,util::random(PI))); targetsHit++; diff --git a/Crawler/Monster.cpp b/Crawler/Monster.cpp index bb92d816..e3be35fd 100644 --- a/Crawler/Monster.cpp +++ b/Crawler/Monster.cpp @@ -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(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(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){ diff --git a/Crawler/Player.cpp b/Crawler/Player.cpp index 07dc9a45..e58d7ced 100644 --- a/Crawler/Player.cpp +++ b/Crawler/Player.cpp @@ -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()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); } diff --git a/Crawler/Player.h b/Crawler/Player.h index d8d57c4f..211413ed 100644 --- a/Crawler/Player.h +++ b/Crawler/Player.h @@ -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 notEnoughManaDisplay={"",0}; - std::pair notificationDisplay={"",0}; float teleportAttemptWaitTime=0; //If a teleport fails, we wait awhile before trying again, it's expensive. State state=State::NORMAL; Animate2D::Animationanimation; Animate2D::AnimationState internal_animState; Key lastReleasedMovementKey; - Key facingDirection; - bool upperLevel=false; void AddAnimation(AnimationState state); void Update(float fElapsedTime); - void ChangeClass(Class cl); std::vectorbuffList; 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 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; }; \ No newline at end of file diff --git a/Crawler/Warrior.cpp b/Crawler/Warrior.cpp new file mode 100644 index 00000000..9788ed8f --- /dev/null +++ b/Crawler/Warrior.cpp @@ -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(GetPos()-vf2d{GetSizeMult()*12,GetSizeMult()*12},attack_range*GetSizeMult()*12),geom2d::circle(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12)) + &&geom2d::line(game->GetWorldMousePos(),m.GetPos()).length()(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(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(GetPos(),12*3.5),geom2d::circle(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(GetPos(),bulletVel,30,GetAttack()*8,AnimationState::SONICSLASH,upperLevel,true,2.25,true,true,WHITE)); + game->SetupWorldShake(0.5); + return true; + }; + #pragma endregion +} \ No newline at end of file