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; float COOLDOWN_TIME=0;
int manaCost=0; int manaCost=0;
Pixel barColor1,barColor2; Pixel barColor1,barColor2;
std::function<bool()>action;
Ability(); Ability();
Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED); 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(){ void sig::Animation::SetupPlayerAnimations(){
game->player.AddAnimation(AnimationState::WARRIOR_WALK_N); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_N);
game->player.AddAnimation(AnimationState::WARRIOR_WALK_E); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_E);
game->player.AddAnimation(AnimationState::WARRIOR_WALK_S); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_S);
game->player.AddAnimation(AnimationState::WARRIOR_WALK_W); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_WALK_W);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_N); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_N);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_E); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_E);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_S); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_S);
game->player.AddAnimation(AnimationState::WARRIOR_IDLE_W); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_IDLE_W);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
game->player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W); game->GetPlayer()->AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
game->player.AddAnimation(AnimationState::RANGER_WALK_N); game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_N);
game->player.AddAnimation(AnimationState::RANGER_WALK_E); game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_E);
game->player.AddAnimation(AnimationState::RANGER_WALK_S); game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_S);
game->player.AddAnimation(AnimationState::RANGER_WALK_W); game->GetPlayer()->AddAnimation(AnimationState::RANGER_WALK_W);
game->player.AddAnimation(AnimationState::RANGER_IDLE_N); game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_N);
game->player.AddAnimation(AnimationState::RANGER_IDLE_E); game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_E);
game->player.AddAnimation(AnimationState::RANGER_IDLE_S); game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_S);
game->player.AddAnimation(AnimationState::RANGER_IDLE_W); game->GetPlayer()->AddAnimation(AnimationState::RANGER_IDLE_W);
game->player.AddAnimation(AnimationState::WIZARD_WALK_N); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_N);
game->player.AddAnimation(AnimationState::WIZARD_WALK_E); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_E);
game->player.AddAnimation(AnimationState::WIZARD_WALK_S); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_S);
game->player.AddAnimation(AnimationState::WIZARD_WALK_W); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_WALK_W);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_N); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_N);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_E); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_E);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_S); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_S);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_W); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_W);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S);
game->player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_N); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_N);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_E); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_E);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_S); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_S);
game->player.AddAnimation(AnimationState::WIZARD_ATTACK_W); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_ATTACK_W);
game->player.AddAnimation(AnimationState::WIZARD_CAST_N); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_N);
game->player.AddAnimation(AnimationState::WIZARD_CAST_E); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_E);
game->player.AddAnimation(AnimationState::WIZARD_CAST_S); game->GetPlayer()->AddAnimation(AnimationState::WIZARD_CAST_S);
game->player.AddAnimation(AnimationState::WIZARD_CAST_W); 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::MonsterHit(Monster&monster){return true;}
bool Bullet::OnUpperLevel(){return upperLevel;} bool Bullet::OnUpperLevel(){return upperLevel;}

@ -34,7 +34,7 @@ public:
public: public:
virtual void Update(float fElapsedTime); 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. //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. //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); virtual bool MonsterHit(Monster&monster);
Animate2D::Frame GetFrame(); Animate2D::Frame GetFrame();

