From c358f7e3c87479c39f7c8b10fc12c0a54e694f0f Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sat, 24 Aug 2024 23:55:26 -0500 Subject: [PATCH] Add menu button system. --- assets/button2.png | Bin 0 -> 805 bytes assets/button3.png | Bin 0 -> 796 bytes assets/button4.png | Bin 0 -> 792 bytes assets/highlight_button2.png | Bin 0 -> 807 bytes assets/highlight_button3.png | Bin 0 -> 787 bytes assets/highlight_button4.png | Bin 0 -> 792 bytes src/HamsterGame.cpp | 13 +++- src/HamsterGame.h | 2 + src/Menu.cpp | 118 ++++++++++++++++++++++++++++++----- src/Menu.h | 17 +++-- 10 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 assets/button2.png create mode 100644 assets/button3.png create mode 100644 assets/button4.png create mode 100644 assets/highlight_button2.png create mode 100644 assets/highlight_button3.png create mode 100644 assets/highlight_button4.png diff --git a/assets/button2.png b/assets/button2.png new file mode 100644 index 0000000000000000000000000000000000000000..07031574af5d38738e982a61045083f5a12addfe GIT binary patch literal 805 zcmV+=1KRwFP)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{008|-L_t(o!|j-{4TCTcMZXbUR-p4D=~5yFU<4W_@B}oB zzyOFcT^4c23aLpG5D+^Y#!_T*uR{3FmcFd>{SyENFwVr|M_Dwe>KtX!ScA{LPK_Dk z06+j3C<%KH2r+-}-c_A11=PKs7Q0p<&D7>5wzyF8DXjOBi8S9p-D`BM;==ZYG*gg? zoNi!j3VPh1tdxQ4?eg(2Vp)z6tzQ*}_INA=Jo>Wz8)M5i3CQBPiO4n3XANXnz~2kV zO*GAwSOxTDea`Mg=ET&Fn=vEso(Gmi<1|cgG2@{REaqO=>p1Joqb^%~w8zG69Wd|E jDK;qN{KYtnE15el5p}z#Ua$fQ00000NkvXXu0mjfC2?Oz literal 0 HcmV?d00001 diff --git a/assets/button3.png b/assets/button3.png new file mode 100644 index 0000000000000000000000000000000000000000..f65f7daf3f0bb1bb356cc66b7a4892128c99fbcb GIT binary patch literal 796 zcmV+%1LOROP)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{008t!L_t(o!($A~d;Fha6p#&AU<~U>8HS_FpD9K;h>?e|LF23h=w#ZEI@8x64Qzw%KA};vqnoY a@&N$Gea27&8_}8o0000EX>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{008hwL_t(o!(&uYv-;043dja5FvgC_i3}dO^BHzbPQ
IC0>KF|vEI`$*0z-@mJ*kcY z!r2*T08*>W817jZX8?`@(!po|jt1Z$3c%4yWV8|)*h*wH1&*dbx~D)EVq4s!06Sno zABBL0FfBXd!)3q%V=#djK+WNxp|0N}cRr*HgbmG5Y5{CemXI04K|jiH)@VsaJ^%o> WmAbU8%()~00000EX>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{0093o1z6BzeYm}3rMJ7!w_Q{4Hn7( z6MC&O3W%#bPy&$Bnr);3Sd$MPfTMv&ULcN^fz&JmN5N5LEc0Sn~5Fja@MhVxJtF7-^LbmItFfZReS lrW-Vr^`i`Djh1BO0{{rYx6LTG1;79R002ovPDHLkV1hQrRX_j$ literal 0 HcmV?d00001 diff --git a/assets/highlight_button3.png b/assets/highlight_button3.png new file mode 100644 index 0000000000000000000000000000000000000000..b4c96464ff58840713f7c27370b63261712fb43b GIT binary patch literal 787 zcmV+u1MK{XP)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{008SrL_t(o!(+^!_WwV_C?FfKz!=Uk3=DghKxkZGxXTl( z2BwaIfq{WBf7<{5#AqPZf}yCNRI~RkK?}h9R}qr;&NDD584@-Gm%5>%pBR8{mZCO} z6nOtCMDZxV4U`Na0SHThEZ7tk`;7(^Hqg5XQ;caeSSSOd0Z6R?gcXXTfcPd1JOC+e z8jLgmYcsEX>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{008hwL_t(o!(;RhZ1~SG3dja5Fh;b%ABLqLSQw%O{@_$R z+~tW?15?Mqz`(%hAK37p7!9OaFckHZYWC6(ET{p7D{vh;4C?0_=bV zeG~!~!nEv+50?Q8jKKtA05yk$hPwWxA6Ot|AZ%!cQVU>%vV_bS4*F4svqnoY@&N#3 WgTRP0&&menuTimer==0.f){ + if(game.GetKey(W).bPressed||game.GetKey(UP).bPressed||game.GetKey(A).bPressed||game.GetKey(LEFT).bPressed){ + if(selectedButton.value()-1<0)selectedButton=menuButtons.size()-1; + else selectedButton.value()--; + } + if(game.GetKey(S).bPressed||game.GetKey(DOWN).bPressed||game.GetKey(D).bPressed||game.GetKey(RIGHT).bPressed){ + if(selectedButton.value()+1>=menuButtons.size())selectedButton=0; + else selectedButton.value()++; + } + if(game.GetKey(ENTER).bPressed||game.GetKey(SPACE).bPressed||menuButtons[selectedButton.value()].IsHovered(oldLayerPos+game.SCREEN_FRAME.pos)&&game.GetMouse(Mouse::LEFT).bPressed){ + menuButtons[selectedButton.value()].OnClick(); + } + } + if(menuTimer>0.f){ menuTimer-=fElapsedTime; if(menuTimer<=0.f){ + menuTimer=0.f; currentMenu=nextMenu; + oldLayerPos={}; + newLayerPos=game.SCREEN_FRAME.pos; OnMenuTransition(); } } @@ -58,15 +81,11 @@ void Menu::UpdateAndDraw(HamsterGame&game,const float fElapsedTime){ Transition(FADE_OUT,TITLE_SCREEN,1.f); }break; case TITLE_SCREEN:{ - if(game.GetKey(SPACE).bPressed||game.GetMouse(Mouse::LEFT).bPressed){ + if(game.GetKey(SPACE).bPressed||game.GetKey(ENTER).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){ - Transition(FADE_OUT,LOADING,0.5f); - selectedMap="StageV.tmx"; - } }break; case GAMEPLAY:{ game.UpdateGame(fElapsedTime); @@ -96,20 +115,49 @@ void Menu::Transition(const TransitionType type,const MenuType gotoMenu,const fl menuTimer=originalMenuTimer=transitionTime; nextMenu=gotoMenu; currentTransition=type; + newMenuButtons=GetMenuButtons(gotoMenu); +} +std::vectorMenu::GetMenuButtons(const MenuType type){ + std::vectorbuttons; + switch(type){ + case MAIN_MENU:{ + buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,-32.f},"Grand Prix","button.png","highlight_button.png",Pixel{165,208,96},Pixel{37,134,139},[this](){Transition(SHIFT_LEFT,GRAND_PRIX,0.5f);}); + buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,0.f},"Single Race","button.png","highlight_button.png",Pixel{165,208,96},Pixel{37,134,139},[this](){Transition(SHIFT_UP,SINGLE_RACE,0.5f);}); + buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,32.f},"Options","button.png","highlight_button.png",Pixel{165,208,96},Pixel{37,134,139},[this](){Transition(SHIFT_RIGHT,OPTIONS,0.5f);}); + buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,64.f},"Quit","button.png","highlight_button.png",Pixel{165,208,96},Pixel{37,134,139},[this](){Transition(SHIFT_DOWN,QUIT,0.5f);}); + }break; + case GRAND_PRIX:{ + //Add more buttons up here! + buttons.emplace_back(vf2d{54.f,HamsterGame::SCREEN_FRAME.size.y-24.f},"< Back","button3.png","highlight_button3.png",Pixel{145,199,255},Pixel{145,199,255},[this](){Transition(SHIFT_RIGHT,MAIN_MENU,0.5f);}); + }break; + case SINGLE_RACE:{ + //Add more buttons up here! + buttons.emplace_back(vf2d{54.f,HamsterGame::SCREEN_FRAME.size.y-24.f},"< Back","button4.png","highlight_button4.png",Pixel{220,185,155},Pixel{180,140,152},[this](){Transition(SHIFT_DOWN,MAIN_MENU,0.5f);}); + }break; + case OPTIONS:{ + //Add more buttons up here! + 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](){Transition(SHIFT_LEFT,MAIN_MENU,0.5f);}); + }break; + } + return buttons; } void Menu::OnMenuTransition(){ selectedButton.reset(); + menuButtons.clear(); + newMenuButtons.clear(); + menuButtons=GetMenuButtons(currentMenu); switch(currentMenu){ - case MAIN_MENU:{ - //selectedButton - }break; case LOADING:{ colorNumb=util::random()%8+1; loading=true; loadingPct=0.f; HamsterGame::Game().LoadRace(selectedMap); }break; + case QUIT:{ + HamsterGame::Game().QuitGame(); + }break; } + if(menuButtons.size()>0)selectedButton=0; } void Menu::DrawTransition(HamsterGame&game){ if(currentTransition==FADE_OUT){ @@ -160,6 +208,19 @@ void Menu::DrawTransition(HamsterGame&game){ void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ game.Clear(BLANK); + const auto DrawButtons=[this,&game](const vf2d&offset){ + for(int i{0};const Button&b:menuButtons){ + if(selectedButton.has_value())b.Draw(game,oldLayerPos+game.SCREEN_FRAME.pos,menuButtons[selectedButton.value()]); + else b.Draw(game,oldLayerPos+game.SCREEN_FRAME.pos); + if(selectedButton.has_value())b.Draw(game,oldLayerPos+game.SCREEN_FRAME.pos,menuButtons[selectedButton.value()]); + else b.Draw(game,oldLayerPos+game.SCREEN_FRAME.pos); + } + for(int i{0};const Button&b:newMenuButtons){ + if(selectedButton.has_value())b.Draw(game,newLayerPos+game.SCREEN_FRAME.pos,menuButtons[selectedButton.value()]); + else b.Draw(game,newLayerPos+game.SCREEN_FRAME.pos); + } + }; + switch(menu){ case TITLE_SCREEN:{ game.FillRectDecal(pos,game.SCREEN_FRAME.size,{111,150,255}); @@ -172,8 +233,27 @@ void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ 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; + case GRAND_PRIX:{ + game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background5.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); + DrawButtons(pos); + game.border.Draw(); + }break; + case SINGLE_RACE:{ + game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background4.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); + DrawButtons(pos); + game.border.Draw(); + }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); game.border.Draw(); }break; + 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; @@ -214,12 +294,22 @@ void Menu::UpdateLoadingProgress(const float pctLoaded){ loadingPct=pctLoaded; } -Menu::Button::Button(const vf2d pos,std::string buttonText,Renderable&buttonImg,std::functiononClick) -:pos(pos),buttonText(buttonText),buttonImg(buttonImg),onClick(onClick){} +Menu::Button::Button(const vf2d pos,const std::string&buttonText,const std::string&buttonImg,const std::string&highlightButtonImg,const Pixel textCol,const Pixel highlightTextCol,const std::functiononClick) +:pos(pos),buttonText(buttonText),buttonImg(buttonImg),highlightButtonImg(highlightButtonImg),onClick(onClick),textCol(textCol),highlightTextCol(highlightTextCol){} -void Menu::Button::Update(const float fElapsedTime){ - +const bool Menu::Button::IsHovered(const vf2d&offset)const{ + return geom2d::overlaps(HamsterGame::Game().GetMousePos(),geom2d::rect(pos-HamsterGame::GetGFX(buttonImg).Sprite()->Size()/2+offset,HamsterGame::GetGFX(buttonImg).Sprite()->Size())); } -void Menu::Button::Draw(HamsterGame&game){ - +void Menu::Button::Draw(HamsterGame&game,const vf2d&offset,std::optional>selectedButton)const{ + if(selectedButton.has_value()&&&selectedButton.value().get()==this){ + game.DrawRotatedDecal(pos+offset,game.GetGFX(highlightButtonImg).Decal(),0.f,game.GetGFX(highlightButtonImg).Sprite()->Size()/2); + game.DrawRotatedStringPropDecal(pos+offset,buttonText,0.f,game.GetTextSizeProp(buttonText)/2,highlightTextCol); + }else{ + game.DrawRotatedDecal(pos+offset,game.GetGFX(buttonImg).Decal(),0.f,game.GetGFX(buttonImg).Sprite()->Size()/2); + game.DrawRotatedStringPropDecal(pos+offset,buttonText,0.f,game.GetTextSizeProp(buttonText)/2,textCol); + } +} + +void Menu::Button::OnClick(){ + onClick(); } \ No newline at end of file diff --git a/src/Menu.h b/src/Menu.h index f4a8f0c..bfd17e1 100644 --- a/src/Menu.h +++ b/src/Menu.h @@ -45,12 +45,16 @@ class Menu{ class Button{ std::string buttonText; vf2d pos; - Renderable&buttonImg; + std::string buttonImg; + std::string highlightButtonImg; + Pixel textCol; + Pixel highlightTextCol; std::functiononClick; public: - Button(const vf2d pos,std::string buttonText,Renderable&buttonImg,std::functiononClick={}); - void Update(const float fElapsedTime); - void Draw(HamsterGame&game); + Button(const vf2d pos,const std::string&buttonText,const std::string&buttonImg,const std::string&highlightButtonImg,const Pixel textCol,const Pixel highlightTextCol,const std::functiononClick={}); + const bool IsHovered(const vf2d&offset)const; + void OnClick(); + void Draw(HamsterGame&game,const vf2d&pos,std::optional>selectedButton={})const; }; enum MenuType{ INITIALIZE, @@ -64,6 +68,7 @@ class Menu{ AFTER_RACE_MENU, PAUSE, LOADING, + QUIT, }; enum TransitionType{ SHIFT_LEFT, @@ -81,7 +86,7 @@ class Menu{ MenuType currentMenu{INITIALIZE}; MenuType nextMenu{TITLE_SCREEN}; float menuTimer{}; - const float MENU_TRANSITION_REFRESH_RATE{0.15f}; + const float MENU_TRANSITION_REFRESH_RATE{0.1f}; float menuTransitionRefreshTimer{MENU_TRANSITION_REFRESH_RATE}; float originalMenuTimer{}; vi2d oldLayerPos{}; @@ -90,12 +95,14 @@ class Menu{ bool loading{false}; float loadingPct{0.f}; std::vector