diff --git a/LORE.txt b/LORE.txt new file mode 100644 index 0000000..5158dbf --- /dev/null +++ b/LORE.txt @@ -0,0 +1,14 @@ +(?) discovered a strange floating energy orb while going for their morning run. Curious, they approached it and came into contact with it, granting them new powers. + +Excited by this discovery (?) decided to share it with the rest of their hamster friends. + +A couple villain/scientist hamsters realize that this has become a stubby legs race with great potential and recruited world class hamsters to run and obtain these new orbs for research. + + + + +Hamsters are experimenting with new technologies to emphasize their running capabilities beyond what was originally thought possible. + + + +Hamsters from all around Hamster planet have been recruited to scavenge for \ No newline at end of file diff --git a/WEB.txt b/WEB.txt new file mode 100644 index 0000000..76a397e --- /dev/null +++ b/WEB.txt @@ -0,0 +1,28 @@ +Leaderboard - Request driven + +Packet of information: Name, Time, Map + +WebSocket: Multiplayer + +Connects to websocket on the web version +Start a race, sends to server when race started +Similar message + +Time calculation on server-side. + +Pausing and quitting / force quit. + +Force Disconnect + + +String Form. + +Client Side: Timestamp when start and when sending. + +Leaderboard: Retrieve in-game. + + + + +Stretch Goal +============ diff --git a/src/Hamster.cpp b/src/Hamster.cpp index 9f544aa..701ccf9 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -65,15 +65,17 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.HandleCollision(); switch(h.state){ case NORMAL:{ - if(h.IsPlayerControlled){ - h.HandlePlayerControls(); - }else{ - //TODO: NPC controls. + if(h.bumpTimer<=0.f){ + if(h.IsPlayerControlled){ + h.HandlePlayerControls(); + }else{ + //TODO: NPC controls. + } } }break; case BUMPED:{ if(h.bumpTimer<=0.f){ - h.state=NORMAL; + h.SetState(NORMAL); } }break; case DROWNING:{ @@ -83,7 +85,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ } else{ h.waitTimer=4.f; - h.state=WAIT; + h.SetState(WAIT); } }break; case WAIT:{ @@ -95,7 +97,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.lastSafeLocation=h.GetNearestSafeLocation(); } h.SetPos(h.lastSafeLocation.value()); - h.state=NORMAL; + h.SetState(NORMAL); h.RemoveAllPowerups(); } }break; @@ -105,13 +107,13 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.imgScale=std::max(0.f,h.imgScale-0.5f*fElapsedTime); }else{ h.waitTimer=4.f; - h.state=WAIT; + h.SetState(WAIT); } }break; case KNOCKOUT:{ h.knockoutTimer-=fElapsedTime; if(h.knockoutTimer<=0.f){ - h.state=NORMAL; + h.SetState(NORMAL); h.animations.ChangeState(h.internalAnimState,HamsterGame::DEFAULT); } }break; @@ -126,10 +128,10 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.lastSafeLocation=h.GetPos(); } if(h.drownTimer>=h.DEFAULT_DROWN_TIME&&h.state!=DROWNING&&h.state!=WAIT){ - h.state=DROWNING; + h.SetState(DROWNING); } if(h.burnTimer>=h.DEFAULT_BURN_TIME&&h.state!=BURNING&&h.state!=WAIT){ - h.state=BURNING; + h.SetState(BURNING); } } if(h.hamsterJet.has_value())h.hamsterJet.value().Update(fElapsedTime); @@ -214,6 +216,10 @@ void Hamster::DrawOverlay(){ } 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().hamsterJet.has_value()){ + const Terrain::FuelDamage jetFuelLandingCost{std::min(GetPlayer().jetFuelDisplayAmt,Terrain::GetFuelDamageTakenAndKnockoutEffect(GetPlayer().GetTerrainHoveringOver(),GetPlayer().hamsterJet.value().GetLandingSpeed()).first)}; + 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*jetFuelLandingCost},{1.f,1.f},{255,0,0,192}); + } 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); } @@ -254,7 +260,7 @@ void Hamster::HandlePlayerControls(){ } if(HamsterGame::Game().GetKey(SPACE).bPressed){ if(lastTappedSpace<=0.6f&&HasPowerup(Powerup::JET)){ - state=FLYING; + SetState(FLYING); lastSafeLocation.reset(); hamsterJet.emplace(*this); } @@ -312,7 +318,6 @@ void Hamster::HandleCollision(){ vel=vf2d{GetBumpAmount(),float(collisionLine.vector().polar().y+geom2d::pi)}.cart(); h.vel=vf2d{GetBumpAmount(),collisionLine.vector().polar().y}.cart(); } - state=h.state=BUMPED; bumpTimer=h.bumpTimer=0.12f; } } @@ -335,6 +340,10 @@ const Terrain::TerrainType Hamster::GetTerrainStandingOn()const{ return HamsterGame::Game().GetTerrainTypeAtPos(GetPos()); } +const Terrain::TerrainType Hamster::GetTerrainHoveringOver()const{ + return HamsterGame::Game().GetTerrainTypeAtPos(GetPos()); +} + const bool Hamster::IsTerrainStandingOnSolid()const{ return HamsterGame::Game().IsTerrainSolid(GetPos()); } @@ -374,6 +383,9 @@ const float Hamster::GetMaxSpeed()const{ case Terrain::FOREST:{ if(!HasPowerup(Powerup::FOREST))finalMaxSpd*=0.50f; }break; + case Terrain::VOID:{ + finalMaxSpd*=0.10f; + }break; } if(HasPowerup(Powerup::WHEEL))finalMaxSpd*=1.5f; if(hamsterJet.has_value()){ @@ -520,11 +532,15 @@ void Hamster::SetJetFuel(const float amt){ } void Hamster::Knockout(){ - state=KNOCKOUT; + SetState(KNOCKOUT); knockoutTimer=4.f; animations.ChangeState(internalAnimState,HamsterGame::KNOCKOUT); } const float Hamster::GetSpeed()const{ return vel.mag(); +} + +void Hamster::SetState(const HamsterState state){ + this->state=state; } \ No newline at end of file diff --git a/src/Hamster.h b/src/Hamster.h index 9fef6bb..703566b 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -149,4 +149,6 @@ public: void SetJetFuel(const float amt); void Knockout(); const float GetSpeed()const; + const Terrain::TerrainType GetTerrainHoveringOver()const; + void SetState(const HamsterState state); }; \ No newline at end of file diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index c8625ca..12bcb3b 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -236,17 +236,15 @@ const Terrain::TerrainType HamsterGame::GetTerrainTypeAtPos(const vf2d pos)const const bool HamsterGame::IsTerrainSolid(const vf2d pos)const{ if(!IsInBounds(pos))return true; - bool tileIsBlank{true}; for(const LayerTag&layer:currentMap.value().GetData().GetLayers()){ int tileX{int(floor(pos.x)/16)}; int tileY{int(floor(pos.y)/16)}; if(tileX<=0||tileX>=currentMap.value().GetData().GetMapData().MapSize.x||tileY<=0||tileY>=currentMap.value().GetData().GetMapData().MapSize.y)break; int tileID{layer.tiles[tileY][tileX]-1}; if(tileID==-1)continue; - tileIsBlank=false; if(currentTileset.value().GetData().GetTerrainData().count(tileID)&¤tTileset.value().GetData().GetTerrainData().at(tileID).first==Terrain::SolidType::SOLID)return true; } - return tileIsBlank; + return false; } void HamsterGame::DrawLevelTiles(){ diff --git a/src/HamsterJet.cpp b/src/HamsterJet.cpp index f6a7d2a..5f3f5ce 100644 --- a/src/HamsterJet.cpp +++ b/src/HamsterJet.cpp @@ -49,7 +49,6 @@ void HamsterJet::Update(const float fElapsedTime){ jet.Update(fElapsedTime); lights.Update(fElapsedTime); timer=std::max(0.f,timer-fElapsedTime); - easeInTimer=std::max(0.f,easeInTimer-fElapsedTime); lastTappedSpace+=fElapsedTime; switch(state){ case SWOOP_DOWN:{ @@ -86,10 +85,12 @@ void HamsterJet::Update(const float fElapsedTime){ } }break; case HAMSTER_CONTROL:{ + easeInTimer=std::max(0.f,easeInTimer-fElapsedTime); jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; HandleJetControls(); }break; case LANDING:{ + easeInTimer=std::min(0.6f,easeInTimer+fElapsedTime); jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; if(hamster.IsPlayerControlled)HandleJetControls(); else{ @@ -101,15 +102,12 @@ void HamsterJet::Update(const float fElapsedTime){ if(hamster.GetZ()<=0.f){ hamster.SetZ(0.f); state=COMPLETE_LANDING; - hamster.state=Hamster::NORMAL; + hamster.SetState(Hamster::NORMAL); HamsterGame::Game().SetZoom(1.f); 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)}; + std::pairlandingResult{Terrain::GetFuelDamageTakenAndKnockoutEffect(hamster.GetTerrainStandingOn(),GetLandingSpeed())}; hamster.jetFuel=std::max(0.f,hamster.jetFuel-landingResult.first); if(landingResult.second)hamster.Knockout(); if(hamster.IsTerrainStandingOnSolid())hamster.SetPos(hamster.GetNearestSafeLocation()); @@ -135,7 +133,7 @@ void HamsterJet::Draw(){ 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==HAMSTER_CONTROL){ + if(state==HAMSTER_CONTROL||state==LANDING){ drawingOffsetY=util::lerp(48.f,0.f,easeInTimer/0.6f); hamster.SetDrawingOffsetY(util::lerp(48.f,0.f,easeInTimer/0.6f)); } @@ -194,6 +192,7 @@ void HamsterJet::HandleJetControls(){ if(HamsterGame::Game().GetKey(SPACE).bPressed){ if(lastTappedSpace<=0.6f){ state=LANDING; + easeInTimer=0.f; } lastTappedSpace=0.f; } @@ -215,4 +214,10 @@ void HamsterJet::DrawOverlay()const{ void HamsterJet::SetPos(const vf2d pos){ this->pos=pos; +} + +Terrain::CrashSpeed HamsterJet::GetLandingSpeed()const{ + if(fallSpd>4.f)return Terrain::MAX; + if(fallSpd>2.f)return Terrain::MEDIUM; + else return Terrain::LIGHT; } \ No newline at end of file diff --git a/src/HamsterJet.h b/src/HamsterJet.h index 6805d8b..97757db 100644 --- a/src/HamsterJet.h +++ b/src/HamsterJet.h @@ -41,6 +41,9 @@ All rights reserved. #include "SpecialRenderable.h" class Hamster; +namespace Terrain{ + enum CrashSpeed; +}; class HamsterJet{ public: @@ -85,4 +88,5 @@ public: void HandleJetControls(); const State GetState()const; void SetPos(const vf2d pos); + Terrain::CrashSpeed GetLandingSpeed()const; }; \ No newline at end of file diff --git a/src/TODO.txt b/src/TODO.txt index e74870c..f485a7a 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -72,6 +72,14 @@ Fall-o-meter Hamster Rescue Boat +AI +=== +Pre-record movement nodes every X amount of seconds. +AI will move towards those nodes as best they can. If they get stuck for some amount of time, attempt moving forward with next nodes. (Give them like 5 extra seconds per node than intended) +Record each collection of a powerup/launch moment as these are important nodes for AI to be on. (Maybe "Cheat" the AI a little if thier stuck node counte i really high by teleporting them when they are off-screen) + + + LORE ===================