#include "olcPGEX_TransformedView.h" #include "Crawler.h" #include "olcUTIL_Camera2D.h" #include "DamageNumber.h" #include "Bullet.h" #include "Ability.h" #include "Class.h" #include "Version.h" #include "TMXParser.h" #include "TSXParser.h" #include "Map.h" #include "DEFINES.h" //192x192 const vi2d WINDOW_SIZE={24*15,24*10}; std::mapANIMATION_DATA; std::vectorMONSTER_LIST; std::vectorSPAWNER_LIST; std::vectorDAMAGENUMBER_LIST; std::vectorBULLET_LIST; std::vectorPLAYER_BULLET_LIST; Crawler*game; Crawler::Crawler() { sAppName = "Crawler Concept"; game=this; } bool Crawler::OnUserCreate(){ InitializeLevel("assets/maps/Level1.tmx",LEVEL1); InitializeLevel("assets/maps/Level2.tmx",LEVEL2); InitializeLevel("assets/Campaigns/1_1_test.tmx",CAMPAIGN_1_1); //Initialize Camera. camera=Camera2D{WINDOW_SIZE}; camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow); camera.SetTarget(player.GetPos()); camera.SetWorldBoundary({0,0},WORLD_SIZE*24); camera.EnableWorldBoundary(false); //Graphics GFX_Warrior_Sheet.Load("assets/nico-warrior.png"); GFX_Slime_Sheet.Load("assets/slime.png"); GFX_Circle.Load("assets/circle.png"); GFX_Effect_GroundSlam_Back.Load("assets/ground-slam-attack-back.png"); GFX_Effect_GroundSlam_Front.Load("assets/ground-slam-attack-front.png"); GFX_Heart.Load("assets/heart.png"); GFX_BLOCK_BUBBLE.Load("assets/block.png"); GFX_Ranger_Sheet.Load("assets/nico-ranger.png"); GFX_Wizard_Sheet.Load("assets/nico-wizard.png"); GFX_Battlecry_Effect.Load("assets/battlecry_effect.png"); GFX_Mana.Load("assets/mana.png"); GFX_SonicSlash.Load("assets/sonicslash.png"); GFX_BulletCircle.Load("assets/circle.png"); GFX_BulletCircleOutline.Load("assets/circle_outline.png"); GFX_EnergyBolt.Load("assets/energy_bolt.png"); GFX_EnergyParticle.Load("assets/energy_particle.png"); //Animations InitializeAnimations(); player.AddAnimation(AnimationState::WARRIOR_WALK_N); player.AddAnimation(AnimationState::WARRIOR_WALK_E); player.AddAnimation(AnimationState::WARRIOR_WALK_S); player.AddAnimation(AnimationState::WARRIOR_WALK_W); player.AddAnimation(AnimationState::WARRIOR_IDLE_N); player.AddAnimation(AnimationState::WARRIOR_IDLE_E); player.AddAnimation(AnimationState::WARRIOR_IDLE_S); player.AddAnimation(AnimationState::WARRIOR_IDLE_W); player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E); player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S); player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N); player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W); player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E); player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S); player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N); player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W); player.AddAnimation(AnimationState::RANGER_WALK_N); player.AddAnimation(AnimationState::RANGER_WALK_E); player.AddAnimation(AnimationState::RANGER_WALK_S); player.AddAnimation(AnimationState::RANGER_WALK_W); player.AddAnimation(AnimationState::RANGER_IDLE_N); player.AddAnimation(AnimationState::RANGER_IDLE_E); player.AddAnimation(AnimationState::RANGER_IDLE_S); player.AddAnimation(AnimationState::RANGER_IDLE_W); player.AddAnimation(AnimationState::WIZARD_WALK_N); player.AddAnimation(AnimationState::WIZARD_WALK_E); player.AddAnimation(AnimationState::WIZARD_WALK_S); player.AddAnimation(AnimationState::WIZARD_WALK_W); player.AddAnimation(AnimationState::WIZARD_IDLE_N); player.AddAnimation(AnimationState::WIZARD_IDLE_E); player.AddAnimation(AnimationState::WIZARD_IDLE_S); player.AddAnimation(AnimationState::WIZARD_IDLE_W); player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N); player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E); player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S); player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W); player.AddAnimation(AnimationState::WIZARD_ATTACK_N); player.AddAnimation(AnimationState::WIZARD_ATTACK_E); player.AddAnimation(AnimationState::WIZARD_ATTACK_S); player.AddAnimation(AnimationState::WIZARD_ATTACK_W); view=TileTransformedView{GetScreenSize(),{1,1}}; player.SetClass(WARRIOR); player.SetPos({4*24,4*24}); LoadLevel(CAMPAIGN_1_1); return true; } bool Crawler::OnUserUpdate(float fElapsedTime){ HandleUserInput(fElapsedTime); UpdateEffects(fElapsedTime); player.Update(fElapsedTime); for(Monster&m:MONSTER_LIST){ m.Update(fElapsedTime); } UpdateBullets(fElapsedTime); UpdateCamera(fElapsedTime); RenderWorld(fElapsedTime); RenderHud(); return true; } void Crawler::InitializeAnimations(){ //Warrior animations. Animate2D::FrameSequence pl_warrior_walk_s{0.2}; pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,0}*24,{24,24}}}); pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_WALK_S]=pl_warrior_walk_s; Animate2D::FrameSequence pl_warrior_walk_e{0.2}; pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,3}*24,{24,24}}}); pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_WALK_E]=pl_warrior_walk_e; Animate2D::FrameSequence pl_warrior_walk_w{0.2}; pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,2}*24,{24,24}}}); pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_WALK_W]=pl_warrior_walk_w; Animate2D::FrameSequence pl_warrior_walk_n{0.2}; pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,1}*24,{24,24}}}); pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_WALK_N]=pl_warrior_walk_n; Animate2D::FrameSequence pl_warrior_idle_s; pl_warrior_idle_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_IDLE_S]=pl_warrior_idle_s; Animate2D::FrameSequence pl_warrior_idle_e; pl_warrior_idle_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_IDLE_E]=pl_warrior_idle_e; Animate2D::FrameSequence pl_warrior_idle_w; pl_warrior_idle_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_IDLE_W]=pl_warrior_idle_w; Animate2D::FrameSequence pl_warrior_idle_n; pl_warrior_idle_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WARRIOR_IDLE_N]=pl_warrior_idle_n; Animate2D::FrameSequence pl_warrior_swing_s(0.05),pl_warrior_swing_n(0.05),pl_warrior_swing_e(0.05),pl_warrior_swing_w(0.05); Animate2D::FrameSequence pl_warrior_sonic_swing_s(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_n(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_e(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_w(0.1,Animate2D::Style::OneShot); for (int i=0;i<4;i++){ pl_warrior_swing_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,0}*24,{24,24}}}); pl_warrior_sonic_swing_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,4}*24,{24,24}}}); } for (int i=0;i<4;i++){ pl_warrior_swing_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,1}*24,{24,24}}}); pl_warrior_sonic_swing_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,5}*24,{24,24}}}); } for (int i=0;i<4;i++){ pl_warrior_swing_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,2}*24,{24,24}}}); pl_warrior_sonic_swing_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,6}*24,{24,24}}}); } for (int i=0;i<4;i++){ pl_warrior_swing_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,3}*24,{24,24}}}); pl_warrior_sonic_swing_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,7}*24,{24,24}}}); } ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_N]=pl_warrior_swing_n; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_E]=pl_warrior_swing_e; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_S]=pl_warrior_swing_s; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_W]=pl_warrior_swing_w; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_N]=pl_warrior_sonic_swing_n; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_E]=pl_warrior_sonic_swing_e; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_S]=pl_warrior_sonic_swing_s; ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_W]=pl_warrior_sonic_swing_w; //Ranger animations Animate2D::FrameSequence pl_ranger_walk_s{0.2}; pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,0}*24,{24,24}}}); pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_WALK_S]=pl_ranger_walk_s; Animate2D::FrameSequence pl_ranger_walk_e{0.2}; pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,3}*24,{24,24}}}); pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_WALK_E]=pl_ranger_walk_e; Animate2D::FrameSequence pl_ranger_walk_w{0.2}; pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,2}*24,{24,24}}}); pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_WALK_W]=pl_ranger_walk_w; Animate2D::FrameSequence pl_ranger_walk_n{0.2}; pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,1}*24,{24,24}}}); pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_WALK_N]=pl_ranger_walk_n; Animate2D::FrameSequence pl_ranger_idle_s; pl_ranger_idle_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_IDLE_S]=pl_ranger_idle_s; Animate2D::FrameSequence pl_ranger_idle_e; pl_ranger_idle_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_IDLE_E]=pl_ranger_idle_e; Animate2D::FrameSequence pl_ranger_idle_w; pl_ranger_idle_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_IDLE_W]=pl_ranger_idle_w; Animate2D::FrameSequence pl_ranger_idle_n; pl_ranger_idle_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::RANGER_IDLE_N]=pl_ranger_idle_n; //Wizard animations Animate2D::FrameSequence pl_wizard_walk_s{0.2}; pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,0}*24,{24,24}}}); pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_WALK_S]=pl_wizard_walk_s; Animate2D::FrameSequence pl_wizard_walk_e{0.2}; pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,3}*24,{24,24}}}); pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_WALK_E]=pl_wizard_walk_e; Animate2D::FrameSequence pl_wizard_walk_w{0.2}; pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,2}*24,{24,24}}}); pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_WALK_W]=pl_wizard_walk_w; Animate2D::FrameSequence pl_wizard_walk_n{0.2}; pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,1}*24,{24,24}}}); pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_WALK_N]=pl_wizard_walk_n; Animate2D::FrameSequence pl_wizard_idle_s; pl_wizard_idle_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_S]=pl_wizard_idle_s; Animate2D::FrameSequence pl_wizard_idle_e; pl_wizard_idle_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_E]=pl_wizard_idle_e; Animate2D::FrameSequence pl_wizard_idle_w; pl_wizard_idle_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_W]=pl_wizard_idle_w; Animate2D::FrameSequence pl_wizard_idle_n; pl_wizard_idle_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_N]=pl_wizard_idle_n; Animate2D::FrameSequence pl_wizard_idle_attack_s; pl_wizard_idle_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_S]=pl_wizard_idle_attack_s; Animate2D::FrameSequence pl_wizard_idle_attack_e; pl_wizard_idle_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_E]=pl_wizard_idle_attack_e; Animate2D::FrameSequence pl_wizard_idle_attack_w; pl_wizard_idle_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_W]=pl_wizard_idle_attack_w; Animate2D::FrameSequence pl_wizard_idle_attack_n; pl_wizard_idle_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_N]=pl_wizard_idle_attack_n; Animate2D::FrameSequence pl_wizard_attack_s(0.2); for(int i=0;i<3;i++){ pl_wizard_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4+i,0}*24,{24,24}}}); if(i==1){ pl_wizard_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}}); } } ANIMATION_DATA[AnimationState::WIZARD_ATTACK_S]=pl_wizard_attack_s; Animate2D::FrameSequence pl_wizard_attack_e(0.2); for(int i=0;i<3;i++){ pl_wizard_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4+i,3}*24,{24,24}}}); if(i==1){ pl_wizard_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}}); } } ANIMATION_DATA[AnimationState::WIZARD_ATTACK_E]=pl_wizard_attack_e; Animate2D::FrameSequence pl_wizard_attack_w(0.2); for(int i=0;i<3;i++){ pl_wizard_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4+i,2}*24,{24,24}}}); if(i==1){ pl_wizard_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}}); } } ANIMATION_DATA[AnimationState::WIZARD_ATTACK_W]=pl_wizard_attack_w; Animate2D::FrameSequence pl_wizard_attack_n(0.2); for(int i=0;i<3;i++){ pl_wizard_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4+i,1}*24,{24,24}}}); if(i==1){ pl_wizard_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}}); } } ANIMATION_DATA[AnimationState::WIZARD_ATTACK_N]=pl_wizard_attack_n; //Load slime animations. for(int slime=0;slime<4;slime++){ for(int state=0;state<5;state++){ Animate2D::FrameSequence anim; if(state==4){//These are death animations. anim=Animate2D::FrameSequence(0.1f,Animate2D::Style::OneShot); } if(state==2){//These are death animations. anim=Animate2D::FrameSequence(0.06f); } for (int frame=0;frame<10;frame++){ anim.AddFrame({&GFX_Slime_Sheet,{vi2d{frame,state+5*slime}*24,{24,24}}}); } ANIMATION_DATA[AnimationState(AnimationState::GREEN_SLIME_IDLE+state+slime*5)]=anim; } } Animate2D::FrameSequence effect_groundslam_back(0.02f,Animate2D::Style::OneShot),effect_groundslam_front(0.02f,Animate2D::Style::OneShot); for(int i=0;i<5;i++){ effect_groundslam_back.AddFrame({&GFX_Effect_GroundSlam_Back,{{i*64,0},{64,64}}}); effect_groundslam_front.AddFrame({&GFX_Effect_GroundSlam_Front,{{i*64,0},{64,64}}}); } ANIMATION_DATA[AnimationState::GROUND_SLAM_ATTACK_BACK]=effect_groundslam_back; ANIMATION_DATA[AnimationState::GROUND_SLAM_ATTACK_FRONT]=effect_groundslam_front; Animate2D::FrameSequence battlecry_effect(0.02f,Animate2D::Style::OneShot); for(int i=0;i<5;i++){ battlecry_effect.AddFrame({&GFX_Battlecry_Effect,{{i*84,0},{84,84}}}); } ANIMATION_DATA[AnimationState::BATTLECRY_EFFECT]=battlecry_effect; Animate2D::FrameSequence sonicslash_effect(0.04f,Animate2D::Style::OneShot); for(int i=0;i<4;i++){ sonicslash_effect.AddFrame({&GFX_SonicSlash,{{i*60,0},{60,60}}}); } ANIMATION_DATA[AnimationState::SONICSLASH]=sonicslash_effect; Animate2D::FrameSequence energy_bolt; energy_bolt.AddFrame({&GFX_EnergyBolt,{{0,0},{24,24}}}); ANIMATION_DATA[AnimationState::ENERGY_BOLT]=energy_bolt; Animate2D::FrameSequence energy_particle; for(int i=0;i<3;i++){ energy_particle.AddFrame({&GFX_EnergyParticle,{{i*3,0},{3,3}}}); } ANIMATION_DATA[AnimationState::ENERGY_PARTICLE]=energy_particle; } bool Crawler::LeftHeld(){ return GetKey(LEFT).bHeld||GetKey(A).bHeld; } bool Crawler::RightHeld(){ return GetKey(RIGHT).bHeld||GetKey(D).bHeld; } bool Crawler::UpHeld(){ return GetKey(UP).bHeld||GetKey(W).bHeld; } bool Crawler::DownHeld(){ return GetKey(DOWN).bHeld||GetKey(S).bHeld; } bool Crawler::LeftReleased(){ return GetKey(LEFT).bReleased||GetKey(A).bReleased; } bool Crawler::RightReleased(){ return GetKey(RIGHT).bReleased||GetKey(D).bReleased; } bool Crawler::UpReleased(){ return GetKey(UP).bReleased||GetKey(W).bReleased; } bool Crawler::DownReleased(){ return GetKey(DOWN).bReleased||GetKey(S).bReleased; } void Crawler::HandleUserInput(float fElapsedTime){ bool setIdleAnimation=true; if(GetMouseWheel()>0){ switch(player.cl){ case WARRIOR:{ player.SetClass(RANGER); }break; case RANGER:{ player.SetClass(WIZARD); }break; case WIZARD:{ player.SetClass(WARRIOR); }break; } } if(GetMouseWheel()<0){ switch(player.cl){ case WARRIOR:{ player.SetClass(WIZARD); }break; case RANGER:{ player.SetClass(WARRIOR); }break; case WIZARD:{ player.SetClass(RANGER); }break; } } if(player.GetVelocity()==vf2d{0,0}){ if(RightHeld()){ player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult()); player.SetFacingDirection(RIGHT); if(player.GetState()==State::NORMAL){ player.UpdateWalkingAnimation(RIGHT); } setIdleAnimation=false; } if(LeftHeld()){ player.SetX(player.GetX()-fElapsedTime*100*player.GetMoveSpdMult()); if(setIdleAnimation){ player.SetFacingDirection(LEFT); if(player.GetState()==State::NORMAL){ player.UpdateWalkingAnimation(LEFT); } } setIdleAnimation=false; } if(UpHeld()){ player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult()); if(setIdleAnimation){ player.SetFacingDirection(UP); if(player.GetState()==State::NORMAL){ player.UpdateWalkingAnimation(UP); } } setIdleAnimation=false; } if(DownHeld()){ player.SetY(player.GetY()+fElapsedTime*100*player.GetMoveSpdMult()); if(setIdleAnimation){ player.SetFacingDirection(DOWN); if(player.GetState()==State::NORMAL){ player.UpdateWalkingAnimation(DOWN); } } setIdleAnimation=false; } } if(UpReleased()){ player.SetLastReleasedMovementKey(UP); if(player.GetState()==State::NORMAL){ if(RightHeld()){ player.UpdateWalkingAnimation(RIGHT); } else if(DownHeld()){ player.UpdateWalkingAnimation(DOWN); } else if(LeftHeld()){ player.UpdateWalkingAnimation(LEFT); } } } if(RightReleased()){ player.SetLastReleasedMovementKey(RIGHT); if(player.GetState()==State::NORMAL){ if(UpHeld()){ player.UpdateWalkingAnimation(UP); } else if(DownHeld()){ player.UpdateWalkingAnimation(DOWN); } else if(LeftHeld()){ player.UpdateWalkingAnimation(LEFT); } } } if(LeftReleased()){ player.SetLastReleasedMovementKey(LEFT); if(player.GetState()==State::NORMAL){ if(RightHeld()){ player.UpdateWalkingAnimation(RIGHT); } else if(DownHeld()){ player.UpdateWalkingAnimation(DOWN); } else if(UpHeld()){ player.UpdateWalkingAnimation(UP); } } } if(DownReleased()){ player.SetLastReleasedMovementKey(DOWN); if(player.GetState()==State::NORMAL){ if(RightHeld()){ player.UpdateWalkingAnimation(RIGHT); } else if(UpHeld()){ player.UpdateWalkingAnimation(UP); } else if(LeftHeld()){ player.UpdateWalkingAnimation(LEFT); } } } if(player.GetState()==State::SWING_SWORD){ setIdleAnimation=false; switch(player.GetFacingDirection()){ case UP:{ player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N); }break; case DOWN:{ player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S); }break; case LEFT:{ player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W); }break; case RIGHT:{ player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E); }break; } player.SetSwordSwingTimer(player.GetSwordSwingTimer()-fElapsedTime); if(player.GetSwordSwingTimer()<=0){ player.SetSwordSwingTimer(0); player.SetState(State::NORMAL); } } if(player.GetState()!=State::NORMAL){ setIdleAnimation=false; } if(setIdleAnimation){ switch(player.GetLastReleasedMovementKey()){ case UP:{ player.UpdateIdleAnimation(UP); }break; case DOWN:{ player.UpdateIdleAnimation(DOWN); }break; case LEFT:{ player.UpdateIdleAnimation(LEFT); }break; case RIGHT:{ player.UpdateIdleAnimation(RIGHT); }break; default:{ player.UpdateIdleAnimation(DOWN); } } } else { //We have moved. player.Moved(); } } void Crawler::UpdateCamera(float fElapsedTime){ lastWorldShakeAdjust=std::max(0.f,lastWorldShakeAdjust-fElapsedTime); if(worldShakeTime-fElapsedTime>0){ if(lastWorldShakeAdjust==0){ lastWorldShakeAdjust=float(rand()%int(WORLD_SHAKE_ADJUST_MAX_TIME*1000))/1000+0.05; worldShakeVel={float(rand()%1000)/1000*100-50,float(rand()%1000)/1000*100-50}; } worldShake+=worldShakeVel*fElapsedTime; } else { camera.SetTarget(player.GetPos()); } worldShakeTime=std::max(0.f,worldShakeTime-fElapsedTime); camera.Update(fElapsedTime); view.SetWorldOffset(vi2d(camera.GetViewPosition())); } void Crawler::UpdateEffects(float fElapsedTime){ for(std::vector::iterator it=backgroundEffects.begin();it!=backgroundEffects.end();++it){ Effect&e=*it; if(!e.Update(fElapsedTime)){ it=backgroundEffects.erase(it); if(it==backgroundEffects.end()){ break; } } } for(std::vector::iterator it=foregroundEffects.begin();it!=foregroundEffects.end();++it){ Effect&e=*it; if(!e.Update(fElapsedTime)){ it=foregroundEffects.erase(it); if(it==foregroundEffects.end()){ break; } } } } void Crawler::UpdateBullets(float fElapsedTime){ for(std::vector::iterator it=BULLET_LIST.begin();it!=BULLET_LIST.end();++it){ Bullet&b=*it; b.Update(fElapsedTime); b.pos+=b.vel*fElapsedTime; if(geom2d::overlaps(geom2d::circle(player.GetPos(),12*player.GetSizeMult()/2),geom2d::circle(b.pos,b.radius))){ if(player.Hurt(b.damage)){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ break; } } } if(b.pos.xview.GetWorldBR().x||b.pos.yview.GetWorldBR().y){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ break; } } b.lifetime-=fElapsedTime; if(b.lifetime<=0){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ break; } } b.animation.UpdateState(b.internal_animState,fElapsedTime); } for(std::vector::iterator it=PLAYER_BULLET_LIST.begin();it!=PLAYER_BULLET_LIST.end();++it){ Bullet&b=*it; b.Update(fElapsedTime); b.pos+=b.vel*fElapsedTime; for(Monster&m:MONSTER_LIST){ if(geom2d::overlaps(geom2d::circle(m.GetPos(),12*m.GetSizeMult()),geom2d::circle(b.pos,b.radius))){ if(b.hitList.find(&m)==b.hitList.end()&&m.Hurt(b.damage)){ if(!b.hitsMultiple){ it=PLAYER_BULLET_LIST.erase(it); if(it==PLAYER_BULLET_LIST.end()){ goto outsidePlayerBulletLoop; } } b.hitList[&m]=true; } } } if(b.pos.xview.GetWorldBR().x||b.pos.yview.GetWorldBR().y){ it=PLAYER_BULLET_LIST.erase(it); if(it==PLAYER_BULLET_LIST.end()){ break; } } b.lifetime-=fElapsedTime; if(b.lifetime<=0){ it=PLAYER_BULLET_LIST.erase(it); if(it==PLAYER_BULLET_LIST.end()){ break; } } b.animation.UpdateState(b.internal_animState,fElapsedTime); } outsidePlayerBulletLoop: int a; } void Crawler::HurtEnemies(vf2d pos,float radius,int damage){ for(Monster&m:MONSTER_LIST){ if(geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m.GetPos(),12*m.GetSizeMult()))){ m.Hurt(damage); } } } void Crawler::RenderWorld(float fElapsedTime){ Clear({100,180,100}); for (int x = view.GetTopLeftTile().x/24-1; x <= view.GetBottomRightTile().x/24; x++){ for (int y = view.GetTopLeftTile().y/24-1; y <= view.GetBottomRightTile().y/24; y++){ if(x>=0&&x=0&&ySprite()->width/24; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24; int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth; if(!IsForegroundTile(tileSheet,tileSheetIndex)){ view.DrawPartialDecal(vi2d{x,y}*24,{24,24},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24}); } if(tileSheet.tileset.collision.find(tileSheetIndex)!=tileSheet.tileset.collision.end()){ geom2d::rectcollision=tileSheet.tileset.collision[tileSheetIndex].collision; view.FillRectDecal(vi2d{x,y}*24+collision.pos,collision.size,{0,0,0,128}); view.DrawRectDecal(vi2d{x,y}*24+collision.pos,collision.size,GREY); } } } } } } //DrawDecal({0,0},MAP_TILESETS["assets/maps/"+MAP_DATA[LEVEL1].TilesetData[1].data["source"]]->Decal()); std::vectormonstersBefore,monstersAfter; Player&pl=player; std::copy_if(MONSTER_LIST.begin(),MONSTER_LIST.end(),std::back_inserter(monstersBefore),[&pl](Monster&m){return m.GetPos().y=pl.GetPos().y;}); std::sort(monstersBefore.begin(),monstersBefore.end(),[](Monster&m1,Monster&m2){return m1.GetPos().y0){ 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:backgroundEffects){ e.Draw(); } for(Monster&m:monstersBefore){ m.Draw(); } view.DrawPartialRotatedDecal(player.GetPos()+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,vf2d(player.GetSizeMult(),player.GetSizeMult()),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.GetState()==State::BLOCK){ view.DrawDecal(player.GetPos()-vf2d{12,12},GFX_BLOCK_BUBBLE.Decal()); } for(Monster&m:monstersAfter){ m.Draw(); } for(Effect&e:foregroundEffects){ e.Draw(); } for(Bullet&b:BULLET_LIST){ b.Draw(); } for(Bullet&b:PLAYER_BULLET_LIST){ b.Draw(); } for(TileGroup&group:foregroundTileGroups){ if(geom2d::overlaps(group.GetRange(),player.pos)){ group.playerBehind=true; } else { group.playerBehind=false; } if(view.IsRectVisible(group.GetRange().pos,group.GetRange().size)){ for(TileRenderData&tile:group.GetTiles()){ view.DrawPartialDecal(tile.pos,{24,24},tile.tileset,tile.tileSheetPos,{24,24},{255,255,255,uint8_t(group.playerBehind?128:255)}); } } } for(std::vector::iterator it=DAMAGENUMBER_LIST.begin();it!=DAMAGENUMBER_LIST.end();++it){ DamageNumber&dn=*it; dn.lifeTime+=fElapsedTime; if(dn.lifeTime>1){ it=DAMAGENUMBER_LIST.erase(it); if(it==DAMAGENUMBER_LIST.end()){ break; } } else { if(dn.lifeTimecapitalize=[](std::string name)->std::string{ std::string newName=""; for(int i=0;i='a'?name[i]-32:name[i]); newName.append(1,' '); } return newName; }; std::vectorcooldowns{ player.rightClickAbility, player.ability1, player.ability2, player.ability3 }; std::vectoractiveCooldowns; std::copy_if(cooldowns.begin(),cooldowns.end(),std::back_inserter(activeCooldowns),[](Ability a){ return a.cooldown>0; }); std::sort(activeCooldowns.begin(),activeCooldowns.end(),[](Ability&a1,Ability&a2){ return a1.cooldown0){ FillRectDecal(vf2d{10,ScreenHeight()-22.f}-vf2d{0,float(offset)},{64,6},BLACK); FillRectDecal(vf2d{11,ScreenHeight()-21.f}-vf2d{0,float(offset)},{62,4},DARK_GREY); GradientFillRectDecal(vf2d{10,ScreenHeight()-22.f}-vf2d{0,float(offset)},{(a.cooldown/a.COOLDOWN_TIME)*64,6},a.barColor1,a.barColor1,a.barColor2,a.barColor2); DrawRotatedShadowStringPropDecal(vf2d{8,ScreenHeight()-20.f}+vf2d{1,1}-vf2d{0,float(offset)},capitalize(a.name),-PI/64,{0,0},WHITE,BLACK,{0.4,0.4},0.5); } offset-=6; } 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()); 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+"!"; DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)}-GetTextSizeProp(displayText)/2,displayText,DARK_RED,VERY_DARK_RED); } 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); } void Crawler::AddEffect(Effect foreground,Effect background){ foregroundEffects.push_back(foreground); backgroundEffects.push_back(background); } void Crawler::AddEffect(Effect foreground,bool back){ if(back){ backgroundEffects.push_back(foreground); } else { foregroundEffects.push_back(foreground); } } vf2d Crawler::GetWorldMousePos(){ return GetMousePos()+view.GetWorldOffset(); } void Crawler::SetupWorldShake(float duration){ worldShakeTime=duration; worldShake=player.GetPos(); camera.SetTarget(worldShake); } void Crawler::InitializeLevel(std::string mapFile,MapName map){ TMXParser level(mapFile); size_t slashMarker = mapFile.find_last_of('/'); std::string baseDir=mapFile.substr(0,slashMarker+1); MAP_DATA[map]=level.GetData(); for(XMLTag&tag:MAP_DATA[map].TilesetData){ size_t slashMarkerSourceDir = tag.data["source"].find_last_of('/'); std::string baseSourceDir=tag.data["source"].substr(slashMarkerSourceDir+1); if(MAP_TILESETS.find("assets/maps/"+baseSourceDir)==MAP_TILESETS.end()){ TSXParser tileset(baseDir+tag.data["source"]); Renderable*r=new Renderable(); MAP_TILESETS["assets/maps/"+baseSourceDir].tileset=r; MAP_TILESETS["assets/maps/"+baseSourceDir].foregroundTiles=tileset.GetData().ForegroundTileData; MAP_TILESETS["assets/maps/"+baseSourceDir].collision=tileset.GetData().CollisionData; r->Load("assets/maps/"+tileset.GetData().ImageData.data["source"]); } } } void Crawler::LoadLevel(MapName map){ SPAWNER_LIST.clear(); foregroundTileGroups.clear(); currentLevel=map; player.SetPos(MAP_DATA[map].MapData.playerSpawnLocation); WORLD_SIZE={MAP_DATA[map].MapData.width,MAP_DATA[map].MapData.height}; for(SpawnerTag&spawner:MAP_DATA[map].SpawnerData){ std::vector>monster_list; vf2d spawnerRadius=vf2d{spawner.ObjectData.GetFloat("width"),spawner.ObjectData.GetFloat("height")}/2; for(XMLTag&property:spawner.properties){ int monsterTypeID=property.GetInteger("value")-1; if(monsterTypeID>=0&&monsterTypeIDSprite()->width/24; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24; int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth; if(IsForegroundTile(tileSheet,tileSheetIndex)){ TileRenderData tile={tileSheet.tileset.tileset->Decal(),vi2d{x,y}*24,vi2d{tileSheetX,tileSheetY}*24}; bool foundGroup=false; for(TileGroup&group:foregroundTileGroups){ if(geom2d::overlaps(geom2d::rect{vi2d{x,y}*24-vi2d{1,1},{26,26}},group.GetRange())){ group.InsertTile(tile); foundGroup=true; break; } } if(!foundGroup){ TileGroup group; group.InsertTile(tile); foregroundTileGroups.push_back(group); } } } } } } } vi2d Crawler::GetWorldSize(){ return WORLD_SIZE; } bool Crawler::IsForegroundTile(TilesheetData sheet,int tileID){ return sheet.tileset.foregroundTiles.find(tileID)!=sheet.tileset.foregroundTiles.end(); } TilesheetData Crawler::GetTileSheet(MapName map,int tileID){ std::vector&tileData=MAP_DATA[map].TilesetData; if(tileData.size()==1){ size_t slashMarkerSourceDir = tileData[0].data["source"].find_last_of('/'); std::string baseSourceDir=tileData[0].data["source"].substr(slashMarkerSourceDir+1); return {MAP_TILESETS["assets/maps/"+baseSourceDir],1}; } else { for (int i=1;iCrawler::GetTileCollision(MapName map,vf2d pos){ for(LayerTag&layer:MAP_DATA[map].LayerData){ int tileID=layer.tiles[int(pos.y)/24][int(pos.x)/24]-1; if(tileID!=-1&&GetTileSheet(map,tileID).tileset.collision.find(tileID)!=GetTileSheet(map,tileID).tileset.collision.end()){ return GetTileSheet(map,tileID).tileset.collision[tileID].collision; } } return {}; } MapName Crawler::GetCurrentLevel(){ return currentLevel; } int main() { Crawler demo; if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4)) demo.Start(); return 0; }