From 363ad229bbc4f4689ae576f957da04091eca563e Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sat, 24 Aug 2024 06:49:47 -0500 Subject: [PATCH] Keep persistent data about hamsters between map loads. Add menu backgrounds. --- assets/background1.png | Bin 0 -> 652 bytes assets/background2.png | Bin 0 -> 652 bytes assets/background3.png | Bin 0 -> 650 bytes assets/background4.png | Bin 0 -> 652 bytes assets/background5.png | Bin 0 -> 652 bytes assets/{hamster.png => hamster1.png} | Bin src/Hamster.cpp | 29 +++++++++- src/Hamster.h | 3 + src/HamsterGame.cpp | 31 +++++++---- src/HamsterGame.h | 15 +++++ src/HamsterJet.cpp | 4 +- src/HamsterLeaderboard.h | 50 +++++++++++++++++ src/HamsterNet.cpp | 2 +- src/HamsterNet.h | 2 +- src/TODO.txt | 79 +++++++++++++++++++++++++++ 15 files changed, 196 insertions(+), 19 deletions(-) create mode 100644 assets/background1.png create mode 100644 assets/background2.png create mode 100644 assets/background3.png create mode 100644 assets/background4.png create mode 100644 assets/background5.png rename assets/{hamster.png => hamster1.png} (100%) create mode 100644 src/HamsterLeaderboard.h diff --git a/assets/background1.png b/assets/background1.png new file mode 100644 index 0000000000000000000000000000000000000000..81fe42e9907d0f1bb93f8dc3ed12b77122236467 GIT binary patch literal 652 zcmV;70(1R|P)EX>4Tx04R}tkv&MmKpe$iQ^lec2P=p;WT;Mdu_BJ8ibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@W3*RLwHd ziMW`{uZn%I2w(&Qh$1L4Q%`0Vv+x{W_we!cF2b|C&;29%C|}6A ztZ?4qtXAu+eNXeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003l3L_t(I%VXTqGvhx41%QQtfq~)M)hA?W=F*m7U}B&U zFrk~sr7eTkMs#^5WJzpnLh>vy#<#0a2pWQ{7ONMC2~2b~)DJ{rqKF;Q|2Nry@fHa~8+|0000EX>4Tx04R}tkv&MmKpe$iQ^lec2P=p;WT;Mdu_BJ8ibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@W3*RLwHd ziMW`{uZn%I2w(&Qh$1L4Q%`0Vv+x{W_we!cF2b|C&;29%C|}6A ztZ?4qtXAu+eNXeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003l3L_t(I%VR9cUHqSc0>Hw+z`$_#$z8HEE6XS|FfmXF zn9xmBmQluQBf2~jvLrS(A$b-UIWh*QAax$P;3BI0ui4f m*yLDEX>4Tx04R}tkv&MmKpe$iQ^lec2P=p;WT;Mdu_BJ8ibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@W3*RLwHd ziMW`{uZn%I2w(&Qh$1L4Q%`0Vv+x{W_we!cF2b|C&;29%C|}6A ztZ?4qtXAu+eNXeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003f1L_t(I%VT6*Dvm#6Lom4Jo zOz0-wxpfS$jp*`B$dcIDgydOZ3>7sif`%Zg#p(rO0ux;g^#hTZsH2?=C^mp9fr!r# kY;r8bDx_H$FjAVG0j)GAm#;|Mg8%>k07*qoM6N<$f_UH!CjbBd literal 0 HcmV?d00001 diff --git a/assets/background4.png b/assets/background4.png new file mode 100644 index 0000000000000000000000000000000000000000..b978bc9abe8588977a79f8af770a9b19f75cfce0 GIT binary patch literal 652 zcmV;70(1R|P)EX>4Tx04R}tkv&MmKpe$iQ^lec2P=p;WT;Mdu_BJ8ibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@W3*RLwHd ziMW`{uZn%I2w(&Qh$1L4Q%`0Vv+x{W_we!cF2b|C&;29%C|}6A ztZ?4qtXAu+eNXeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003l3L_t(I%VSh+?fTC^0bpTZU|?X^RwGOE&#Si>m>4Jo zOz0;5ym||-jp*`B$dcIDgydOZ40dfbf`%Zg#p(rO0ux;g^#hTZsH2?=C^mp9fr!r# mY;r8bDx_H$un-%4xBvhhOe*^z9F*_?0000EX>4Tx04R}tkv&MmKpe$iQ^lec2P=p;WT;Mdu_BJ8ibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfc5qU3krMxx6k5c1aNLh~_a1le0HIlBs@W3*RLwHd ziMW`{uZn%I2w(&Qh$1L4Q%`0Vv+x{W_we!cF2b|C&;29%C|}6A ztZ?4qtXAu+eNXeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003l3L_t(I%VWH~bM}7*3IGcO0|SGk!3(l9KffTsz{Efy zU_v+X`2`8QHloWjAxmOo6Ow0vF(eIM5Hti?EmkiO6PV~~s2_;LL>=v1K(PT-2}FE` mV3T7ZRw2#8fQ8uT!vz31TPTvvqBj8m0000Hamster::HAMSTER_LIST; const uint8_t Hamster::MAX_HAMSTER_COUNT{100U}; const uint8_t Hamster::NPC_HAMSTER_COUNT{5U}; const std::vectorHamster::NPC_HAMSTER_IMAGES{ - "hamster.png", + "hamster1.png", "hamster2.png", "hamster3.png", "hamster4.png", @@ -57,11 +57,11 @@ const std::vectorHamster::NPC_HAMSTER_IMAGES{ "hamster7.png", "hamster8.png", }; -std::string Hamster::PLAYER_HAMSTER_IMAGE{"hamster.png"}; +std::string Hamster::PLAYER_HAMSTER_IMAGE{"hamster1.png"}; std::optionalHamster::playerHamster; Hamster::Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled) -:pos(spawnPos),IsPlayerControlled(IsPlayerControlled),randomId(util::random()){ +:pos(spawnPos),IsPlayerControlled(IsPlayerControlled),randomId(util::random()),colorFilename(img){ animations=HamsterGame::GetAnimations(img); animations.ChangeState(internalAnimState,AnimationState::DEFAULT); } @@ -297,6 +297,28 @@ void Hamster::MoveHamstersToSpawn(const geom2d::rectstartingLoc){ aiFileCount++; MAX_AI_FILES--; } + + struct HamsterPersistentData{ + HamsterAI::AIType aiLevel; + std::string colorFilename; + Hamster::PlayerControlled IsPlayerControlled; + int points; + }; + + std::vectorpersistentData; + size_t previousHamsterCount{HAMSTER_LIST.size()}; + for(int i:std::ranges::iota_view(0U,HAMSTER_LIST.size())){ + Hamster&hamster{HAMSTER_LIST[i]}; + //Keep persistent data available and reset Hamster. + persistentData.emplace_back(hamster.aiLevel,hamster.colorFilename,hamster.IsPlayerControlled,hamster.points); + } + + HAMSTER_LIST.clear(); + for(HamsterPersistentData&data:persistentData){ + Hamster&newHamster{HAMSTER_LIST.emplace_back(vf2d{},data.colorFilename,data.IsPlayerControlled)}; + newHamster.points=data.points; + } + for(Hamster&hamster:HAMSTER_LIST){ hamster.SetPos(vf2d{util::random_range(startingLoc.pos.x,startingLoc.pos.x+startingLoc.size.x),util::random_range(startingLoc.pos.y,startingLoc.pos.y+startingLoc.size.y)}); @@ -538,6 +560,7 @@ void Hamster::HandleCollision(){ FloatingText::CreateFloatingText(pos,std::format("{} / {}",checkpointsCollected.size(),Checkpoint::GetCheckpoints().size()),{WHITE,GREEN},{1.5f,2.f}); if(IsPlayerControlled)HamsterAI::OnCheckpointCollected(this->pos); if(IsPlayerControlled)checkpoint.OnCheckpointCollect(); + if(CollectedAllCheckpoints()){finishedRaceTime=HamsterGame::Game().GetRaceTime();} } } if(GetState()==NORMAL){ diff --git a/src/Hamster.h b/src/Hamster.h index 15f3d12..030a007 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -129,6 +129,9 @@ class Hamster{ float boostTimer{}; float canCollectWheelPowerupTimer{}; float SEARCH_RANGE{1.f}; + std::string colorFilename; + int points{}; + std::optionalfinishedRaceTime; HamsterAI::AIType aiLevel{HamsterAI::AIType::NORMAL}; public: Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled=NPC); diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index c64ed49..234dba5 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -96,6 +96,11 @@ void HamsterGame::LoadGraphics(){ _LoadImage("radaricons.png"); _LoadImage("boost.png"); _LoadImage("boost_outline.png"); + _LoadImage("background1.png"); + _LoadImage("background2.png"); + _LoadImage("background3.png"); + _LoadImage("background4.png"); + _LoadImage("background5.png"); } void HamsterGame::LoadAnimations(){ @@ -114,13 +119,7 @@ void HamsterGame::LoadAnimations(){ } ANIMATIONS[std::string(img)].AddState(state,newAnimation); }; - - LoadAnimation(AnimationState::DEFAULT,"hamster.png",{{0,32},{32,32}},0.3f); - LoadAnimation(AnimationState::WHEEL_TOP,"hamster.png",{{0,96},{32,96}},0.1f); - LoadAnimation(AnimationState::WHEEL_BOTTOM,"hamster.png",{{64,96},{96,96}},0.1f); - LoadAnimation(AnimationState::KNOCKOUT,"hamster.png",{{64,32},{96,32}},0.2f); - LoadAnimation(AnimationState::SIDE_VIEW,"hamster.png",{{0,0},{32,0}},0.3f); - for(int i:std::ranges::iota_view(2,9)){ + for(int i:std::ranges::iota_view(1,9)){ LoadAnimation(AnimationState::DEFAULT,std::format("hamster{}.png",i),{{0,32},{32,32}},0.3f); LoadAnimation(AnimationState::WHEEL_TOP,std::format("hamster{}.png",i),{{0,96},{32,96}},0.1f); LoadAnimation(AnimationState::WHEEL_BOTTOM,std::format("hamster{}.png",i),{{64,96},{96,96}},0.1f); @@ -369,11 +368,9 @@ bool HamsterGame::OnUserUpdate(float fElapsedTime){ net.InitSession(); netInitialized=true; - net.SetName("Sig"); - net.SetColor("Yellow"); - LoadLevel("StageV.tmx"); //THIS IS TEMPORARY. - camera.SetTarget(Hamster::GetPlayer().GetPos()); - net.StartRace(currentMapName); + net.SetName("OneLoneHamster"); + net.SetColor(hamsterColorNames[0]); + SetupAndStartRace(); } runTime+=fElapsedTime; @@ -658,6 +655,16 @@ const HamsterGame::GameMode HamsterGame::GetGameMode(){ return mode; } +void HamsterGame::SetupAndStartRace(){ + LoadLevel("StageV.tmx"); //THIS IS TEMPORARY. + camera.SetTarget(Hamster::GetPlayer().GetPos()); + net.StartRace(currentMapName); +} + +const int HamsterGame::GetRaceTime(){ + return net.GetCurrentRaceTime(); +} + int main() { HamsterGame game("Project Hamster"); diff --git a/src/HamsterGame.h b/src/HamsterGame.h index 9d36ab3..260dec3 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -101,6 +101,7 @@ public: const GameMode GetGameMode(); static void SavePB(const std::string&mapName,int ms); static void LoadPBs(); + const int GetRaceTime(); private: void UpdateGame(const float fElapsedTime); void DrawGame(); @@ -113,6 +114,7 @@ private: static HamsterGame*self; Border border; void DrawLevelTiles(); + void SetupAndStartRace(); std::optionalcurrentMap; std::optionalcurrentTileset; double runTime{}; @@ -158,6 +160,19 @@ private: "StageX.tmx", "StageXI.tmx", "StageXII.tmx", + "Grand Prix I", + "Grand Prix II", + "Grand Prix III", }; std::string emscripten_temp_val{"123456"}; + std::vectorhamsterColorNames{ + "Yellow", + "Pink", + "Cyan", + "Black", + "Green", + "Purple" + "Red", + "Blue", + }; }; \ No newline at end of file diff --git a/src/HamsterJet.cpp b/src/HamsterJet.cpp index db9a780..d25b0c3 100644 --- a/src/HamsterJet.cpp +++ b/src/HamsterJet.cpp @@ -192,10 +192,10 @@ void HamsterJet::HandlePlayerControls(){ hamster.vel=vf2d{std::min(hamster.GetMaxSpeed(),hamster.vel.polar().x),hamster.vel.polar().y}.cart(); hamster.frictionEnabled=false; } - if(HamsterGame::Game().GetKey(UP).bHeld){ + if(GetState()==LANDING&&HamsterGame::Game().GetKey(UP).bHeld){ fallSpd=std::min(5.f,fallSpd+5.f*HamsterGame::Game().GetElapsedTime()); } - if(HamsterGame::Game().GetKey(DOWN).bHeld){ + if(GetState()==LANDING&&HamsterGame::Game().GetKey(DOWN).bHeld){ fallSpd=std::max(1.f,fallSpd-5.f*HamsterGame::Game().GetElapsedTime()); } if(HamsterGame::Game().GetKey(SPACE).bPressed){ diff --git a/src/HamsterLeaderboard.h b/src/HamsterLeaderboard.h new file mode 100644 index 0000000..67bbe96 --- /dev/null +++ b/src/HamsterLeaderboard.h @@ -0,0 +1,50 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions or derivations of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions or derivative works in binary form must reproduce the above +copyright notice. This list of conditions and the following disclaimer must be +reproduced in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once +#include "Hamster.h" + +class HamsterLeaderboard{ + class HamsterRanking{ + std::reference_wrapperhamster; + float ranking; //The higher the ranking, the higher the hamster is placed. + }; + std::vectorhamsterRanking; +public: + void OnRaceStart(); + void OnRaceFinished(); +}; \ No newline at end of file diff --git a/src/HamsterNet.cpp b/src/HamsterNet.cpp index 2e528fe..1a83593 100644 --- a/src/HamsterNet.cpp +++ b/src/HamsterNet.cpp @@ -227,7 +227,7 @@ bool HamsterNet::StartRace(const std::string& map) return (hamsterNet__startRace() == 1); } -int HamsterNet::GetCurrentRaceTime(const std::string& map){ +int HamsterNet::GetCurrentRaceTime(){ std::chrono::duration duration = std::chrono::system_clock::now() - m_tp1; return static_cast(duration.count()); } diff --git a/src/HamsterNet.h b/src/HamsterNet.h index c4718ff..7f8700b 100644 --- a/src/HamsterNet.h +++ b/src/HamsterNet.h @@ -29,7 +29,7 @@ public: bool StartRace(const std::string& map); using FinishTime=int; - int GetCurrentRaceTime(const std::string& map); + int GetCurrentRaceTime(); std::pair FinishRace(); std::vector GetLeaderboard(const std::string& map, const int offset = 0, const int limit = 100, const std::string& sortBy = "time", bool ascending = true); diff --git a/src/TODO.txt b/src/TODO.txt index 9af7912..ffe218f 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -154,6 +154,85 @@ Stage 11: Boss Battle #3 Alternate - nene Stage 12: Boss Battle #5 V2 - nene +Live Placement Tracking +Pulsating Animation based on terrain walking across + +Sound Effects + +Footstep sounds(Grass, Sand, Rock, Shore (Shared with Lava and Swamp), Ocean) +Hamster Wheel sounds (Rolling) +Hamster Jet Idle Sound +Hamster Jet Rockets Sound +Hamster Jet Landing Sound +Powerup Collection Sound +Hamster Wheel Boost Sound +Checkpoint Collection Sound + +Hamster Jet Launch Command Sound +Fail to Boost/Jet Launch command sound + +Race Finish sound +Race Start sound +Race Countdown timer sound + +Menu Select/Back Sound + +========================== +Stages VI - XII: 7 Stages (1 hour each, 7 hours total) +Menu Navigations (2 hours) +Grand Prix Management (1 hour) +Unlocks (1 hour) +Leaderboard Management (1 hour) + +Menus +=========== +Title Screen +Main Menu + Grand Prix + Single Race (Locked behind Grand Prix I) + Options + Quit + (Bottom of Main Menu shows Research Progress) + + Races: + 1st - 10 + 2nd - 7 + 3rd - 5 + 4th - 3 + 5th - 2 + 6th - 1 + + Research Progress: Each Grand Prix has up to 40 points to earn, thus you need 120 Research points to beat the game. + +Grand Prix + Grand Prix I + Grand Prix II (Locked behind Grand Prix I) + Grand Prix III (Locked behind Grand Prix II) + Marathon (Locked behind Game Completion) + +Single Race + Track I + Track II + Track III + Track IV + Track V + Track VI + Track VII + Track VIII + Track IX + Track X + Track XI + Track XII + +Options + Volume Control + Remap R / Space to different keys. + +Racing + + + + Settings ======== Keybind Rebinds \ No newline at end of file