diff --git a/assets/PBData b/assets/PBData index 416d668..518bbb6 100644 --- a/assets/PBData +++ b/assets/PBData @@ -1 +1 @@ -42976 64212 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 0.8 0.6 OneLoneHam Black \ No newline at end of file +41481 54006 53138 73057 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 1 0.6 OneLoneHam Black \ No newline at end of file diff --git a/assets/highlight_trackselectbutton.png b/assets/highlight_trackselectbutton.png new file mode 100644 index 0000000..1fbec8e Binary files /dev/null and b/assets/highlight_trackselectbutton.png differ diff --git a/assets/sounds/jet_land.wav b/assets/sounds/jet_land.wav deleted file mode 100644 index ffaf07f..0000000 Binary files a/assets/sounds/jet_land.wav and /dev/null differ diff --git a/assets/trackselectbutton.png b/assets/trackselectbutton.png new file mode 100644 index 0000000..858c2a9 Binary files /dev/null and b/assets/trackselectbutton.png differ diff --git a/src/Checkpoint.cpp b/src/Checkpoint.cpp index 27d29b3..999c456 100644 --- a/src/Checkpoint.cpp +++ b/src/Checkpoint.cpp @@ -109,5 +109,4 @@ const vf2d&Checkpoint::GetPos()const{ void Checkpoint::OnCheckpointCollect(){ collectedByPlayerTimer=2.f; animation.ChangeState(internal_animState,AnimationState::CHECKPOINT_CYCLING); - if(Hamster::GetPlayer().CollectedAllCheckpoints())HamsterGame::Game().OnPlayerFinishedRace(); } \ No newline at end of file diff --git a/src/Hamster.cpp b/src/Hamster.cpp index 677a6d4..05e96f6 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -551,8 +551,10 @@ void Hamster::HandleCollision(){ if(IsPlayerControlled)HamsterAI::OnCheckpointCollected(this->pos); if(IsPlayerControlled)checkpoint.OnCheckpointCollect(); if(CollectedAllCheckpoints()){ - finishedRaceTime=HamsterGame::Game().GetRaceTime(); + if(IsPlayerControlled||!GetPlayer().CollectedAllCheckpoints())finishedRaceTime=HamsterGame::Game().GetRaceTime(); + else if(!IsPlayerControlled){finishedRaceTime=GetPlayer().GetFinishedTime()+HamsterGame::Game().GetPlayerDifferentialTime();} if(IsPlayerControlled)HamsterGame::PlaySFX("winneris.ogg"); + if(IsPlayerControlled)HamsterGame::Game().OnPlayerFinishedRace(); }else HamsterGame::PlaySFX(pos,"checkpoint_collection.wav"); lastObtainedCheckpointPos=checkpoint.GetPos(); } @@ -739,7 +741,7 @@ void Hamster::SetPos(const vf2d pos){ movedY=true; } Terrain::TerrainType terrainAtPos{HamsterGame::Game().GetTerrainTypeAtPos(this->pos)}; - if(distanceTravelled-lastFootstep>32.f){ + if(state!=FLYING&&distanceTravelled-lastFootstep>32.f){ lastFootstep=distanceTravelled; if(terrainAtPos==Terrain::ROCK)HamsterGame::PlaySFX(pos,"footsteps_rock.wav"); else if(terrainAtPos==Terrain::SAND||terrainAtPos==Terrain::SWAMP||terrainAtPos==Terrain::FOREST)HamsterGame::PlaySFX(pos,"sfx_movement_footsteps1b.wav"); @@ -1040,4 +1042,12 @@ const size_t Hamster::GetCheckpointsCollectedCount()const{ const std::optionalHamster::GetLastCollectedCheckpoint()const{ return lastObtainedCheckpointPos; +} + +const int Hamster::GetFinishedTime()const{ + return finishedRaceTime.value_or(std::numeric_limits::max()); +} + +const std::string&Hamster::GetHamsterImage()const{ + return colorFilename; } \ No newline at end of file diff --git a/src/Hamster.h b/src/Hamster.h index 09b4a7c..11bded4 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -101,7 +101,6 @@ class Hamster{ float burnTimer{}; float imgScale{1.f}; Pixel shrinkEffectColor{BLACK}; - std::string img; Animate2D::Animationanimations; Animate2D::AnimationState internalAnimState; static std::optionalplayerHamster; @@ -193,4 +192,6 @@ public: const size_t GetCheckpointsCollectedCount()const; const std::optionalGetLastCollectedCheckpoint()const; PlayerControlled IsPlayerControlled; + const int GetFinishedTime()const; + const std::string&GetHamsterImage()const; }; \ No newline at end of file diff --git a/src/HamsterAI.cpp b/src/HamsterAI.cpp index a1af4dc..a4b661c 100644 --- a/src/HamsterAI.cpp +++ b/src/HamsterAI.cpp @@ -133,7 +133,7 @@ void HamsterAI::OnJetBeginLanding(const vi2d pos){ const HamsterAI::ActionOptRef HamsterAI::GetPreviousAction(){ - if(actionInd-1>0)return actionsToPerform[actionInd-1]; + if(actionInd-1>0&&actionInd-10)return actionsToPerform[actionsToPerform.size()-1]; return {}; } diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index 79bce81..f698cf5 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -163,6 +163,8 @@ void HamsterGame::LoadGraphics(){ _LoadImage("highlight_button4.png"); _LoadImage("smallbutton.png"); _LoadImage("smallhighlight_button.png"); + _LoadImage("trackselectbutton.png"); + _LoadImage("highlight_trackselectbutton.png"); } void HamsterGame::LoadAnimations(){ @@ -613,6 +615,7 @@ void HamsterGame::OnPlayerFinishedRace(){ std::cout<<"Finish Time: "<(self->camera.GetPosition(),pos).length()}; float Xdiff{pos.x-self->camera.GetPosition().x}; //If it's positive the sound is to our right... self->audio.Play("assets/sounds/"+filename,std::clamp(1-distanceFromCamera/250.f,0.f,1.f)*self->sfxVol,std::clamp(Xdiff/250.f,-1.f,1.f),util::random_range(0.9f,1.1f)); } +const float HamsterGame::GetPlayerDifferentialTime()const{ + return playerDifferentialTime; +} + int main() { HamsterGame game("Project Hamster"); diff --git a/src/HamsterGame.h b/src/HamsterGame.h index da56f6e..aa0dc23 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -129,6 +129,7 @@ public: std::string hamsterColor{hamsterColorNames[0]}; static void PlaySFX(const std::string&filename); static void PlaySFX(vf2d pos,const std::string&filename); + const float GetPlayerDifferentialTime()const; private: void UpdateGame(const float fElapsedTime); void DrawGame(); @@ -168,6 +169,11 @@ private: GameMode mode{GameMode::SINGLE_RACE}; HamsterNet net; float countdownTimer{}; + using Points=int; + using HamsterInd=size_t; + using FinishTime=int; + std::vector>grandPrixPoints; + std::vector>racerList; #ifndef __EMSCRIPTEN__ #ifndef __DEBUG__ SplashScreen splash; @@ -210,4 +216,5 @@ private: float bgmVol{0.7f}; float sfxVol{0.7f}; int lastDigitPlayedSound{}; + float playerDifferentialTime{}; }; diff --git a/src/HamsterJet.cpp b/src/HamsterJet.cpp index 157702d..708c40e 100644 --- a/src/HamsterJet.cpp +++ b/src/HamsterJet.cpp @@ -126,7 +126,6 @@ void HamsterJet::Update(const float fElapsedTime){ case COMPLETE_LANDING:{ z=util::lerp(3.f,0.f,std::pow(timer/3.f,2)); if(timer<=0.f){ - HamsterGame::PlaySFX(pos,"jet_land.wav"); hamster.hamsterJet.reset(); return; }else{ diff --git a/src/Menu.cpp b/src/Menu.cpp index 0f6fbde..2e635fd 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -195,6 +195,7 @@ std::vectorMenu::GetMenuButtons(const MenuType type){ case OPTIONS:{ buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,-32.f},std::format("BGM: {}",int(round(HamsterGame::Game().bgmVol*100))),"button2.png","highlight_button2.png",Pixel{114,109,163},Pixel{79,81,128},[this](Button&self){ HamsterGame::Game().bgmVol=((int(round(HamsterGame::Game().bgmVol*100))+10)%110)/100.f; + HamsterGame::Game().audio.SetVolume(HamsterGame::Game().bgm["Trevor Lentz - Guinea Pig Hero.ogg"],HamsterGame::Game().bgmVol); self.buttonText=std::format("BGM: {}",int(round(HamsterGame::Game().bgmVol*100))); HamsterGame::Game().emscripten_temp_val=std::to_string(HamsterGame::Game().bgmVol); #ifdef __EMSCRIPTEN__ @@ -252,6 +253,37 @@ std::vectorMenu::GetMenuButtons(const MenuType type){ }); buttons.emplace_back(vf2d{54.f,HamsterGame::SCREEN_FRAME.size.y-24.f},"< Back","button2.png","highlight_button2.png",Pixel{114,109,163},Pixel{79,81,128},[this](Button&self){Transition(SHIFT_LEFT,MAIN_MENU,0.5f);}); }break; + case GAMEPLAY_RESULTS:{ + switch(HamsterGame::Game().GetGameMode()){ + case HamsterGame::GameMode::SINGLE_RACE:{ + int MAX_SIMULATION_COUNT{10000}; + HamsterGame::Game().playerDifferentialTime=0.f; + while(MAX_SIMULATION_COUNT>0){ + bool allHamstersFinished{true}; + for(Hamster&hamster:Hamster::GetHamsters()){ + if(!hamster.CollectedAllCheckpoints())allHamstersFinished=false; + } + if(allHamstersFinished)break; + HamsterGame::Game().SetElapsedTime(1/30.f); + HamsterGame::Game().UpdateGame(1/30.f); + HamsterGame::Game().playerDifferentialTime+=33; + MAX_SIMULATION_COUNT--; + } + HamsterGame::Game().racerList.clear(); + for(size_t ind{0};Hamster&hamster:Hamster::GetHamsters()){ + HamsterGame::Game().racerList.emplace_back(std::pair{hamster.GetFinishedTime(),ind}); + ind++; + } + std::sort(HamsterGame::Game().racerList.begin(),HamsterGame::Game().racerList.end(),[](const std::pair&hamster1,const std::pair&hamster2){return hamster1.first0)selectedButton=0; } void Menu::DrawTransition(HamsterGame&game){ + if(currentTransition==SIMPLE)return; if(currentTransition==FADE_OUT){ if(menuTimer>=originalMenuTimer/2){//Fading out from old scene. game.SetDrawTarget(1U); @@ -349,7 +380,6 @@ void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ }break; case MAIN_MENU:{ game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background1.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); - game.DrawRotatedDecal(pos,game.GetGFX("button.png").Decal(),0.f,game.GetGFX("button.png").Sprite()->Size()/2); DrawButtons(pos); game.border.Draw(); }break; @@ -398,6 +428,21 @@ void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ } } }break; + case GAMEPLAY_RESULTS:{ + for(size_t ind{0};const auto&[finishTime,hamsterInd]:HamsterGame::Game().racerList){ + const Hamster&hamster{Hamster::GetHamsters()[hamsterInd]}; + game.DrawShadowStringDecal(vf2d{game.SCREEN_FRAME.pos.x+game.SCREEN_FRAME.size.x/2-64.f,game.SCREEN_FRAME.pos.y+game.SCREEN_FRAME.size.y/2-100.f+ind*16},std::format("{}.",ind+1)); + game.DrawPartialRotatedDecal(vf2d{game.SCREEN_FRAME.pos.x+game.SCREEN_FRAME.size.x/2-64.f+24.f,game.SCREEN_FRAME.pos.y+game.SCREEN_FRAME.size.y/2-100.f+ind*16+6.f},game.GetGFX(hamster.GetHamsterImage()).Decal(),0.f,{8.f,6.f},{64.f,64.f},{16.f,12.f}); + std::string timeStr{util::timerStr(finishTime)}; + vf2d timeStrSize{game.GetTextSize(timeStr)}; + game.DrawShadowStringDecal(vf2d{game.SCREEN_FRAME.pos.x+game.SCREEN_FRAME.size.x/2+64.f-timeStrSize.x,game.SCREEN_FRAME.pos.y+game.SCREEN_FRAME.size.y/2-100.f+ind*16},timeStr); + ind++; + } + DrawButtons(pos); + }break; + case AFTER_RACE_MENU:{ + DrawButtons(pos); + }break; case OPTIONS:{ game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background2.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); DrawButtons(pos); @@ -406,12 +451,6 @@ void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ case QUIT:{ game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background3.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); }break; - case GAMEPLAY:{ - game.DrawGame(); - }break; - case GAMEPLAY_RESULTS:{ - game.DrawGame(); - }break; case LOADING:{ game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background3.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); game.FillRectDecal(pos+vf2d{32.f,game.SCREEN_FRAME.size.y-64.f}+vf2d{2.f,2.f},vf2d{loadingPct*(game.SCREEN_FRAME.size.x-64),32.f},BLACK); @@ -434,6 +473,7 @@ void Menu::OnLevelLoaded(){ Checkpoint::Initialize(HamsterGame::Game().checkpointsTemp); HamsterGame::Game().audio.SetVolume(HamsterGame::Game().bgm.at(HamsterGame::Game().currentMap.value().GetData().GetBGM()),HamsterGame::Game().bgmVol); + HamsterGame::Game().audio.Stop(HamsterGame::Game().bgm["Trevor Lentz - Guinea Pig Hero.ogg"]); HamsterGame::Game().audio.Play(HamsterGame::Game().bgm.at(HamsterGame::Game().currentMap.value().GetData().GetBGM()),true); HamsterGame::Game().net.SetName(HamsterGame::Game().playerName); HamsterGame::Game().net.SetColor(HamsterGame::Game().hamsterColor); diff --git a/src/Menu.h b/src/Menu.h index 677022c..3a2cd04 100644 --- a/src/Menu.h +++ b/src/Menu.h @@ -57,6 +57,7 @@ class Menu{ void OnClick(); void Draw(HamsterGame&game,const vf2d&pos,std::optional>selectedButton={})const; }; +public: enum MenuType{ INITIALIZE, TITLE_SCREEN, @@ -77,11 +78,13 @@ class Menu{ SHIFT_UP, SHIFT_DOWN, FADE_OUT, + SIMPLE, }; enum MenuState{ NORMAL, TRANSITIONING, }; +private: MenuState currentState{NORMAL}; TransitionType currentTransition{FADE_OUT}; MenuType currentMenu{INITIALIZE}; @@ -100,7 +103,6 @@ class Menu{ std::string selectedMap{"StageI.tmx"}; std::optionalselectedButton; int lastHovered{}; - void Transition(const TransitionType type,const MenuType gotoMenu,const float transitionTime); void Draw(HamsterGame&game,const MenuType menu,const vi2d pos); void DrawTransition(HamsterGame&game); void OnMenuTransition(); @@ -112,4 +114,5 @@ public: void OnLevelLoaded(); void UpdateLoadingProgress(const float pctLoaded); void OnTextEntryComplete(const std::string&text); + void Transition(const TransitionType type,const MenuType gotoMenu,const float transitionTime); }; \ No newline at end of file diff --git a/src/olcPGEX_MiniAudio.h b/src/olcPGEX_MiniAudio.h index c0646f6..1986356 100644 --- a/src/olcPGEX_MiniAudio.h +++ b/src/olcPGEX_MiniAudio.h @@ -328,7 +328,7 @@ namespace olc { if(ma_sound_is_playing(vecSounds.at(id))) { - ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0); + //ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0); return; } @@ -355,7 +355,7 @@ namespace olc void MiniAudio::Stop(const int id) { ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0); - ma_sound_stop_with_fade_in_milliseconds(vecSounds.at(id),300); + ma_sound_stop(vecSounds.at(id)); } void MiniAudio::Pause(const int id) diff --git a/src/olcPixelGameEngine.h b/src/olcPixelGameEngine.h index bca52a6..1701aa7 100644 --- a/src/olcPixelGameEngine.h +++ b/src/olcPixelGameEngine.h @@ -1037,6 +1037,7 @@ namespace olc uint32_t GetFPS() const; // Gets last update of elapsed time float GetElapsedTime() const; + void SetElapsedTime(const float fElapsedTime); // Gets Actual Window size const olc::vi2d& GetWindowSize() const; // Gets pixel scale @@ -2154,6 +2155,8 @@ namespace olc float PixelGameEngine::GetElapsedTime() const { return fLastElapsed; } + void PixelGameEngine::SetElapsedTime(const float fElapsedTime) + { fLastElapsed=fElapsedTime; } const olc::vi2d& PixelGameEngine::GetWindowSize() const { return vWindowSize; } diff --git a/src/util.cpp b/src/util.cpp index ae2d0b4..ebd2860 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -57,6 +57,7 @@ vf2d olc::util::pointTo(vf2d posFrom,vf2d posTo){ return geom2d::line(posFrom,posTo).vector().norm(); } std::string olc::util::timerStr(int ms){ + if(ms==std::numeric_limits::max())return "DNF"; int millis=ms%1000; int seconds=ms/1000; int hours=seconds/3600;