@ -1,4 +1,4 @@
#include "Class.h"
#include "DEFINES.h" #include "DEFINES.h"
#include "Crawler.h" #include "Crawler.h"
#include "BulletTypes.h" #include "BulletTypes.h"
@ -11,10 +11,10 @@ std::map<Class,std::unique_ptr<ClassData>>CLASS_DATA;
void ClassData::InitializeClassData(){ void ClassData::InitializeClassData(){
CLASS_DATA[WARRIOR]=std::make_unique<Warrior>(Warrior("Warrior",WARRIOR, 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_WALK_N,WARRIOR_WALK_E,WARRIOR_WALK_S,WARRIOR_WALK_W,
WARRIOR_IDLE_N,WARRIOR_IDLE_E,WARRIOR_IDLE_S,WARRIOR_IDLE_W)); WARRIOR_IDLE_N,WARRIOR_IDLE_E,WARRIOR_IDLE_S,WARRIOR_IDLE_W));
CLASS_DATA[RANGER]=std::make_unique<Ranger>(Ranger("Ranger",RANGER, CLASS_DATA[RANGER]=std::make_unique<Ranger>(Ranger("Ranger",RANGER,
@ -24,7 +24,7 @@ void ClassData::InitializeClassData(){
{"Multishot",25,50}, {"Multishot",25,50},
RANGER_WALK_N,RANGER_WALK_E,RANGER_WALK_S,RANGER_WALK_W, RANGER_WALK_N,RANGER_WALK_E,RANGER_WALK_S,RANGER_WALK_W,
RANGER_IDLE_N,RANGER_IDLE_E,RANGER_IDLE_S,RANGER_IDLE_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}, {"???",7,0,VERY_DARK_BLUE,DARK_BLUE},
{"???",12,0}, {"???",12,0},
{"???",15,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) 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, 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) 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, :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){ void Wizard::Update(float fElapsedTime){
ACCESS_PLAYER 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_n=AnimationState::WIZARD_IDLE_ATTACK_N;
CLASS_DATA[cl]->idle_e=AnimationState::WIZARD_IDLE_ATTACK_E; CLASS_DATA[cl]->idle_e=AnimationState::WIZARD_IDLE_ATTACK_E;
CLASS_DATA[cl]->idle_s=AnimationState::WIZARD_IDLE_ATTACK_S; 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_s=AnimationState::WIZARD_WALK_S;
CLASS_DATA[cl]->walk_w=AnimationState::WIZARD_WALK_W; CLASS_DATA[cl]->walk_w=AnimationState::WIZARD_WALK_W;
} }
if(p.GetState()==State::CASTING){ if(p->GetState()==State::CASTING){
switch(p.GetFacingDirection()){ switch(p->GetFacingDirection()){
case UP:{ case UP:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_N); p->UpdateAnimation(AnimationState::WIZARD_CAST_N);
}break; }break;
case DOWN:{ case DOWN:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_S); p->UpdateAnimation(AnimationState::WIZARD_CAST_S);
}break; }break;
case LEFT:{ case LEFT:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_W); p->UpdateAnimation(AnimationState::WIZARD_CAST_W);
}break; }break;
case RIGHT:{ case RIGHT:{
p.UpdateAnimation(AnimationState::WIZARD_CAST_E); p->UpdateAnimation(AnimationState::WIZARD_CAST_E);
}break; }break;
} }
} }
@ -319,56 +193,56 @@ void Wizard::Update(float fElapsedTime){
bool Wizard::AutoAttack(){ bool Wizard::AutoAttack(){
ACCESS_PLAYER ACCESS_PLAYER
p.attack_cooldown_timer=p.MAGIC_ATTACK_COOLDOWN; p->attack_cooldown_timer=p->MAGIC_ATTACK_COOLDOWN;
float angleToCursor=atan2(game->GetWorldMousePos().y-p.pos.y,game->GetWorldMousePos().x-p.pos.x); 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.pos,{cos(angleToCursor)*200,sin(angleToCursor)*200},12,p.GetAttack(),p.upperLevel,true,WHITE))); 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; return true;
} }
bool Wizard::Ability1(){ bool Wizard::Ability1(){
ACCESS_PLAYER ACCESS_PLAYER
float angleToCursor=atan2(game->GetWorldMousePos().y-p.pos.y,game->GetWorldMousePos().x-p.pos.x); 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.pos,{cos(angleToCursor)*275,sin(angleToCursor)*275},12,p.GetAttack(),p.upperLevel,true,{240,120,60}))); 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; return true;
} }
bool Wizard::Ability2(){ bool Wizard::Ability2(){
ACCESS_PLAYER ACCESS_PLAYER
float angleToCursor=atan2(game->GetWorldMousePos().y-p.pos.y,game->GetWorldMousePos().x-p.pos.x); 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.pos,{cos(angleToCursor)*230,sin(angleToCursor)*230},12,p.GetAttack()*4,p.upperLevel,true,WHITE))); 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; return true;
} }
bool Wizard::Ability3(){ bool Wizard::Ability3(){
ACCESS_PLAYER ACCESS_PLAYER
p.SetState(State::CASTING); p->SetState(State::CASTING);
game->AddEffect(std::make_unique<Meteor>(p.GetPos(),3,AnimationState::METEOR,p.OnUpperLevel(),vf2d{1,1},2)); game->AddEffect(std::make_unique<Meteor>(p->GetPos(),3,AnimationState::METEOR,p->OnUpperLevel(),vf2d{1,1},2));
return true; return true;
} }
bool Wizard::RightClickAbility(){ bool Wizard::RightClickAbility(){
ACCESS_PLAYER 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)}; 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; if(dist<12)return false;
vf2d teleportPoint=p.GetPos()+pointTowardsMouse*dist; vf2d teleportPoint=p->GetPos()+pointTowardsMouse*dist;
while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p.CanPathfindTo(p.GetPos(),teleportPoint)){ while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p->CanPathfindTo(p->GetPos(),teleportPoint)){
dist-=24; dist-=24;
teleportPoint=p.GetPos()+pointTowardsMouse*dist; teleportPoint=p->GetPos()+pointTowardsMouse*dist;
} }
if(dist>0&&p.CanPathfindTo(p.GetPos(),teleportPoint)){ if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint)){
p.SetState(State::TELEPORT); p->SetState(State::TELEPORT);
p.teleportAnimationTimer=0.35; p->teleportAnimationTimer=0.35;
p.teleportTarget=teleportPoint; p->teleportTarget=teleportPoint;
p.teleportStartPosition=p.GetPos(); p->teleportStartPosition=p->GetPos();
p.iframe_time=0.35; p->iframe_time=0.35;
for(int i=0;i<16;i++){ 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; return true;
} else { } else {
p.notificationDisplay={"Cannot Teleport to that location!",0.5}; p->notificationDisplay={"Cannot Teleport to that location!",0.5};
return false; return false;
} }
} }

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

