#include "olcPGEX_TransformedView.h" #include "Crawler.h" #include "olcUTIL_Camera2D.h" #include "DamageNumber.h" #include "Bullet.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; Crawler*game; Crawler::Crawler() { sAppName = "Crawler Concept"; game=this; } bool Crawler::OnUserCreate(){ //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_Pl_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"); //Animations InitializeAnimations(); player.AddAnimation(AnimationState::WALK_N); player.AddAnimation(AnimationState::WALK_E); player.AddAnimation(AnimationState::WALK_S); player.AddAnimation(AnimationState::WALK_W); player.AddAnimation(AnimationState::IDLE_N); player.AddAnimation(AnimationState::IDLE_E); player.AddAnimation(AnimationState::IDLE_S); player.AddAnimation(AnimationState::IDLE_W); view=TileTransformedView{GetScreenSize(),{1,1}}; player.SetPos({4*24,4*24}); player.UpdateAnimation(AnimationState::IDLE_S); SPAWNER_LIST.push_back(MonsterSpawner({360*1,96},4*24,{{ {MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); SPAWNER_LIST.push_back(MonsterSpawner({360*2,96},4*24,{{ {MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); SPAWNER_LIST.push_back(MonsterSpawner({360*3,96},4*24,{{ {MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); SPAWNER_LIST.push_back(MonsterSpawner({360*4,96},4*24,{{ {MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_GREEN,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); SPAWNER_LIST.push_back(MonsterSpawner({360*5,96},4*24,{{ {MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); SPAWNER_LIST.push_back(MonsterSpawner({360*6,96},4*24,{{ {MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_RED,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); SPAWNER_LIST.push_back(MonsterSpawner({360*7,96},4*24,{{ {MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} ,{MonsterName::SLIME_BLUE,{(rand()%20/2.f-5)*24,(rand()%20/2.f-5)*24}} }})); 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(){ Animate2D::FrameSequence pl_walk_s{0.2}; pl_walk_s.AddFrame({&GFX_Pl_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_walk_s.AddFrame({&GFX_Pl_Sheet,{vi2d{1,0}*24,{24,24}}}); pl_walk_s.AddFrame({&GFX_Pl_Sheet,{vi2d{0,0}*24,{24,24}}}); pl_walk_s.AddFrame({&GFX_Pl_Sheet,{vi2d{2,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WALK_S]=pl_walk_s; Animate2D::FrameSequence pl_walk_e{0.2}; pl_walk_e.AddFrame({&GFX_Pl_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_walk_e.AddFrame({&GFX_Pl_Sheet,{vi2d{1,3}*24,{24,24}}}); pl_walk_e.AddFrame({&GFX_Pl_Sheet,{vi2d{0,3}*24,{24,24}}}); pl_walk_e.AddFrame({&GFX_Pl_Sheet,{vi2d{2,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WALK_E]=pl_walk_e; Animate2D::FrameSequence pl_walk_w{0.2}; pl_walk_w.AddFrame({&GFX_Pl_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_walk_w.AddFrame({&GFX_Pl_Sheet,{vi2d{1,2}*24,{24,24}}}); pl_walk_w.AddFrame({&GFX_Pl_Sheet,{vi2d{0,2}*24,{24,24}}}); pl_walk_w.AddFrame({&GFX_Pl_Sheet,{vi2d{2,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WALK_W]=pl_walk_w; Animate2D::FrameSequence pl_walk_n{0.2}; pl_walk_n.AddFrame({&GFX_Pl_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_walk_n.AddFrame({&GFX_Pl_Sheet,{vi2d{1,1}*24,{24,24}}}); pl_walk_n.AddFrame({&GFX_Pl_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_walk_n.AddFrame({&GFX_Pl_Sheet,{vi2d{2,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::WALK_N]=pl_walk_n; Animate2D::FrameSequence pl_idle_s; pl_idle_s.AddFrame({&GFX_Pl_Sheet,{vi2d{0,0}*24,{24,24}}}); ANIMATION_DATA[AnimationState::IDLE_S]=pl_idle_s; Animate2D::FrameSequence pl_idle_e; pl_idle_e.AddFrame({&GFX_Pl_Sheet,{vi2d{0,3}*24,{24,24}}}); ANIMATION_DATA[AnimationState::IDLE_E]=pl_idle_e; Animate2D::FrameSequence pl_idle_w; pl_idle_w.AddFrame({&GFX_Pl_Sheet,{vi2d{0,2}*24,{24,24}}}); ANIMATION_DATA[AnimationState::IDLE_W]=pl_idle_w; Animate2D::FrameSequence pl_idle_n; pl_idle_n.AddFrame({&GFX_Pl_Sheet,{vi2d{0,1}*24,{24,24}}}); ANIMATION_DATA[AnimationState::IDLE_N]=pl_idle_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; } 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(SPACE).bPressed&&player.GetState()==State::NORMAL&&player.GetGroundSlamCooldown()==0){ player.Spin(Player::GROUND_SLAM_SPIN_TIME,14*PI); } if(player.GetVelocity()==vf2d{0,0}){ if(RightHeld()){ if(player.GetPos().x+12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()0){ player.SetX(player.GetX()-fElapsedTime*100*player.GetMoveSpdMult()); } else { player.SetX(12); } if(setIdleAnimation){ player.SetFacingDirection(LEFT); player.UpdateAnimation(AnimationState::WALK_W); } setIdleAnimation=false; } if(UpHeld()){ if(player.GetPos().y-12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()>0){ player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult()); } else { player.SetY(12); } if(setIdleAnimation){ player.SetFacingDirection(UP); player.UpdateAnimation(AnimationState::WALK_N); } setIdleAnimation=false; } if(DownHeld()){ if(player.GetPos().y+12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()::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.pos+=b.vel*fElapsedTime; if(geom2d::overlaps(geom2d::circle(player.GetPos(),12*player.GetSizeMult()/2),geom2d::circle(b.pos,b.radius))){ 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; } } } } 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>=00&&x=0&&ymonstersBefore,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())); for(Monster&m:monstersAfter){ m.Draw(); } for(Effect&e:foregroundEffects){ e.Draw(); } for(Bullet&b:BULLET_LIST){ view.FillCircle(b.pos,b.radius,b.col); view.DrawCircle(b.pos,b.radius,WHITE,0xAA); } 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.lifeTime0){ FillRectDecal({10,ScreenHeight()-22.f},{64,6},BLACK); FillRectDecal({11,ScreenHeight()-21.f},{62,4},DARK_GREY); GradientFillRectDecal({10,ScreenHeight()-22.f},{(player.GetGroundSlamCooldown()/Player::GROUND_SLAM_COOLDOWN)*64,6},VERY_DARK_RED,VERY_DARK_RED,DARK_RED,DARK_RED); DrawRotatedStringPropDecal(vf2d{8,ScreenHeight()-20.f}+vf2d{1,1},"G R O U N D S L A M",-PI/64,{0,0},BLACK,{0.4,0.4}); DrawRotatedStringPropDecal({8,ScreenHeight()-20.f},"G R O U N D S L A M",-PI/64,{0,0},WHITE,{0.4,0.4}); } DrawDecal({2,2},GFX_Heart.Decal()); std::string text=player.GetHealth()>0?std::to_string(player.GetHealth()):"X"; for(int y=-1;y<=1;y++){ for(int x=-1;x<=1;x++){ if(x!=0||y!=0){ DrawStringPropDecal(vf2d{20,3}+vf2d{float(x),float(y)},text,BLACK,{2,2}); } } } DrawStringPropDecal({20,3},text,WHITE,{2,2}); } void Crawler::AddEffect(Effect foreground,Effect background){ foregroundEffects.push_back(foreground); backgroundEffects.push_back(background); } vf2d Crawler::GetWorldMousePos(){ return GetMousePos()+view.GetWorldOffset(); } int main() { Crawler demo; if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4)) demo.Start(); return 0; }