From 506b5f99ae5ec0a7c60c5481b4cd1b14ce18cabc Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sat, 17 Aug 2024 00:12:06 -0500 Subject: [PATCH] Add basic collision resolution between Hamsters. --- src/Hamster.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++-- src/Hamster.h | 10 ++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/Hamster.cpp b/src/Hamster.cpp index 1736473..7331df5 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -60,8 +60,20 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ for(Hamster&h:HAMSTER_LIST){ h.animations.UpdateState(h.internalAnimState,fElapsedTime); h.frictionEnabled=true; - if(h.IsPlayerControlled){ - h.HandlePlayerControls(); + h.bumpTimer-=fElapsedTime; + h.HandleCollision(); + switch(h.state){ + case NORMAL:{ + //TODO: NPC controls. + if(h.IsPlayerControlled){ + h.HandlePlayerControls(); + } + }break; + case BUMPED:{ + if(h.bumpTimer<=0.f){ + h.state=NORMAL; + } + }break; } h.TurnTowardsTargetDirection(); h.MoveHamster(); @@ -134,4 +146,38 @@ void Hamster::MoveHamster(){ vel=vf2d{std::max(0.f,currentVel.polar().x-friction*HamsterGame::Game().GetElapsedTime()),currentVel.polar().y}.cart(); } #pragma endregion +} + +void Hamster::HandleCollision(){ + for(Hamster&h:HAMSTER_LIST){ + if(this==&h)continue; + if(geom2d::overlaps(geom2d::circle(GetPos(),GetRadius()),geom2d::circle(h.GetPos(),h.GetRadius()))){ + if(geom2d::line(GetPos(),h.GetPos()).length()==0.f){ //Push these two in random directions, they are on top of each other! + float randDir{util::random(2*geom2d::pi)}; + vf2d collisionResolve1{GetPos()+vf2d{GetRadius(),randDir}.cart()}; + vf2d collisionResolve2{h.GetPos()+vf2d{h.GetRadius(),float(randDir+geom2d::pi)}.cart()}; + pos=collisionResolve1; + h.pos=collisionResolve2; + vel=vf2d{100.f,randDir}.cart(); + h.vel=vf2d{100.f,float(randDir+geom2d::pi)}.cart(); + }else{ + geom2d::linecollisionLine{geom2d::line(GetPos(),h.GetPos())}; + float distance{collisionLine.length()}; + float totalRadii{GetRadius()+h.GetRadius()}; + float bumpDistance{totalRadii-distance}; + vf2d collisionResolve1{GetPos()+vf2d{bumpDistance/2.f,float(collisionLine.vector().polar().y+geom2d::pi)}.cart()}; + vf2d collisionResolve2{h.GetPos()+vf2d{bumpDistance/2.f,collisionLine.vector().polar().y}.cart()}; + pos=collisionResolve1; + h.pos=collisionResolve2; + vel=vf2d{100.f,float(collisionLine.vector().polar().y+geom2d::pi)}.cart(); + h.vel=vf2d{100.f,collisionLine.vector().polar().y}.cart(); + } + state=h.state=BUMPED; + bumpTimer=h.bumpTimer=0.12f; + } + } +} + +const float Hamster::GetRadius()const{ + return collisionRadius; } \ No newline at end of file diff --git a/src/Hamster.h b/src/Hamster.h index 1f22d67..82757ab 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -47,6 +47,11 @@ class Hamster{ NPC=false, }; + enum PlayerState{ + NORMAL, + BUMPED, + }; + static std::vectorHAMSTER_LIST; static const uint8_t MAX_HAMSTER_COUNT; @@ -64,11 +69,14 @@ class Hamster{ float timeToMaxSpd{0.5f}; float friction{400.f}; bool frictionEnabled{false}; + float collisionRadius{12.f}; + float bumpTimer{}; std::string img; Animate2D::Animationanimations; Animate2D::AnimationState internalAnimState; PlayerControlled IsPlayerControlled; static std::optionalplayerHamster; + PlayerState state{NORMAL}; public: Hamster(const vf2d spawnPos,const std::string_view img,const PlayerControlled IsPlayerControlled=NPC); static const Hamster&GetPlayer(); @@ -80,4 +88,6 @@ public: void HandlePlayerControls(); void TurnTowardsTargetDirection(); void MoveHamster(); + void HandleCollision(); + const float GetRadius()const; }; \ No newline at end of file