@ -20,7 +20,7 @@ class Crawler : public olc::PixelGameEngine
{ {
friend class sig::Animation; friend class sig::Animation;
Camera2D camera; Camera2D camera;
Player player; std::unique_ptr<Player>player;
Renderable GFX_Warrior_Sheet,GFX_Slime_Sheet, Renderable GFX_Warrior_Sheet,GFX_Slime_Sheet,
GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front, GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front,
GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet, GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet,
@ -75,7 +75,7 @@ public:
bool RightReleased(); bool RightReleased();
bool UpReleased(); bool UpReleased();
bool DownReleased(); bool DownReleased();
Player&GetPlayer(); Player*GetPlayer();
void SetupWorldShake(float duration); void SetupWorldShake(float duration);
vi2d GetWorldSize(); vi2d GetWorldSize();
//tileID is the tile number from the tilesets. //tileID is the tile number from the tilesets.
@ -92,4 +92,5 @@ public:
bool IsBridgeLayer(LayerTag&layer); bool IsBridgeLayer(LayerTag&layer);
std::map<std::string,std::vector<geom2d::rect<int>>>&GetZoneData(MapName map); 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 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="Player.cpp" />
<ClCompile Include="Monster.cpp" /> <ClCompile Include="Monster.cpp" />
<ClCompile Include="MonsterData.cpp" /> <ClCompile Include="MonsterData.cpp" />
<ClCompile Include="Warrior.cpp" />
<ClCompile Include="utils.cpp" /> <ClCompile Include="utils.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

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

@ -10,6 +10,15 @@
#define INCLUDE_PARTICLE_LIST extern std::vector<Particle>PARTICLE_LIST; #define INCLUDE_PARTICLE_LIST extern std::vector<Particle>PARTICLE_LIST;
#define INCLUDE_EMITTER_LIST extern std::vector<std::unique_ptr<Emitter>>EMITTER_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 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; if(&m==&monster||monster.OnUpperLevel()!=m.OnUpperLevel())continue;
geom2d::line<float>lineToTarget=geom2d::line<float>(monster.GetPos(),m.GetPos()); geom2d::line<float>lineToTarget=geom2d::line<float>(monster.GetPos(),m.GetPos());
float dist=lineToTarget.length(); float dist=lineToTarget.length();
vf2d vec;
vec.norm();
if(dist<=72){ 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))); 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))); game->AddEffect(std::make_unique<Effect>(m.GetPos(),0.5,AnimationState::LIGHTNING_SPLASH,upperLevel,monster.GetSizeMult(),0.25,vf2d{},WHITE,util::random(PI)));
targetsHit++; 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))){ 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()); geom2d::line line(pos,game->GetPlayer()->GetPos());
float dist = line.length(); float dist = line.length();
SetPosition(line.rpoint(-0.1)); SetPosition(line.rpoint(-0.1));
vel=line.vector().norm()*-128; vel=line.vector().norm()*-128;
} }
if(state==NORMAL){ if(state==NORMAL){
if(game->GetPlayer().GetX()>pos.x){ if(game->GetPlayer()->GetX()>pos.x){
facingDirection=RIGHT; facingDirection=RIGHT;
} else { } else {
facingDirection=LEFT; facingDirection=LEFT;
@ -137,7 +137,7 @@ bool Monster::Update(float fElapsedTime){
targetAcquireTimer=std::max(0.f,targetAcquireTimer-fElapsedTime); targetAcquireTimer=std::max(0.f,targetAcquireTimer-fElapsedTime);
if(targetAcquireTimer==0){ if(targetAcquireTimer==0){
targetAcquireTimer=3; 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; state=MOVE_TOWARDS;
hasHitPlayer=false; hasHitPlayer=false;
} }
@ -169,11 +169,11 @@ bool Monster::Update(float fElapsedTime){
if(queueShotTimer<0){ if(queueShotTimer<0){
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){ if(targetAcquireTimer==0&&queueShotTimer==0){
targetAcquireTimer=1; targetAcquireTimer=1;
if(line.length()<24*6){ if(line.length()<24*6){

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

@ -16,40 +16,27 @@ struct Player{
int mana=100,maxmana=mana; int mana=100,maxmana=mana;
int atk=10; int atk=10;
vf2d pos; vf2d pos;
vf2d vel={0,0};
float friction=400; float friction=400;
float z=0; float z=0;
float moveSpd=1.0f; float moveSpd=1.0f;
float size=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_attack_timer=0;
float spin_spd=0; float spin_spd=0;
float spin_angle=0; float spin_angle=0;
float lastAnimationFlip=0; float lastAnimationFlip=0;
float swordSwingTimer=0;
float iframe_time=0;
float manaTickTimer=0; float manaTickTimer=0;
float teleportAnimationTimer=0;
vf2d teleportTarget={};
vf2d teleportStartPosition={};
std::pair<std::string,float> notEnoughManaDisplay={"",0}; 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. float teleportAttemptWaitTime=0; //If a teleport fails, we wait awhile before trying again, it's expensive.
State state=State::NORMAL; State state=State::NORMAL;
Animate2D::Animation<AnimationState>animation; Animate2D::Animation<AnimationState>animation;
Animate2D::AnimationState internal_animState; Animate2D::AnimationState internal_animState;
Key lastReleasedMovementKey; Key lastReleasedMovementKey;
Key facingDirection;
bool upperLevel=false;
void AddAnimation(AnimationState state); void AddAnimation(AnimationState state);
void Update(float fElapsedTime); void Update(float fElapsedTime);
void ChangeClass(Class cl);
std::vector<Buff>buffList; std::vector<Buff>buffList;
protected: protected:
const float ATTACK_COOLDOWN=0.35f;
const float MAGIC_ATTACK_COOLDOWN=0.85f;
void SetSwordSwingTimer(float val); void SetSwordSwingTimer(float val);
void SetState(State newState); void SetState(State newState);
void SetFacingDirection(Key direction); void SetFacingDirection(Key direction);
@ -62,6 +49,17 @@ protected:
void SetZ(float z); void SetZ(float z);
//Returns true if the move was valid and successful. //Returns true if the move was valid and successful.
bool SetPos(vf2d pos); 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: public:
Player(); Player();
const static float GROUND_SLAM_SPIN_TIME; const static float GROUND_SLAM_SPIN_TIME;
@ -97,17 +95,48 @@ public:
Key GetLastReleasedMovementKey(); Key GetLastReleasedMovementKey();
float GetSwordSwingTimer(); float GetSwordSwingTimer();
bool OnUpperLevel(); bool OnUpperLevel();
float GetAbility2Cooldown();
float GetRightClickCooldown();
//Triggers when the player has moved. //Triggers when the player has moved.
void Moved(); void Moved();
virtual ~Player()=default; virtual ~Player()=default;
virtual Class GetClass(); virtual Class GetClass()=0;
virtual bool AutoAttack(); virtual bool AutoAttack()=0;
virtual bool Ability1(); virtual void InitializeClassAbilities()=0;
virtual bool Ability2(); virtual std::string GetClassName()=0;
virtual bool Ability3(); virtual Ability&GetRightClickAbility()=0;
virtual bool RightClickAbility(); 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