#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" #include "utils.h" #include #include INCLUDE_CLASS_DATA //192x192 const vi2d WINDOW_SIZE={24*15,24*10}; std::mapANIMATION_DATA; std::vectorMONSTER_LIST; std::vectorSPAWNER_LIST; std::vectorDAMAGENUMBER_LIST; std::vector>BULLET_LIST; Crawler*game; Crawler::Crawler() { sAppName = "Crawler Concept"; game=this; } bool Crawler::OnUserCreate(){ InitializeLevel("assets/Campaigns/1_1.tmx",CAMPAIGN_1_1); #ifdef OLC_PLATFORM_EMSCRIPTEN ConsoleCaptureStdOut(true); #endif ClassData::InitializeClassData(); //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"); GFX_Splash_Effect.Load("assets/splash_effect.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}}; LoadLevel(CAMPAIGN_1_1); player.SetClass(WARRIOR); return true; } bool Crawler::OnUserUpdate(float fElapsedTime){ fElapsedTime=std::min(1/60.f,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; Animate2D::FrameSequence splash_animation(0.05); for(int i=0;i<5;i++){ splash_animation.AddFrame({&GFX_Splash_Effect,{{i*24,0},{24,24}}}); } ANIMATION_DATA[AnimationState::SPLASH_EFFECT]=splash_animation; Animate2D::FrameSequence dot_particle; dot_particle.AddFrame({&GFX_BulletCircle,{{0,0},{3,3}}}); ANIMATION_DATA[AnimationState::DOT_PARTICLE]=dot_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(GetKey(F1).bPressed){ ConsoleShow(F1); } 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}){ auto GetPlayerStaircaseDirection=[&](){ for(LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){ int truncatedPlayerX=int(player.GetX())/24; int truncatedPlayerY=int(player.GetY())/24; int tileID=layer.tiles[truncatedPlayerY][truncatedPlayerX]; TilesheetData dat=GetTileSheet(GetCurrentLevel(),tileID); if (dat.tileset.staircaseTiles.find(tileID)!=dat.tileset.staircaseTiles.end()){ return dat.tileset.staircaseTiles[tileID].data["value"]; } } return std::string("NONE"); }; std::string staircaseDirection=GetPlayerStaircaseDirection(); if(RightHeld()){ player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult()); if(staircaseDirection=="RIGHT"){ player.SetY(player.GetY()-60*fElapsedTime*player.GetMoveSpdMult()); } else if(staircaseDirection=="LEFT"){ player.SetY(player.GetY()+60*fElapsedTime*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(staircaseDirection=="RIGHT"){ player.SetY(player.GetY()+60*fElapsedTime*player.GetMoveSpdMult()); } else if(staircaseDirection=="LEFT"){ player.SetY(player.GetY()-60*fElapsedTime*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); } } } } void Crawler::UpdateCamera(float fElapsedTime){ lastWorldShakeAdjust=std::max(0.f,lastWorldShakeAdjust-fElapsedTime); if(worldShakeTime-fElapsedTime>0){ if(lastWorldShakeAdjust==0){ lastWorldShakeAdjust=util::random(0.04)+0.01; worldShakeVel={util::random(200)+100,util::random(200)+100}; if(rand()%2==0){ worldShakeVel.x*=-1; } if(rand()%2==0){ worldShakeVel.y*=-1; } } worldShake+=worldShakeVel*fElapsedTime; } else { camera.SetTarget(player.GetPos()); } worldShakeTime=std::max(0.f,worldShakeTime-fElapsedTime); camera.Update(fElapsedTime); view.SetWorldOffset(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(auto it=BULLET_LIST.begin();it!=BULLET_LIST.end();++it){ Bullet*b=(*it).get(); b->UpdateFadeTime(fElapsedTime); b->Update(fElapsedTime); b->pos+=b->vel*fElapsedTime; if(!b->deactivated){ if(b->friendly){ for(Monster&m:MONSTER_LIST){ if(b->OnUpperLevel()==m.OnUpperLevel()&&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){ if(b->MonsterHit(m)){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ goto outsidePlayerBulletLoop; } } goto continuePlayerBulletLoop; } b->hitList[&m]=true; } } } } else { if(b->OnUpperLevel()==player.OnUpperLevel()&&geom2d::overlaps(geom2d::circle(player.GetPos(),12*player.GetSizeMult()/2),geom2d::circle(b->pos,b->radius))){ if(player.Hurt(b->damage)){ if(b->PlayerHit(player)){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ break; } } continue; } } } } if(b->pos.x+b->radiuspos.x-b->radius>view.GetWorldBR().x||b->pos.y+b->radiuspos.y-b->radius>view.GetWorldBR().y){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ break; } continue; } b->lifetime-=fElapsedTime; if(b->lifetime<=0){ it=BULLET_LIST.erase(it); if(it==BULLET_LIST.end()){ break; } continue; } b->animation.UpdateState(b->internal_animState,fElapsedTime); continuePlayerBulletLoop: continue; } outsidePlayerBulletLoop: int a; } void Crawler::HurtEnemies(vf2d pos,float radius,int damage,bool upperLevel){ for(Monster&m:MONSTER_LIST){ if(m.OnUpperLevel()==upperLevel&&geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m.GetPos(),12*m.GetSizeMult()))){ m.Hurt(damage); } } } void Crawler::PopulateRenderLists(std::vector&monstersBeforeLower,std::vector&monstersBeforeUpper,std::vector&monstersAfterLower,std::vector&monstersAfterUpper,std::vector&bulletsLower,std::vector&bulletsUpper,std::vector&backgroundEffectsLower,std::vector&backgroundEffectsUpper,std::vector&foregroundEffectsLower,std::vector&foregroundEffectsUpper){ Player&pl=player; for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){ Monster&m=*it; if(m.GetPos().yOnUpperLevel()){ bulletsUpper.push_back(b); }else{ bulletsLower.push_back(b); } } for(auto it=foregroundEffects.begin();it!=foregroundEffects.end();++it){ Effect&e=*it; if(e.OnUpperLevel()){ foregroundEffectsUpper.push_back(&e); }else{ foregroundEffectsLower.push_back(&e); } } for(auto it=backgroundEffects.begin();it!=backgroundEffects.end();++it){ Effect&e=*it; if(e.OnUpperLevel()){ backgroundEffectsUpper.push_back(&e); }else{ backgroundEffectsLower.push_back(&e); } } std::sort(monstersBeforeUpper.begin(),monstersBeforeUpper.end(),[](Monster*m1,Monster*m2){return m1->GetPos().yGetPos().y;}); std::sort(monstersBeforeLower.begin(),monstersBeforeLower.end(),[](Monster*m1,Monster*m2){return m1->GetPos().yGetPos().y;}); std::sort(monstersAfterUpper.begin(),monstersAfterUpper.end(),[](Monster*m1,Monster*m2){return m1->GetPos().yGetPos().y;}); std::sort(monstersAfterLower.begin(),monstersAfterLower.end(),[](Monster*m1,Monster*m2){return m1->GetPos().yGetPos().y;}); } void Crawler::RenderWorld(float fElapsedTime){ Clear({100,180,100}); LayerTag*bridgeLayer=nullptr; bool bridgeLayerFade=false; #pragma region Basic Tile Layer Rendering 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)&&!IsUpperForegroundTile(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); } } } } } } #pragma endregion //DrawDecal({0,0},MAP_TILESETS["assets/maps/"+MAP_DATA[LEVEL1].TilesetData[1].data["source"]]->Decal()); std::vectormonstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper; std::vectorbulletsLower,bulletsUpper; std::vectorbackgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper; Player&pl=player; PopulateRenderLists(monstersBeforeLower,monstersBeforeUpper,monstersAfterLower,monstersAfterUpper,bulletsLower,bulletsUpper,backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper); if(player.GetZ()>0){ vf2d shadowScale=vf2d{8/3.f,1}/std::max(1.f,player.GetZ()/4); view.DrawDecal(player.GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6},GFX_Circle.Decal(),shadowScale); } for(Effect*e:backgroundEffectsLower){ e->Draw(); } for(Monster*m:monstersBeforeLower){ m->Draw(); } vf2d playerScale=vf2d(player.GetSizeMult(),player.GetSizeMult()); vf2d playerPosition=player.GetPos(); #define RENDER_PLAYER \ if(player.teleportAnimationTimer>0){ \ playerScale.x=120*abs(pow(player.teleportAnimationTimer-0.175,3)); \ playerPosition=player.teleportStartPosition.lerp(player.teleportTarget,(0.35-player.teleportAnimationTimer)/0.35); \ view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,playerScale,player.GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE); \ } else {view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,playerScale,player.GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player.GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE);} //define end if(!player.upperLevel){ RENDER_PLAYER } if(player.GetState()==State::BLOCK){ view.DrawDecal(player.GetPos()-vf2d{12,12},GFX_BLOCK_BUBBLE.Decal()); } for(Monster*m:monstersAfterLower){ m->Draw(); } for(Effect*e:foregroundEffectsLower){ e->Draw(); } for(Bullet*b:bulletsLower){ b->Draw(); } #pragma region Foreground Rendering 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)}); } } } #pragma endregion #pragma region Bridge Layer Rendering if(bridgeLayer!=nullptr){ 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&&ytiles[y][x]-1; if(tileID!=-1){ TilesheetData tileSheet=GetTileSheet(currentLevel,tileID); int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/24; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24; int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth; view.DrawPartialDecal(vi2d{x,y}*24,{24,24},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24},{255,255,255,uint8_t(bridgeLayerFade?128:255)}); 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); } } } } } } #pragma endregion for(Effect*e:backgroundEffectsUpper){ e->Draw(); } for(Monster*m:monstersBeforeUpper){ m->Draw(); } if(player.upperLevel){ RENDER_PLAYER } for(Monster*m:monstersAfterUpper){ m->Draw(); } for(Effect*e:foregroundEffectsUpper){ e->Draw(); } for(Bullet*b:bulletsUpper){ b->Draw(); } #pragma region Upper Foreground Rendering for(TileGroup&group:upperForegroundTileGroups){ 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)}); } } } #pragma endregion 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); std::stringstream cooldownTimeDisplay; cooldownTimeDisplay<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); } if(player.notificationDisplay.second>0){ std::string displayText=player.notificationDisplay.first; DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)-24}-GetTextSizeProp(displayText)/2,displayText,BLUE,VERY_DARK_BLUE); } std::string versionStr("v" + std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR) + "." + std::to_string(VERSION_PATCH) + "." + std::to_string(VERSION_BUILD)); DrawShadowStringDecal(vf2d{ GetScreenSize() } - vf2d{ GetTextSize(versionStr) }*0.4,versionStr,WHITE,BLACK,{0.4,0.4},0.4); DrawShadowStringDecal({0,128},player.GetPos().str()); } 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].upperForegroundTiles=tileset.GetData().UpperForegroundTileData; MAP_TILESETS["assets/maps/"+baseSourceDir].collision=tileset.GetData().CollisionData; MAP_TILESETS["assets/maps/"+baseSourceDir].staircaseTiles=tileset.GetData().StaircaseData; r->Load("assets/maps/"+tileset.GetData().ImageData.data["source"]); } } } void Crawler::LoadLevel(MapName map){ SPAWNER_LIST.clear(); foregroundTileGroups.clear(); currentLevel=map; WORLD_SIZE={MAP_DATA[map].MapData.width,MAP_DATA[map].MapData.height}; for(auto key:MAP_DATA[map].SpawnerData){ SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key.first]; std::vector>monster_list; vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2; for(XMLTag&monster:spawnData.monsters){ int monsterTypeID=monster.GetInteger("value")-1; if(monsterTypeID>=0&&monsterTypeIDforegroundTilesAdded,upperForegroundTilesAdded; for(int x=0;xSprite()->width/24; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24; int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth; #pragma region TileGroupShenanigans TileRenderData tile={tileSheet.tileset.tileset->Decal(),vi2d{x,y}*24,vi2d{tileSheetX,tileSheetY}*24}; if(IsForegroundTile(tileSheet,tileSheetIndex)&&foregroundTilesAdded.find({x,y})==foregroundTilesAdded.end()){ std::queuetileGroupChecks; TileGroup group; foregroundTilesAdded.insert({x,y}); group.InsertTile(tile); if(x>0)tileGroupChecks.push({x-1,y}); if(x0)tileGroupChecks.push({x,y-1}); if(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; TileRenderData tile={tileSheet.tileset.tileset->Decal(),pos*24,vi2d{tileSheetX,tileSheetY}*24}; if(IsForegroundTile(tileSheet,tileSheetIndex)&&foregroundTilesAdded.find(pos)==foregroundTilesAdded.end()){ foregroundTilesAdded.insert(pos); group.InsertTile(tile); if(pos.x>0)tileGroupChecks.push(pos+vi2d{-1,0}); if(pos.x0)tileGroupChecks.push(pos+vi2d{0,-1}); if(pos.ytileGroupChecks; TileGroup group; upperForegroundTilesAdded.insert({x,y}); group.InsertTile(tile); if(x>0)tileGroupChecks.push({x-1,y}); if(x0)tileGroupChecks.push({x,y-1}); if(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; TileRenderData tile={tileSheet.tileset.tileset->Decal(),pos*24,vi2d{tileSheetX,tileSheetY}*24}; if(IsUpperForegroundTile(tileSheet,tileSheetIndex)&&upperForegroundTilesAdded.find(pos)==upperForegroundTilesAdded.end()){ upperForegroundTilesAdded.insert(pos); group.InsertTile(tile); if(pos.x>0)tileGroupChecks.push(pos+vi2d{-1,0}); if(pos.x0)tileGroupChecks.push(pos+vi2d{0,-1}); if(pos.y&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;icollisionRect=GetTileCollision(map,pos,upperLevel); vi2d collisionRectSnapPos=vi2d{pos/24}*24; collisionRect.pos+=collisionRectSnapPos; return geom2d::overlaps(collisionRect,pos); } bool Crawler::IsBridgeLayer(LayerTag&layer){ return layer.tag.data.find("class")!=layer.tag.data.end()&&layer.tag.data["class"]=="Bridge"; } geom2d::rectCrawler::GetTileCollision(MapName map,vf2d pos,bool upperLevel){ if(pos.x<0||pos.y<0||pos.x>=WORLD_SIZE.x*24||pos.y>=WORLD_SIZE.y*24)return NO_COLLISION; #pragma region Lower Bridge Collision Check if(!upperLevel){ //We are looking for lower bridge collisions. for(geom2d::rect&zone:MAP_DATA[map].ZoneData["LowerBridgeCollision"]){ if(geom2d::contains(zone,pos)){ return {{0,0},{32,32}}; } } } #pragma endregion //The logic here is, if there's a tile on the bridge, we respect that tile instead if we're on the upper level. So we don't check other layers when we are on the upper level and there is a tile below us. if(upperLevel&&bridgeLayerIndex!=-1){ int tileID=MAP_DATA[map].LayerData[bridgeLayerIndex].tiles[int(pos.y)/24][int(pos.x)/24]-1; if(tileID!=-1){ if (GetTileSheet(map,tileID).tileset.collision.find(tileID-GetTileSheet(map,tileID).firstgid+1)!=GetTileSheet(map,tileID).tileset.collision.end()){ return GetTileSheet(map,tileID).tileset.collision[tileID-GetTileSheet(map,tileID).firstgid+1].collision; } return NO_COLLISION; } } int counter=0; for(LayerTag&layer:MAP_DATA[map].LayerData){ auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();}; if(HasNoClass()&&counter!=bridgeLayerIndex){ 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).firstgid+1)!=GetTileSheet(map,tileID).tileset.collision.end()){ return GetTileSheet(map,tileID).tileset.collision[tileID-GetTileSheet(map,tileID).firstgid+1].collision; } } counter++; } return NO_COLLISION; } MapName Crawler::GetCurrentLevel(){ return currentLevel; } std::map>>&Crawler::GetZoneData(MapName map){ return MAP_DATA[map].ZoneData; } int main() { Crawler demo; if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4)) demo.Start(); return 0; }