From f47d49417b85367ecdcbfe6b9a785840f367c996 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sat, 17 Aug 2024 19:46:36 -0500 Subject: [PATCH] Add in burning and drowning states and all terrain effects. --- assets/burnmeter.png | Bin 0 -> 788 bytes assets/drownmeter.png | Bin 0 -> 734 bytes src/Hamster.cpp | 71 ++++++++++++++++++++++++++++++++++++++++-- src/Hamster.h | 19 +++++++++++ src/HamsterGame.cpp | 44 +++++++++++++++++--------- 5 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 assets/burnmeter.png create mode 100644 assets/drownmeter.png diff --git a/assets/burnmeter.png b/assets/burnmeter.png new file mode 100644 index 0000000000000000000000000000000000000000..1fa24d26af480467ebee11b2b4cca1347a1de503 GIT binary patch literal 788 zcmV+v1MB>WP)EX>4Tx04R}tkv&MmKpe$iQ^g_`K|6?uWT?8>MMWG-6^me@v=v%)FuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3;J6>}?mh0_0Yam~RI@7zsG4P@ z;xRFsTNQg=5x@X|QA|k8)D!8&3_QozJ$!t)R&;^Mfxh}i>#<}RQz%xTeCN)nSA{L7sEO#&~87lD%aad6`$``UO zE1b7DtCbpS-IKpCnAcX)T&FpLIF^t=5+Y>OP(}q7BD89xm`Krn%)>wI_><(4$yEj; z#{#NQAvu2VKlt6PS(u)3lY%jz`^C0D#(eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{008VsL_t(o!|j(b3WG2hh2P&6oa)j^6p07%8r|JILU9qH z?EyM<^AtUS2Qi4^)J006UD8FNq_NPYgZ>W!AzMD)|6T&Hepj1Cs?8$BBmgqODWnSk z2t@-Y&1uen7CM|^zs>i={sC6{K_Oj)q5%M-d#YMZe)N2gXcW)@$E2!O%J-&ktp1+# zF=9@d(~v)3LYii<#xp1s4eU5TAzg5jy#X3v*l~c%?#bz_*L<5r%8mnAn*>XF!+m{1 zcP{m?R#iQHQ}sDZ#*ltokFZ37?ogVVjC_yOoQy+b@1U`o=WhmoGgvIv|MUX(%U5n> SC5SHo0000EX>4Tx04R}tkv&MmKpe$iQ^g_`K|6?uWT?8>MMWG-6^me@v=v%)FuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|?BJy6A|?JWDYS_3;J6>}?mh0_0Yam~RI@7zsG4P@ z;xRFsTNQg=5x@X|QA|k8)D!8&3_QozJ$!t)R&;^Mfxh}i>#<}RQz%xTeCN)nSA{L7sEO#&~87lD%aad6`$``UO zE1b7DtCbpS-IKpCnAcX)T&FpLIF^t=5+Y>OP(}q7BD89xm`Krn%)>wI_><(4$yEj; z#{#NQAvu2VKlt6PS(u)3lY%jz`^C0D#(eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{006d0L_t(o!|j%_4TUfaL~V(h38IWdNyQ9IK*=afz(|k@ zSim$mSRv?tBr0;RiG@Vr)8#Hi0KCS$iOib_lsKuZIMWc~+|G+clG4QC5U+UePbPa@+E)TewDUgZ*!;w_oRD92Q@Xb3WNN4&}wi{B8a+2 zgWG=dj!OyYICEO_w#k%kboSbn;G%p$+tbc?C}z;mMqp=L1U3F_EdYM919xARFR(}< Q%m4rY07*qoM6N<$f?j(%b^rhX literal 0 HcmV?d00001 diff --git a/src/Hamster.cpp b/src/Hamster.cpp index e3c5e39..9c11d24 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -58,6 +58,7 @@ Hamster::Hamster(const vf2d spawnPos,const std::string_view img,const PlayerCont void Hamster::UpdateHamsters(const float fElapsedTime){ for(Hamster&h:HAMSTER_LIST){ + h.lastSafeLocationTimer=std::max(0.f,h.lastSafeLocationTimer-fElapsedTime); h.animations.UpdateState(h.internalAnimState,fElapsedTime); h.frictionEnabled=true; h.bumpTimer-=fElapsedTime; @@ -74,6 +75,49 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.state=NORMAL; } }break; + case DROWNING:{ + if(h.imgScale>0.f){ + h.shrinkEffectColor=BLACK; + h.imgScale=std::max(0.f,h.imgScale-0.5f*fElapsedTime); + } + else{ + h.waitTimer=4.f; + h.state=WAIT; + } + }break; + case WAIT:{ + h.waitTimer=std::max(0.f,h.waitTimer-fElapsedTime); + if(h.waitTimer<=0.f){ + h.imgScale=1.f; + h.drownTimer=0.f; + h.pos=h.lastSafeLocation; + h.state=NORMAL; + h.RemoveAllPowerups(); + } + }break; + case BURNING:{ + if(h.imgScale>0.f){ + h.shrinkEffectColor=RED; + h.imgScale=std::max(0.f,h.imgScale-0.5f*fElapsedTime); + }else{ + h.waitTimer=4.f; + h.state=WAIT; + } + }break; + } + if((h.GetTerrainStandingOn()==Terrain::OCEAN||!h.HasPowerup(Powerup::SWAMP)&&h.GetTerrainStandingOn()==Terrain::SWAMP)&&h.state!=DROWNING&&h.state!=WAIT)h.drownTimer+=fElapsedTime; + else if((!h.HasPowerup(Powerup::LAVA)&&h.GetTerrainStandingOn()==Terrain::LAVA)&&h.state!=BURNING&&h.state!=WAIT)h.burnTimer+=fElapsedTime; + else if(h.lastSafeLocationTimer<=0.f&&h.state==NORMAL&&!h.StandingOnLethalTerrain()){ + h.lastSafeLocationTimer=0.5f; + h.drownTimer=0.f; + h.burnTimer=0.f; + h.lastSafeLocation=h.GetPos(); + } + if(h.drownTimer>=h.DEFAULT_DROWN_TIME&&h.state!=DROWNING&&h.state!=WAIT){ + h.state=DROWNING; + } + if(h.burnTimer>=h.DEFAULT_BURN_TIME&&h.state!=BURNING&&h.state!=WAIT){ + h.state=BURNING; } h.TurnTowardsTargetDirection(); h.MoveHamster(); @@ -99,9 +143,9 @@ void Hamster::DrawHamsters(TransformedView&tv){ const Animate2D::Frame&img{h.animations.GetState(h.internalAnimState)==HamsterGame::DEFAULT?anim.GetFrame(h.distanceTravelled/100.f):h.GetCurrentAnimation()}; const Animate2D::Frame&wheelTopImg{wheelTopAnim.GetFrame(h.distanceTravelled/80.f)}; const Animate2D::Frame&wheelBottomImg{wheelBottomAnim.GetFrame(h.distanceTravelled/80.f)}; - if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos,wheelBottomImg.GetSourceImage()->Decal(),h.rot,wheelBottomImg.GetSourceRect().size/2,wheelBottomImg.GetSourceRect().pos,wheelBottomImg.GetSourceRect().size); - tv.DrawPartialRotatedDecal(h.pos,img.GetSourceImage()->Decal(),h.rot,img.GetSourceRect().size/2,img.GetSourceRect().pos,img.GetSourceRect().size); - if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos,wheelTopImg.GetSourceImage()->Decal(),h.rot,wheelTopImg.GetSourceRect().size/2,wheelTopImg.GetSourceRect().pos,wheelTopImg.GetSourceRect().size,{1.f,1.f},{255,255,255,192}); + if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos,wheelBottomImg.GetSourceImage()->Decal(),h.rot,wheelBottomImg.GetSourceRect().size/2,wheelBottomImg.GetSourceRect().pos,wheelBottomImg.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale)); + tv.DrawPartialRotatedDecal(h.pos,img.GetSourceImage()->Decal(),h.rot,img.GetSourceRect().size/2,img.GetSourceRect().pos,img.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,WHITE,h.imgScale)); + if(h.HasPowerup(Powerup::WHEEL))tv.DrawPartialRotatedDecal(h.pos,wheelTopImg.GetSourceImage()->Decal(),h.rot,wheelTopImg.GetSourceRect().size/2,wheelTopImg.GetSourceRect().pos,wheelTopImg.GetSourceRect().size,vf2d{1.f,1.f}*h.imgScale,PixelLerp(h.shrinkEffectColor,{255,255,255,192},h.imgScale)); } } @@ -256,4 +300,25 @@ void Hamster::ObtainPowerup(const Powerup::PowerupType powerup){ } const bool Hamster::HasPowerup(const Powerup::PowerupType powerup)const{ return powerups.count(powerup); +} + +void Hamster::RemoveAllPowerups(){ + powerups.clear(); +} + +const bool Hamster::StandingOnLethalTerrain()const{ + return GetTerrainStandingOn()==Terrain::LAVA||GetTerrainStandingOn()==Terrain::OCEAN||GetTerrainStandingOn()==Terrain::SWAMP; +} + +const bool Hamster::IsDrowning()const{ + return drownTimer>0.f; +} +const bool Hamster::IsBurning()const{ + return burnTimer>0.f; +} +const float Hamster::GetDrownRatio()const{ + return drownTimer/DEFAULT_DROWN_TIME; +} +const float Hamster::GetBurnRatio()const{ + return burnTimer/DEFAULT_BURN_TIME; } \ No newline at end of file diff --git a/src/Hamster.h b/src/Hamster.h index 0f79c1b..87354a7 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -52,6 +52,10 @@ class Hamster{ enum HamsterState{ NORMAL, BUMPED, + DROWNING, + FLYING, + WAIT, + BURNING, }; static std::vectorHAMSTER_LIST; @@ -67,15 +71,24 @@ class Hamster{ const float DEFAULT_FRICTION{400.f}; const float DEFAULT_TURN_SPD{2.f*geom2d::pi}; const float DEFAULT_BUMP_AMT{100.f}; + const float DEFAULT_DROWN_TIME{5.f}; + const float DEFAULT_BURN_TIME{0.3f}; vf2d pos; vf2d vel; + vf2d lastSafeLocation{}; + float lastSafeLocationTimer{}; float rot{}; float targetRot{}; bool frictionEnabled{false}; float collisionRadius{12.f}; float bumpTimer{}; + float waitTimer{}; double distanceTravelled{}; + float drownTimer{}; + float burnTimer{}; + float imgScale{1.f}; + Pixel shrinkEffectColor{BLACK}; std::string img; Animate2D::Animationanimations; Animate2D::AnimationState internalAnimState; @@ -104,4 +117,10 @@ public: const float GetBumpAmount()const; void ObtainPowerup(const Powerup::PowerupType powerup); const bool HasPowerup(const Powerup::PowerupType powerup)const; + void RemoveAllPowerups(); + const bool StandingOnLethalTerrain()const; + const bool IsDrowning()const; + const bool IsBurning()const; + const float GetDrownRatio()const; + const float GetBurnRatio()const; }; \ No newline at end of file diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index 2b8778c..e48e8f5 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -39,6 +39,8 @@ void HamsterGame::LoadGraphics(){ _LoadImage("border.png"); _LoadImage("gametiles.png"); _LoadImage("shadow.png"); + _LoadImage("drownmeter.png"); + _LoadImage("burnmeter.png"); } void HamsterGame::LoadAnimations(){ @@ -109,23 +111,35 @@ void HamsterGame::DrawGame(){ DrawStringDecal(SCREEN_FRAME.pos+vf2d{1,1},"Terrain Type: "+Terrain::TerrainToString(Hamster::GetPlayer().GetTerrainStandingOn()),BLACK); DrawStringDecal(SCREEN_FRAME.pos,"Terrain Type: "+Terrain::TerrainToString(Hamster::GetPlayer().GetTerrainStandingOn())); - for(int y:std::ranges::iota_view(0,4)){ - for(int x:std::ranges::iota_view(0,2)){ - const int powerupInd{y*2+x}; - const float drawX{x*32.f+12.f}; - const float drawY{y*32.f+12.f+96.f}; - const Powerup::PowerupType powerupType{Powerup::PowerupType(powerupInd)}; - const geom2d::rectpowerupSubimageRect{Powerup::GetPowerupSubimageRect(powerupType)}; - if(Hamster::GetPlayer().HasPowerup(powerupType)){ - SetDecalMode(DecalMode::ADDITIVE); - DrawPartialRotatedDecal(vf2d{drawX,drawY}+16,GetGFX("gametiles.png").Decal(),0.f,{16.f,16.f},powerupSubimageRect.pos,powerupSubimageRect.size,{1.1f,1.1f}); - SetDecalMode(DecalMode::NORMAL); - DrawPartialDecal({drawX,drawY},GetGFX("gametiles.png").Decal(),powerupSubimageRect.pos,powerupSubimageRect.size); - }else{ - DrawPartialDecal({drawX,drawY},GetGFX("gametiles.png").Decal(),powerupSubimageRect.pos,powerupSubimageRect.size,{1.f,1.f},VERY_DARK_GREY); + #pragma region Powerup Display + for(int y:std::ranges::iota_view(0,4)){ + for(int x:std::ranges::iota_view(0,2)){ + const int powerupInd{y*2+x}; + const float drawX{x*32.f+12.f}; + const float drawY{y*32.f+12.f+96.f}; + const Powerup::PowerupType powerupType{Powerup::PowerupType(powerupInd)}; + const geom2d::rectpowerupSubimageRect{Powerup::GetPowerupSubimageRect(powerupType)}; + if(Hamster::GetPlayer().HasPowerup(powerupType)){ + SetDecalMode(DecalMode::ADDITIVE); + DrawPartialRotatedDecal(vf2d{drawX,drawY}+16,GetGFX("gametiles.png").Decal(),0.f,{16.f,16.f},powerupSubimageRect.pos,powerupSubimageRect.size,{1.1f,1.1f}); + SetDecalMode(DecalMode::NORMAL); + DrawPartialDecal({drawX,drawY},GetGFX("gametiles.png").Decal(),powerupSubimageRect.pos,powerupSubimageRect.size); + }else{ + DrawPartialDecal({drawX,drawY},GetGFX("gametiles.png").Decal(),powerupSubimageRect.pos,powerupSubimageRect.size,{1.f,1.f},VERY_DARK_GREY); + } } } - } + #pragma endregion + #pragma region Drown/Burn Bar. + if(Hamster::GetPlayer().IsDrowning()){ + DrawDecal({12.f,240.f},GetGFX("drownmeter.png").Decal()); + GradientFillRectDecal(vf2d{12.f,240.f}+vf2d{12.f,5.f},vf2d{Hamster::GetPlayer().GetDrownRatio()*57.f,4.f},{145,199,255},{226,228,255},{226,228,255},{145,199,255}); + } + else if(Hamster::GetPlayer().IsBurning()){ + DrawDecal({12.f,240.f},GetGFX("burnmeter.png").Decal()); + GradientFillRectDecal(vf2d{12.f,240.f}+vf2d{12.f,5.f},vf2d{Hamster::GetPlayer().GetBurnRatio()*57.f,4.f},{250,177,163},{226,228,255},{226,228,255},{250,177,163}); + } + #pragma endregion } const Terrain::TerrainType HamsterGame::GetTerrainTypeAtPos(const vf2d pos)const{