diff --git a/assets/button.png b/assets/button.png new file mode 100644 index 0000000..9973c05 Binary files /dev/null and b/assets/button.png differ diff --git a/assets/hamsterplanet1.png b/assets/hamsterplanet1.png new file mode 100644 index 0000000..319a576 Binary files /dev/null and b/assets/hamsterplanet1.png differ diff --git a/assets/hamsterplanet2.png b/assets/hamsterplanet2.png new file mode 100644 index 0000000..814daee Binary files /dev/null and b/assets/hamsterplanet2.png differ diff --git a/assets/hamsterplanet3.png b/assets/hamsterplanet3.png new file mode 100644 index 0000000..e310195 Binary files /dev/null and b/assets/hamsterplanet3.png differ diff --git a/assets/welcometo.png b/assets/welcometo.png new file mode 100644 index 0000000..a5b927d Binary files /dev/null and b/assets/welcometo.png differ diff --git a/src/Hamster.cpp b/src/Hamster.cpp index d5f78ae..8f39ad2 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -871,7 +871,8 @@ void Hamster::HandleAIControls(){ if(aiNodeTime>GetAIAdjustNodeTime()){ geom2d::lineplayerToHamster{GetPlayer().GetPos(),GetPos()}; const float screenDistance{playerToHamster.length()*(1.325f/(HamsterGame::Game().GetCameraZ()))}; - if(screenDistance>226){ + const float playerScreenDistanceToNewNode{geom2d::line(GetPlayer().GetPos(),action.pos).length()*(1.325f/(HamsterGame::Game().GetCameraZ()))}; + if(screenDistance>226&&playerScreenDistanceToNewNode>226){ //Let's cheat, hehe. pos=action.pos; temporaryNode.reset(); @@ -980,7 +981,7 @@ const float Hamster::GetAILandingSpeed()const{ const float Hamster::GetAIAdjustNodeTime()const{ switch(ai.GetAIType()){ case HamsterAI::SMART:{ - return 0.5f; + return 1.f; }break; case HamsterAI::NORMAL:{ return 2.f; diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index 0279471..acd7c82 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -22,6 +22,8 @@ HamsterGame::HamsterGame(const std::string&appName){ } bool HamsterGame::OnUserCreate(){ + CreateLayer(); + EnableLayer(1U,true); LoadPBs(); audio.SetBackgroundPlay(true); olc::GFX3D::ConfigureDisplay(); @@ -102,6 +104,11 @@ void HamsterGame::LoadGraphics(){ _LoadImage("background4.png"); _LoadImage("background5.png"); _LoadImage("raceprogress.png"); + _LoadImage("welcometo.png"); + _LoadImage("hamsterplanet1.png"); + _LoadImage("hamsterplanet2.png"); + _LoadImage("hamsterplanet3.png"); + _LoadImage("button.png"); } void HamsterGame::LoadAnimations(){ @@ -387,12 +394,10 @@ bool HamsterGame::OnUserUpdate(float fElapsedTime){ net.SetName("OneLoneHamster"); net.SetColor(hamsterColorNames[0]); - SetupAndStartRace(); } runTime+=fElapsedTime; - UpdateGame(fElapsedTime); - DrawGame(); + menu.UpdateAndDraw(*this,fElapsedTime); return true; } @@ -690,6 +695,19 @@ const geom2d::rectHamsterGame::GetMapSpawnRect()const{ return currentMap.value().GetData().GetSpawnZone(); } +void HamsterGame::SetMapSetList(const std::queue&mapSet){ + while(mapSetList.size()>0)mapSetList.pop(); + mapSetList=mapSet; +} +const bool HamsterGame::HasMoreMapsToPlay()const{ + return mapSetList.size()>0; +} +const std::string HamsterGame::PopNextMap(){ + std::string frontMap{mapSetList.front()}; + mapSetList.pop(); + return frontMap; +} + int main() { HamsterGame game("Project Hamster"); diff --git a/src/HamsterGame.h b/src/HamsterGame.h index 39eda15..3c58a77 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -53,6 +53,7 @@ All rights reserved. #include "HamsterNet.h" #include "olcPGEX_SplashScreen.h" #include "HamsterLeaderboard.h" +#include "Menu.h" struct Letter{ vf2d pos; @@ -62,6 +63,7 @@ struct Letter{ class HamsterGame : public olc::PixelGameEngine { + friend class Menu; public: enum class GameMode{ GRAND_PRIX_1, @@ -105,6 +107,9 @@ public: const int GetRaceTime(); const bool RaceCountdownCompleted(); const geom2d::rectGetMapSpawnRect()const; + void SetMapSetList(const std::queue&mapSet); + const bool HasMoreMapsToPlay()const; + const std::string PopNextMap(); private: void UpdateGame(const float fElapsedTime); void DrawGame(); @@ -180,4 +185,6 @@ private: "Blue", }; HamsterLeaderboard leaderboard; + std::queuemapSetList{}; + Menu menu; }; \ No newline at end of file diff --git a/src/Menu.cpp b/src/Menu.cpp new file mode 100644 index 0000000..c3aafd8 --- /dev/null +++ b/src/Menu.cpp @@ -0,0 +1,160 @@ +#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 + +#include "Menu.h" +#include "HamsterGame.h" +#include "util.h" + +void Menu::UpdateAndDraw(HamsterGame&game,const float fElapsedTime){ + menuTransitionRefreshTimer-=fElapsedTime; + if(menuTimer>0.f){ + menuTimer-=fElapsedTime; + if(menuTimer<=0.f){ + currentMenu=nextMenu; + } + } + + game.EnableLayer(0U,menuTimer>0.f); + + switch(currentMenu){ + case INITIALIZE:{ + Transition(FADE_OUT,TITLE_SCREEN,1.f); + }break; + case TITLE_SCREEN:{ + if(game.GetKey(SPACE).bPressed||game.GetMouse(Mouse::LEFT).bPressed){ + Transition(SHIFT_LEFT,MAIN_MENU,0.5f); + } + }break; + case MAIN_MENU:{ + if(game.GetKey(SPACE).bPressed||game.GetMouse(Mouse::LEFT).bPressed){ + game.SetupAndStartRace(); + } + }break; + case GAMEPLAY:{ + game.UpdateGame(fElapsedTime); + game.DrawGame(); + }break; + case GAMEPLAY_RESULTS:{ + game.DrawGame(); + }break; + } + + if(menuTimer>0.f){ + DrawTransition(game); + if(menuTransitionRefreshTimer<=0.f){ + menuTransitionRefreshTimer=MENU_TRANSITION_REFRESH_RATE; + } + }else Draw(game,currentMenu,game.SCREEN_FRAME.pos); +} +void Menu::Transition(const TransitionType type,const MenuType gotoMenu,const float transitionTime){ + if(menuTimer>0.f)return; + menuTimer=originalMenuTimer=transitionTime; + nextMenu=gotoMenu; + currentTransition=type; +} +void Menu::DrawTransition(HamsterGame&game){ + if(currentTransition==FADE_OUT){ + if(menuTimer>=originalMenuTimer/2){//Fading out from old scene. + game.SetDrawTarget(1U); + Draw(game,currentMenu,game.SCREEN_FRAME.pos); + game.SetDrawTarget(nullptr); + game.Clear(BLACK); + if(menuTransitionRefreshTimer<=0.f)game.SetLayerTint(0U,{255,255,255,uint8_t(util::lerp(255,0,(menuTimer-originalMenuTimer/2)/(originalMenuTimer/2)))}); + }else{//Fading into new scene. + game.SetDrawTarget(1U); + Draw(game,nextMenu,game.SCREEN_FRAME.pos); + game.SetDrawTarget(nullptr); + game.Clear(BLACK); + if(menuTransitionRefreshTimer<=0.f)game.SetLayerTint(0U,{255,255,255,uint8_t(util::lerp(0,255,menuTimer/(originalMenuTimer/2)))}); + } + }else{ + if(menuTransitionRefreshTimer<=0.f){ + switch(currentTransition){ + case SHIFT_LEFT:{ + oldLayerPos=vi2d{int(util::lerp(-game.SCREEN_FRAME.size.x,0,menuTimer/originalMenuTimer)),0}; + newLayerPos=vi2d{int(util::lerp(0,game.SCREEN_FRAME.size.x,menuTimer/originalMenuTimer)),0}; + }break; + case SHIFT_RIGHT:{ + oldLayerPos=vi2d{int(util::lerp(game.SCREEN_FRAME.size.x,0,menuTimer/originalMenuTimer)),0}; + newLayerPos=vi2d{int(util::lerp(0,-game.SCREEN_FRAME.size.x,menuTimer/originalMenuTimer)),0}; + }break; + case SHIFT_UP:{ + oldLayerPos=vi2d{0,int(util::lerp(-game.SCREEN_FRAME.size.y,0,menuTimer/originalMenuTimer))}; + newLayerPos=vi2d{0,int(util::lerp(0,game.SCREEN_FRAME.size.y,menuTimer/originalMenuTimer))}; + }break; + case SHIFT_DOWN:{ + oldLayerPos=vi2d{0,int(util::lerp(game.SCREEN_FRAME.size.y,0,menuTimer/originalMenuTimer))}; + newLayerPos=vi2d{0,int(util::lerp(0,-game.SCREEN_FRAME.size.y,menuTimer/originalMenuTimer))}; + }break; + } + } + game.SetDrawTarget(1U); + game.SetLayerOffset(1U,oldLayerPos+game.SCREEN_FRAME.pos); + Draw(game,currentMenu,oldLayerPos+game.SCREEN_FRAME.pos); + game.SetDrawTarget(nullptr); + game.SetLayerTint(0U,WHITE); + game.SetLayerOffset(0U,newLayerPos+game.SCREEN_FRAME.pos); + Draw(game,nextMenu,newLayerPos+game.SCREEN_FRAME.pos); + } + game.SetDrawTarget(nullptr); +} + +void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ + game.Clear(BLANK); + switch(menu){ + case TITLE_SCREEN:{ + game.FillRectDecal(pos,game.SCREEN_FRAME.size,{111,150,255}); + game.DrawDecal(pos,game.GetGFX("welcometo.png").Decal()); + if(menuTransitionRefreshTimer>0.f)game.DrawDecal(pos,game.GetGFX("hamsterplanet1.png").Decal()); + if(fmod(game.GetRuntime(),2.f)<1.f)game.DrawDecal(pos,game.GetGFX("hamsterplanet2.png").Decal()); + else game.DrawDecal(pos,game.GetGFX("hamsterplanet3.png").Decal()); + game.border.Draw(); + }break; + case MAIN_MENU:{ + game.FillRectDecal(pos,game.SCREEN_FRAME.size,{}); + game.DrawRotatedDecal(pos,game.GetGFX("button.png").Decal(),0.f,game.GetGFX("button.png").Sprite()->Size()/2); + game.border.Draw(); + }break; + case GAMEPLAY:{ + game.DrawGame(); + }break; + case GAMEPLAY_RESULTS:{ + game.DrawGame(); + }break; + } +} \ No newline at end of file diff --git a/src/Menu.h b/src/Menu.h new file mode 100644 index 0000000..7050db4 --- /dev/null +++ b/src/Menu.h @@ -0,0 +1,82 @@ +#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 "olcPixelGameEngine.h" + +class HamsterGame; +class Menu{ + enum MenuType{ + INITIALIZE, + TITLE_SCREEN, + MAIN_MENU, + GRAND_PRIX, + SINGLE_RACE, + OPTIONS, + GAMEPLAY, + GAMEPLAY_RESULTS, + AFTER_RACE_MENU, + PAUSE, + }; + enum TransitionType{ + SHIFT_LEFT, + SHIFT_RIGHT, + SHIFT_UP, + SHIFT_DOWN, + FADE_OUT, + }; + enum MenuState{ + NORMAL, + TRANSITIONING, + }; + MenuState currentState{NORMAL}; + TransitionType currentTransition{FADE_OUT}; + MenuType currentMenu{INITIALIZE}; + MenuType nextMenu{TITLE_SCREEN}; + float menuTimer{}; + const float MENU_TRANSITION_REFRESH_RATE{0.15f}; + float menuTransitionRefreshTimer{MENU_TRANSITION_REFRESH_RATE}; + float originalMenuTimer{}; + vi2d oldLayerPos{}; + vi2d newLayerPos{}; + 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); +public: + void UpdateAndDraw(HamsterGame&game,const float fElapsedTime); +}; \ No newline at end of file diff --git a/src/TODO.txt b/src/TODO.txt index 9389dd3..db6741b 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -154,7 +154,6 @@ Stage 11: Boss Battle #3 Alternate - nene Stage 12: Boss Battle #5 V2 - nene -Live Placement Tracking Pulsating Animation based on terrain walking across (30 min) Sound Effects (1 hour) @@ -180,7 +179,7 @@ Menu Select/Back Sound ========================== Stages VI - XII: 7 Stages (1 hour each, 7 hours total) -Menu Navigations (2 hours) +Menu Navigations (3 hours) Grand Prix Management (1 hour) Unlocks (1 hour) Leaderboard Management (1 hour)