From 002b00f018de2ec929c862c9fa666407676988d1 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Tue, 20 Aug 2024 03:52:29 -0500 Subject: [PATCH] Added Fall-o-meter HUD elements, added crash landing mechanics, and fuel. --- assets/fuelbar_outline.png | Bin 0 -> 778 bytes assets/hamster.png | Bin 2471 -> 19273 bytes assets/hamster_jet.png | Bin 3791 -> 17339 bytes src/Hamster.cpp | 194 +++++++++++++++++++++++++------------ src/Hamster.h | 11 +++ src/HamsterGame.cpp | 2 + src/HamsterGame.h | 1 + src/HamsterJet.cpp | 23 +++-- src/HamsterJet.h | 2 +- src/Powerup.cpp | 4 +- src/Powerup.h | 4 +- src/Terrain.cpp | 78 +++++++++++++++ src/Terrain.h | 8 ++ 13 files changed, 257 insertions(+), 70 deletions(-) create mode 100644 assets/fuelbar_outline.png diff --git a/assets/fuelbar_outline.png b/assets/fuelbar_outline.png new file mode 100644 index 0000000000000000000000000000000000000000..72b1730a873bdbc9c59a142b709eb3142654d4e4 GIT binary patch literal 778 zcmV+l1NHogP)EX>4Tx04R}tkv&MmKpe$iQ>8_!g6$yUkf92KT~x%eRIvyaN?V~-2b1e3G-*gu zTpR`0f`cE6RRU2TkN3P2bzi}?vEbz>bo=MFUhls^e7t3AD%DO^4LmbX4D&-4V zhx44bI4jjUYu}Tuie$2%`V*8WilF3y8 zBgX=2P$1cU@IUz7tx=qwa*_fup!dbHKE?pwF3@UN*7vbxwN3!^`WJ_L}La_+EpV2qvfZ#3Ax90TL-pAn`v1clY-1nRb6ax7>2Vt#32K00006VoOIv08ao>0Dz+=vp@g<010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=m-=CGaA*7GKl~H02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{0081iL_t(&-tE}I3dA4`1kg#z|9`R2Jy{lMyD_>Z!gvx- zZ^l+Z0f17^oQki~`g<)Rd zmTig(;(~j_%nULO-Wy~z#NXi7Al?AW;J-rj258~OlIvMjTIlG7w*>waUtZvT;l6>EPDZ(>6{x z;e-=TIN^j7PB`I&6HYkcgcD9U;e-?J8JZdQ_S7spp}(J?KbwqzQv7ckxBvhE07*qo IM6N<$f@5@A6951J literal 0 HcmV?d00001 diff --git a/assets/hamster.png b/assets/hamster.png index 40e3263e7142dcdf70807e5bc70390f2061f9f19..e99b147ad2b2cf772848451148f4801c46334a3c 100644 GIT binary patch literal 19273 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�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 KX^=7x{eJ-1FqO~% delta 3360 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,-1},{3,3}}; - std::optional>closestTile; - - const auto DetermineAndUpdateClosestTile=[&h,&playerTile,&closestTile](const vi2d&tile){ - if(!h.IsLethalTerrain(tile*16)){ - std::pairclosest{closestTile.value_or(std::pair{{},std::numeric_limits::max()})}; - int tileDist{abs(playerTile.x-tile.x)+abs(playerTile.y-tile.y)}; - if(tileDist<=closest.second)closestTile.emplace(std::pair{tile,tileDist}); - } - }; - while(!closestTile.has_value()){ - #pragma region Top Outline Check - { - for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){ - const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.top().end.y}}; - DetermineAndUpdateClosestTile(checkTile); - } - } - #pragma endregion - #pragma region Bottom Outline Check - { - for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){ - const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.bottom().end.y}}; - DetermineAndUpdateClosestTile(checkTile); - } - } - #pragma endregion - #pragma region Right Outline Check - { - for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){ - const vi2d checkTile{playerTile+vi2d{searchRect.right().end.x,offsetY}}; - DetermineAndUpdateClosestTile(checkTile); - } - } - #pragma endregion - #pragma region Left Outline Check - { - for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){ - const vi2d checkTile{playerTile+vi2d{searchRect.left().end.x,offsetY}}; - DetermineAndUpdateClosestTile(checkTile); - } - } - #pragma endregion - searchRect.pos-=1; - searchRect.size+=2; - } - h.lastSafeLocation=closestTile.value().first*16+8; - } - #pragma endregion + h.lastSafeLocation=h.GetNearestSafeLocation(); } h.SetPos(h.lastSafeLocation.value()); h.state=NORMAL; @@ -162,6 +108,13 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.state=WAIT; } }break; + case KNOCKOUT:{ + h.knockoutTimer-=fElapsedTime; + if(h.knockoutTimer<=0.f){ + h.state=NORMAL; + h.animations.ChangeState(h.internalAnimState,HamsterGame::DEFAULT); + } + }break; } if(h.hamsterJet.has_value())h.hamsterJet.value().Update(fElapsedTime); if(h.state!=FLYING){ @@ -182,6 +135,12 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ } h.TurnTowardsTargetDirection(); h.MoveHamster(); + if(h.IsPlayerControlled){ + h.hamsterJetDisplay.Update(fElapsedTime); + h.hamsterJetLightsDisplay.Update(fElapsedTime); + h.readyFlashTimer+=fElapsedTime; + h.jetFuelDisplayAmt+=(h.jetFuel-h.jetFuelDisplayAmt)*4.f*fElapsedTime; + } } } @@ -194,6 +153,8 @@ void Hamster::LoadHamsters(const vf2d startingLoc){ for(int i:std::ranges::iota_view(0U,NPC_HAMSTER_COUNT)){ HAMSTER_LIST.emplace_back(startingLoc,NPC_HAMSTER_IMAGES.at(util::random()%NPC_HAMSTER_IMAGES.size()),NPC); } + playerHamster.value()->hamsterJetDisplay.Initialize("hamster_jet.png",{78,223,208},{79,81,128}); + playerHamster.value()->hamsterJetLightsDisplay.Initialize("hamster_jet.png",{245,233,130},{245,233,130}); } void Hamster::DrawHamsters(TransformedView&tv){ @@ -216,10 +177,44 @@ void Hamster::DrawHamsters(TransformedView&tv){ } void Hamster::DrawOverlay(){ - if(GetPlayer().hamsterJet.has_value()){ - GetPlayer().hamsterJet.value().DrawOverlay(); - HamsterGame::Game().DrawDecal(vf2d{96.f,0.f}+HamsterGame::SCREEN_FRAME.size,HamsterGame::GetGFX("fuelmeter.png").Decal()); + if(GetPlayer().hamsterJet.has_value())GetPlayer().hamsterJet.value().DrawOverlay(); + + const vf2d jetDisplayOffset{HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f}}; + Pixel jetDisplayCol{VERY_DARK_GREY}; + if(!GetPlayer().hamsterJet.has_value()){ + if(GetPlayer().HasPowerup(Powerup::JET))jetDisplayCol=WHITE; + const Animate2D::FrameSequence&lightAnim{HamsterGame::Game().GetAnimation("hamster_jet.png",HamsterGame::AnimationState::JET_LIGHTS)}; + const Animate2D::Frame&lightFrame{lightAnim.GetFrame(HamsterGame::Game().GetRuntime())}; + HamsterGame::Game().DrawPartialRotatedDecal(jetDisplayOffset+vf2d{48.f,80.f},GetPlayer().hamsterJetDisplay.Decal(),0.f,{24.f,24.f},{0.f,0.f},{48.f,48.f},{2.f,2.f},jetDisplayCol); + HamsterGame::Game().DrawPartialRotatedDecal(jetDisplayOffset+vf2d{48.f,80.f},GetPlayer().hamsterJetLightsDisplay.Decal(),0.f,{24.f,24.f},lightFrame.GetSourceRect().pos,lightFrame.GetSourceRect().size,{2.f,2.f},jetDisplayCol); } + + if(GetPlayer().HasPowerup(Powerup::JET)&&!GetPlayer().hamsterJet.has_value()){ + const std::string readyText{"READY!"}; + const vi2d textSize{HamsterGame::Game().GetTextSize(readyText)}; + for(int y:std::ranges::iota_view(-1,2)){ + for(int x:std::ranges::iota_view(-1,2)){ + if(x==0&&y==0)continue; + HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f}+vi2d{x,y},readyText,0.f,textSize/2,fmod(GetPlayer().readyFlashTimer,1.5f)<=0.75f?DARK_RED:BLACK); + } + } + HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f},readyText,0.f,textSize/2,GREEN); + HamsterGame::Game().DrawDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f},HamsterGame::GetGFX("fuelmeter.png").Decal()); + const std::string launchText{"(SPACE)x2\nto Launch!"}; + const vi2d launchTextSize{HamsterGame::Game().GetTextSize(launchText)}; + for(int y:std::ranges::iota_view(-1,2)){ + for(int x:std::ranges::iota_view(-1,2)){ + if(x==0&&y==0)continue; + HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f}+vi2d{x,y},launchText,0.f,launchTextSize/2,BLACK); + } + } + HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f},launchText,0.f,launchTextSize/2,WHITE); + }else{ + HamsterGame::Game().DrawPartialDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f},HamsterGame::GetGFX("fuelmeter.png").Decal(),{0,0},{96,200}); + } + const float jetFuelBarHeight{float(HamsterGame::GetGFX("fuelbar.png").Sprite()->height)}; + HamsterGame::Game().DrawPartialDecal(jetDisplayOffset+vf2d{24.f,139.f}+vf2d{0.f,jetFuelBarHeight*(1.f-GetPlayer().jetFuelDisplayAmt)},HamsterGame::GetGFX("fuelbar.png").Decal(),{0.f,jetFuelBarHeight*(1.f-GetPlayer().jetFuelDisplayAmt)},{float(HamsterGame::GetGFX("fuelbar.png").Sprite()->width),jetFuelBarHeight*(GetPlayer().jetFuelDisplayAmt)}); + if(GetPlayer().HasPowerup(Powerup::JET))HamsterGame::Game().DrawDecal(jetDisplayOffset+vf2d{22.f,137.f},HamsterGame::GetGFX("fuelbar_outline.png").Decal(),{1.f,1.f},GetPlayer().jetFuel<=0.2f?(fmod(GetPlayer().readyFlashTimer,1.f)<=0.5f?RED:BLACK):BLACK); } const Animate2D::Frame&Hamster::GetCurrentAnimation()const{ @@ -265,7 +260,11 @@ void Hamster::HandlePlayerControls(){ } lastTappedSpace=0.f; } - if(HamsterGame::Game().GetKey(P).bPressed)ObtainPowerup(Powerup::JET); + if(HamsterGame::Game().GetKey(P).bPressed){ + ObtainPowerup(Powerup::JET); + Powerup tempJetPowerup{{},Powerup::JET}; + tempJetPowerup.OnPowerupObtain(*this); + } } void Hamster::TurnTowardsTargetDirection(){ @@ -276,6 +275,9 @@ void Hamster::MoveHamster(){ SetPos(GetPos()+vel*HamsterGame::Game().GetElapsedTime()); distanceTravelled+=vel.mag()*HamsterGame::Game().GetElapsedTime(); + if(state==FLYING){ + jetFuel=std::max(0.f,jetFuel-vel.mag()*HamsterGame::Game().GetElapsedTime()/100000.f); + } #pragma region Handle Friction if(frictionEnabled){ @@ -314,9 +316,11 @@ void Hamster::HandleCollision(){ } } for(Powerup&powerup:Powerup::GetPowerups()){ - if(z<=0.1f&&!HasPowerup(powerup.GetType())&&geom2d::overlaps(geom2d::circle(GetPos(),collisionRadius),geom2d::circle(powerup.GetPos(),20.f))){ + if(z<=0.1f&& + (!HasPowerup(powerup.GetType())||HasPowerup(Powerup::JET)&&powerup.GetType()==Powerup::JET&&jetFuel!=1.f) + &&geom2d::overlaps(geom2d::circle(GetPos(),collisionRadius),geom2d::circle(powerup.GetPos(),20.f))){ ObtainPowerup(powerup.GetType()); - powerup.OnPowerupObtain(); + powerup.OnPowerupObtain(*this); } } } @@ -450,4 +454,72 @@ void Hamster::OnUserDestroy(){ void Hamster::SetDrawingOffsetY(const float offsetY){ drawingOffsetY=offsetY; +} + +const vf2d Hamster::GetNearestSafeLocation()const{ + using TilePos=vi2d; + using TileDistance=int; + + const vi2d playerTile{GetPos()/16}; + geom2d::rectsearchRect{{-1,-1},{3,3}}; + std::optional>closestTile; + + const auto DetermineAndUpdateClosestTile=[this,&playerTile,&closestTile](const vi2d&tile){ + if(!IsLethalTerrain(tile*16)&&!IsSolidTerrain(tile*16)){ + std::pairclosest{closestTile.value_or(std::pair{{},std::numeric_limits::max()})}; + int tileDist{abs(playerTile.x-tile.x)+abs(playerTile.y-tile.y)}; + if(tileDist<=closest.second)closestTile.emplace(std::pair{tile,tileDist}); + } + }; + while(!closestTile.has_value()){ + #pragma region Top Outline Check + { + for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){ + const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.top().end.y}}; + DetermineAndUpdateClosestTile(checkTile); + } + } + #pragma endregion + #pragma region Bottom Outline Check + { + for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){ + const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.bottom().end.y}}; + DetermineAndUpdateClosestTile(checkTile); + } + } + #pragma endregion + #pragma region Right Outline Check + { + for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){ + const vi2d checkTile{playerTile+vi2d{searchRect.right().end.x,offsetY}}; + DetermineAndUpdateClosestTile(checkTile); + } + } + #pragma endregion + #pragma region Left Outline Check + { + for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){ + const vi2d checkTile{playerTile+vi2d{searchRect.left().end.x,offsetY}}; + DetermineAndUpdateClosestTile(checkTile); + } + } + #pragma endregion + searchRect.pos-=1; + searchRect.size+=2; + } + return closestTile.value().first*16+8; +} + +const bool Hamster::IsSolidTerrain(const vf2d pos)const{ + return HamsterGame::Game().IsTerrainSolid(pos); +} + +void Hamster::SetJetFuel(const float amt){ + jetFuel=amt; +} + +void Hamster::Knockout(){ + state=KNOCKOUT; + knockoutTimer=4.f; + animations.ChangeState(internalAnimState,HamsterGame::KNOCKOUT); } \ No newline at end of file diff --git a/src/Hamster.h b/src/Hamster.h index 22f4f26..de183ea 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -59,6 +59,7 @@ class Hamster{ FLYING, WAIT, BURNING, + KNOCKOUT, }; static std::vectorHAMSTER_LIST; @@ -103,6 +104,12 @@ class Hamster{ std::optionalhamsterJet; float lastTappedSpace{0.f}; float drawingOffsetY{0.f}; + SpecialRenderable hamsterJetDisplay; + SpecialRenderable hamsterJetLightsDisplay; + float readyFlashTimer{}; + float jetFuel{0.f}; + float jetFuelDisplayAmt{0.f}; + float knockoutTimer{0.f}; public: Hamster(const vf2d spawnPos,const std::string_view img,const PlayerControlled IsPlayerControlled=NPC); static const Hamster&GetPlayer(); @@ -129,6 +136,7 @@ public: const bool HasPowerup(const Powerup::PowerupType powerup)const; void RemoveAllPowerups(); const bool IsLethalTerrain(const vf2d pos)const; + const bool IsSolidTerrain(const vf2d pos)const; const bool IsDrowning()const; const bool IsBurning()const; const float GetDrownRatio()const; @@ -137,4 +145,7 @@ public: void SetZ(const float z); static void OnUserDestroy(); void SetDrawingOffsetY(const float offsetY); + const vf2d GetNearestSafeLocation()const; + void SetJetFuel(const float amt); + void Knockout(); }; \ No newline at end of file diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index 092af73..cb405a6 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -52,6 +52,7 @@ void HamsterGame::LoadGraphics(){ _LoadImage("fallometer_outline.png"); _LoadImage("fuelmeter.png"); _LoadImage("fuelbar.png"); + _LoadImage("fuelbar_outline.png"); UpdateMatrixTexture(); } @@ -75,6 +76,7 @@ void HamsterGame::LoadAnimations(){ LoadAnimation(DEFAULT,"hamster.png",{{0,32},{32,32}},0.3f); LoadAnimation(WHEEL_TOP,"hamster.png",{{0,96},{32,96}},0.1f); LoadAnimation(WHEEL_BOTTOM,"hamster.png",{{64,96},{96,96}},0.1f); + LoadAnimation(KNOCKOUT,"hamster.png",{{64,32},{96,32}},0.2f); Animate2D::FrameSequence&waterAnimFrames{(*ANIMATED_TILE_IDS.insert({1384,Animate2D::FrameSequence{0.2f}}).first).second}; for(vf2d&sourcePos:std::vector{{192+16*0,784},{192+16*1,784},{192+16*2,784},{192+16*3,784},{192+16*4,784},{192+16*5,784},{192+16*6,784},{192+16*7,784}}){ waterAnimFrames.AddFrame(Animate2D::Frame{&GetGFX("gametiles.png"),{sourcePos,{16,16}}}); diff --git a/src/HamsterGame.h b/src/HamsterGame.h index 2f096fb..2fab5d7 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -64,6 +64,7 @@ public: WHEEL_BOTTOM, JET_LIGHTS, JET_FLAMES, + KNOCKOUT, }; HamsterGame(); diff --git a/src/HamsterJet.cpp b/src/HamsterJet.cpp index 9fa16e2..d3edb10 100644 --- a/src/HamsterJet.cpp +++ b/src/HamsterJet.cpp @@ -80,19 +80,22 @@ void HamsterJet::Update(const float fElapsedTime){ hamster.SetPos(pos); hamster.SetZ(z+0.03f); if(timer<=0.f){ - state=PLAYER_CONTROL; + state=HAMSTER_CONTROL; HamsterGame::Game().SetZoom(0.6f); easeInTimer=0.6f; } }break; - case PLAYER_CONTROL:{ + case HAMSTER_CONTROL:{ jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; HandleJetControls(); pos=hamster.GetPos(); }break; case LANDING:{ jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; - HandleJetControls(); + if(hamster.IsPlayerControlled)HandleJetControls(); + else{ + //TODO: AI controls here! + } pos=hamster.GetPos(); hamster.SetZ(hamster.GetZ()-fallSpd*fElapsedTime); z=hamster.GetZ(); @@ -104,6 +107,14 @@ void HamsterJet::Update(const float fElapsedTime){ timer=3.f; originalPos=hamster.GetPos(); targetPos={hamster.GetPos().x+128.f,hamster.GetPos().y+32.f}; + Terrain::CrashSpeed crashSpd{Terrain::LIGHT}; + if(fallSpd>4.f)crashSpd=Terrain::MAX; + else if(fallSpd>2.f)crashSpd=Terrain::MEDIUM; + std::pairlandingResult{Terrain::GetFuelDamageTakenAndKnockoutEffect(hamster.GetTerrainStandingOn(),crashSpd)}; + hamster.jetFuel=std::max(0.f,hamster.jetFuel-landingResult.first); + if(landingResult.second)hamster.Knockout(); + if(hamster.IsTerrainStandingOnSolid())hamster.SetPos(hamster.GetNearestSafeLocation()); + if(hamster.jetFuel<=0.f)hamster.powerups.erase(Powerup::JET); } }break; case COMPLETE_LANDING:{ @@ -121,11 +132,11 @@ void HamsterJet::Update(const float fElapsedTime){ void HamsterJet::Draw(){ float drawingOffsetY{0.f}; hamster.SetDrawingOffsetY(0.f); - if((state==PLAYER_CONTROL||state==LANDING)&&z>2.f){ + if((state==HAMSTER_CONTROL||state==LANDING)&&z>2.f){ HamsterGame::Game().SetZ(z/2.f); HamsterGame::Game().tv.DrawRotatedDecal(pos,HamsterGame::GetGFX("aimingTarget.png").Decal(),0.f,HamsterGame::GetGFX("aimingTarget.png").Sprite()->Size()/2); } - if(state==PLAYER_CONTROL){ + if(state==HAMSTER_CONTROL){ drawingOffsetY=util::lerp(48.f,0.f,easeInTimer/0.6f); hamster.SetDrawingOffsetY(util::lerp(48.f,0.f,easeInTimer/0.6f)); } @@ -168,7 +179,7 @@ void HamsterJet::HandleJetControls(){ jetState[BOTTOM_RIGHT]=ON; jetState[TOP_RIGHT]=ON; } - if(aimingDir!=vf2d{}){ + if(aimingDir!=vf2d{}&&hamster.jetFuel>0.f){ hamster.targetRot=aimingDir.norm().polar().y; const vf2d currentVel{hamster.vel}; hamster.vel+=vf2d{currentVel.polar().x+(hamster.GetMaxSpeed()*HamsterGame::Game().GetElapsedTime())/hamster.GetTimeToMaxSpeed(),hamster.rot}.cart(); diff --git a/src/HamsterJet.h b/src/HamsterJet.h index b3b7de5..400e761 100644 --- a/src/HamsterJet.h +++ b/src/HamsterJet.h @@ -47,7 +47,7 @@ public: enum State{ SWOOP_DOWN, RISE_UP, - PLAYER_CONTROL, + HAMSTER_CONTROL, LANDING, COMPLETE_LANDING, }; diff --git a/src/Powerup.cpp b/src/Powerup.cpp index 1180734..85cc9be 100644 --- a/src/Powerup.cpp +++ b/src/Powerup.cpp @@ -38,6 +38,7 @@ All rights reserved. #include "HamsterGame.h" #include "Powerup.h" +#include "Hamster.h" std::vectorPowerup::powerupList; std::unordered_map>Powerup::powerupIds; @@ -112,6 +113,7 @@ const geom2d::rectPowerup::GetPowerupSubimageRect(const PowerupType power return {POWERUP_TILESET_STARTING_POS+vf2d{int(powerupType)*32.f,0.f},{32,32}}; } -void Powerup::OnPowerupObtain(){ +void Powerup::OnPowerupObtain(Hamster&pickupHamster){ spinSpd=0.3f; + if(type==JET)pickupHamster.SetJetFuel(1.f); } \ No newline at end of file diff --git a/src/Powerup.h b/src/Powerup.h index a8ec92e..69107a2 100644 --- a/src/Powerup.h +++ b/src/Powerup.h @@ -41,6 +41,8 @@ All rights reserved. #include "olcUTIL_Geometry2D.h" #include "olcPGEX_TransformedView.h" +class Hamster; + class Powerup{ public: enum PowerupType{ @@ -79,5 +81,5 @@ public: static void UpdatePowerups(const float fElapsedTime); static void DrawPowerups(TransformedView&tv); static const geom2d::rectGetPowerupSubimageRect(const PowerupType powerupType); - void OnPowerupObtain(); + void OnPowerupObtain(Hamster&pickupHamster); }; \ No newline at end of file diff --git a/src/Terrain.cpp b/src/Terrain.cpp index 32d7f72..dd69e88 100644 --- a/src/Terrain.cpp +++ b/src/Terrain.cpp @@ -73,4 +73,82 @@ const std::string Terrain::TerrainToString(const TerrainType type){ return "Void"; } } +} +const std::pairTerrain::GetFuelDamageTakenAndKnockoutEffect(const TerrainType type,const CrashSpeed crashSpeed){ + + const auto GetHardSurfaceCrashResult=[&crashSpeed](){ + switch(crashSpeed){ + case MAX:{ + return std::pair{1.f,true}; + }break; + case MEDIUM:{ + return std::pair{0.8f,false}; + }break; + case LIGHT:{ + return std::pair{0.5f,false}; + }break; + } + }; + const auto GetMediumSurfaceCrashResult=[&crashSpeed](){ + switch(crashSpeed){ + case MAX:{ + return std::pair{0.8f,true}; + }break; + case MEDIUM:{ + return std::pair{0.5f,false}; + }break; + case LIGHT:{ + return std::pair{0.25f,false}; + }break; + } + }; + const auto GetSoftSurfaceCrashResult=[&crashSpeed](){ + switch(crashSpeed){ + case MAX:{ + return std::pair{0.5f,false}; + }break; + case MEDIUM:{ + return std::pair{0.25f,false}; + }break; + case LIGHT:{ + return std::pair{0.25f,false}; + }break; + } + }; + + switch(type){ + case ROCK:{ + return GetHardSurfaceCrashResult(); + }break; + case GRASS:{ + return GetMediumSurfaceCrashResult(); + }break; + case SAND:{ + return GetSoftSurfaceCrashResult(); + }break; + case SWAMP:{ + return GetSoftSurfaceCrashResult(); + }break; + case LAVA:{ + return GetSoftSurfaceCrashResult(); + }break; + case SHORE:{ + return GetMediumSurfaceCrashResult(); + }break; + case OCEAN:{ + return GetMediumSurfaceCrashResult(); + }break; + case FOREST:{ + return GetMediumSurfaceCrashResult(); + }break; + case TUNNEL:{ + return GetHardSurfaceCrashResult(); + }break; + case ICE:{ + return GetHardSurfaceCrashResult(); + }break; + default:{ + return GetMediumSurfaceCrashResult(); + } + } } \ No newline at end of file diff --git a/src/Terrain.h b/src/Terrain.h index 4ec7d06..ef0498e 100644 --- a/src/Terrain.h +++ b/src/Terrain.h @@ -57,5 +57,13 @@ namespace Terrain{ TUNNEL, ICE, }; + enum CrashSpeed{ + MAX, + MEDIUM, + LIGHT, + }; + using FuelDamage=float; + using KnockoutOccurs=bool; const std::string TerrainToString(const TerrainType type); + const std::pairGetFuelDamageTakenAndKnockoutEffect(const TerrainType type,const CrashSpeed crashSpeed); } \ No newline at end of file