Windowing System button controls, stack system, and custom functions implemented.

pull/28/head
sigonasr2 1 year ago
parent 3cbb0d1e17
commit 03f2738ead
  1. 18
      Crawler/Crawler.cpp
  2. 1
      Crawler/Crawler.h
  3. 7
      Crawler/Crawler.vcxproj
  4. 24
      Crawler/Crawler.vcxproj.filters
  5. 2
      Crawler/Key.cpp
  6. 104
      Crawler/Menu.cpp
  7. 20
      Crawler/Menu.h
  8. 22
      Crawler/MenuButton.cpp
  9. 21
      Crawler/MenuButton.h
  10. 14
      Crawler/MenuType.h
  11. 91
      Crawler/Player.cpp
  12. 26
      Crawler/TestMenu.cpp
  13. 20
      Crawler/TestSubMenu.cpp
  14. 2
      Crawler/Version.h

@ -17,6 +17,7 @@
#include "config.h"
#include "safemap.h"
#include "Key.h"
#include "Menu.h"
INCLUDE_EMITTER_LIST
@ -76,6 +77,7 @@ Crawler::Crawler()
bool Crawler::OnUserCreate(){
InitializeDefaultKeybinds();
InitializeLevels();
Menu::InitializeMenus();
circleCooldownPoints.push_back({0,0});
for(int i=0;i<=360;i+=4){
@ -141,6 +143,7 @@ bool Crawler::OnUserUpdate(float fElapsedTime){
UpdateCamera(fElapsedTime);
RenderWorld(fElapsedTime);
RenderHud();
RenderMenu();
return true;
}
@ -170,6 +173,8 @@ bool Crawler::DownReleased(){
}
void Crawler::HandleUserInput(float fElapsedTime){
if(!Menu::stack.empty())return; //A window being opened means there's no user input allowed.
bool setIdleAnimation=true;
if(GetKey(F1).bPressed){
ConsoleShow(F1);
@ -357,6 +362,10 @@ void Crawler::HandleUserInput(float fElapsedTime){
}
}
}
if(GetKey(I).bPressed){
Menu::OpenMenu(TEST);
}
}
void Crawler::UpdateCamera(float fElapsedTime){
@ -1661,4 +1670,13 @@ void Crawler::ReduceBossEncounterMobCount(){
std::cout<<"WARNING! Boss Encounter mob count is less than zero, THIS SHOULD NOT BE HAPPENING!"<<std::endl;
throw;
}
}
void Crawler::RenderMenu(){
if(Menu::stack.size()>0){
Menu::stack.back()->Update(this);
}
if(Menu::stack.size()>0){
Menu::stack.back()->Draw(this);
}
}

@ -75,6 +75,7 @@ public:
void UpdateBullets(float fElapsedTime);
void RenderWorld(float fElapsedTime);
void RenderHud();
void RenderMenu();
void AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect>background);
//If back is true, places the effect in the background
void AddEffect(std::unique_ptr<Effect>foreground,bool back=false);

@ -270,8 +270,11 @@
<ClInclude Include="DEFINES.h" />
<ClInclude Include="Effect.h" />
<ClInclude Include="Emitter.h" />
<ClInclude Include="MenuType.h" />
<ClInclude Include="Key.h" />
<ClInclude Include="Map.h" />
<ClInclude Include="Menu.h" />
<ClInclude Include="MenuButton.h" />
<ClInclude Include="Monster.h" />
<ClInclude Include="MonsterAttribute.h" />
<ClInclude Include="MonsterStrategyHelpers.h" />
@ -309,6 +312,8 @@
<ClCompile Include="LightningBolt.cpp" />
<ClCompile Include="LightningBoltEmitter.cpp" />
<ClCompile Include="Map.cpp" />
<ClCompile Include="Menu.cpp" />
<ClCompile Include="MenuButton.cpp" />
<ClCompile Include="Meteor.cpp" />
<ClCompile Include="RunAway.cpp" />
<ClCompile Include="RunTowards.cpp" />
@ -322,6 +327,8 @@
<ClCompile Include="RUN_STRATEGY.cpp" />
<ClCompile Include="ShootAfar.cpp" />
<ClCompile Include="SlimeKing.cpp" />
<ClCompile Include="TestMenu.cpp" />
<ClCompile Include="TestSubMenu.cpp" />
<ClCompile Include="Thief.cpp" />
<ClCompile Include="Trapper.cpp" />
<ClCompile Include="Turret.cpp" />

@ -40,6 +40,9 @@
<Filter Include="Source Files\Monster Strategies">
<UniqueIdentifier>{3d2f7a3f-5781-45ab-a66d-c6d57d9de13c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Interface">
<UniqueIdentifier>{f90a901c-026c-4c22-9fab-58927f1e5536}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="olcPixelGameEngine.h">
@ -141,6 +144,15 @@
<ClInclude Include="Key.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Menu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MenuButton.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MenuType.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">
@ -251,6 +263,18 @@
<ClCompile Include="Key.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Menu.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
<ClCompile Include="MenuButton.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
<ClCompile Include="TestMenu.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
<ClCompile Include="TestSubMenu.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

@ -193,7 +193,7 @@ std::map<std::pair<InputType,int>,std::string> GenericKey::keyLiteral={
{{KEY, OEM_7},"\""},
{{KEY, OEM_8},"\\"},
{{KEY, CAPS_LOCK},"CAP LK"},
{{KEY, ENUM_END},""},
{{KEY, olc::ENUM_END},""},
{{MOUSE, Mouse::LEFT},"L.MOUSE"},
{{MOUSE, Mouse::RIGHT},"R.MOUSE"},
{{MOUSE, Mouse::MIDDLE},"M.MOUSE"},

@ -0,0 +1,104 @@
#include "Crawler.h"
#include "Menu.h"
bool Menu::MOUSE_NAVIGATION=true;
std::vector<Menu*>Menu::stack;
std::map<MenuType,Menu>Menu::menus;
Menu::Menu(){}
Menu::Menu(vf2d size)
:size(size){}
void Menu::InitializeMenus(){
stack.reserve(32);
menus[TEST]=InitializeTestMenu();
menus[TEST_2]=InitializeTestSubMenu();
for(MenuType type=TEST;type<MenuType::ENUM_END;type=MenuType(int(type+1))){
if(menus.count(type)==0){
std::cout<<"WARNING! Menu Type "<<type<<" does not exist!"<<std::endl;
throw;
}
}
}
void Menu::AddButton(const MenuButton&button){
buttons.push_back(button);
}
void Menu::MenuSelect(Crawler*game){
if(selection==-1)return;
buttons[selection].onClick(*this,game);
if(buttons[selection].menuDest!=MenuType::ENUM_END){
if(stack.size()<32){
stack.push_back(&menus[buttons[selection].menuDest]);//Navigate to the next menu.
}else{
std::cout<<"WARNING! Exceeded menu stack size limit!"<<std::endl;
throw;
}
}
}
void Menu::Update(Crawler*game){
vf2d upperLeftPos=game->GetScreenSize()/2-size/2;
for(MenuButton&button:buttons){
button.hovered=false;
}
if(!MOUSE_NAVIGATION){
if(selection!=-1)buttons[selection].hovered=true;
}else{
for(MenuButton&button:buttons){
if(geom2d::overlaps(geom2d::rect<float>{button.rect.pos+upperLeftPos,button.rect.size},game->GetMousePos())){
button.hovered=true;
}
}
}
if(game->GetKey(RIGHT).bPressed||game->GetKey(DOWN).bPressed){
MOUSE_NAVIGATION=false;
selection=(selection+1)%buttons.size();
}
if(game->GetKey(LEFT).bPressed||game->GetKey(UP).bPressed){
MOUSE_NAVIGATION=false;
selection--;
if(selection<0)selection+=buttons.size();
}
if(game->GetMouse(0).bPressed||game->GetKey(ENTER).bPressed||game->GetKey(SPACE).bPressed){
MOUSE_NAVIGATION=game->GetMouse(0).bPressed; //If a click occurs we use mouse controls.
if(!MOUSE_NAVIGATION){
MenuSelect(game);
//Key presses automatically highlight the first button if it's not highlighted.
if(selection==-1&&buttons.size()>0){
selection=0;
}
}else{//Mouse click.
selection=-1;
int index=0;
for(MenuButton&button:buttons){
if(geom2d::overlaps(geom2d::rect<float>{button.rect.pos+upperLeftPos,button.rect.size},game->GetMousePos())){
selection=index;
break;
}
index++;
}
MenuSelect(game);
}
}
for(MenuButton&button:buttons){
button.Update(game);
}
};
void Menu::Draw(Crawler*game){
vf2d upperLeftPos=game->GetScreenSize()/2-size/2;
game->FillRectDecal(upperLeftPos,size,VERY_DARK_BLUE);
for(MenuButton&button:buttons){
button.Draw(game,upperLeftPos);
}
};
void Menu::OpenMenu(MenuType menu){
stack.clear();
stack.push_back(&(menus[menu]));
}

@ -6,13 +6,25 @@
class Crawler;
class Menu{
std::stack<Menu*>*stack=nullptr;
friend class Crawler;
friend class Player;
static bool MOUSE_NAVIGATION;
static std::map<MenuType,Menu>menus;
std::vector<MenuButton>buttons;
int selection=-1;
vf2d size; //Size in tiles (24x24), every menu will be tile-based
public:
Menu();
void AddButton(vf2d pos);
void Update(float fElapsedTime);
Menu(vf2d size);
void AddButton(const MenuButton&button);
void Update(Crawler*game);
void Draw(Crawler*game);
static void InitializeMenus();
static void OpenMenu(MenuType menu);
static std::vector<Menu*>stack;
private:
void MenuSelect(Crawler*game);
static const Menu InitializeTestMenu();
static const Menu InitializeTestSubMenu();
};

@ -0,0 +1,22 @@
#include "Crawler.h"
#include "Menu.h"
MenuButton::MenuButton(geom2d::rect<float>rect,std::string label,Decal*icon,MenuFunc onClick)
:rect(rect),label(label),menuDest(MenuType::ENUM_END),icon(icon),onClick(onClick),hoverEffect(0){}
MenuButton::MenuButton(geom2d::rect<float>rect,std::string label,MenuType menuDest,Decal*icon,MenuFunc onClick)
:rect(rect),label(label),menuDest(menuDest),icon(icon),onClick(onClick),hoverEffect(0){}
void MenuButton::Update(Crawler*game){
if(hovered){
hoverEffect=std::min(1.f,hoverEffect+game->GetElapsedTime());
}else{
hoverEffect=std::max(0.f,hoverEffect-game->GetElapsedTime());
}
}
void MenuButton::Draw(Crawler*game,vf2d parentPos){
game->FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(VERY_DARK_BLUE,CYAN,hoverEffect));
game->DrawRectDecal(rect.pos+parentPos,rect.size,GREY);
game->DrawStringPropDecal(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label);
}

@ -1,17 +1,24 @@
#pragma once
#include "olcPixelGameEngine.h"
#include "olcUTIL_Geometry2D.h"
#include "MenuType.h"
#include <functional>
class Menu;
class Crawler;
class MenuButton{
Menu*menuDest;
vf2d size;
friend class Menu;
MenuType menuDest;
geom2d::rect<float>rect;
std::string label;
Decal*icon;
std::function<void()>onClick;
void Update(float fElapsedTime);
void Draw(Crawler*game);
MenuFunc onClick;
bool hovered=false;
private:
float hoverEffect=0;
public:
MenuButton(geom2d::rect<float>rect,std::string label,Decal*icon,MenuFunc onClick);
MenuButton(geom2d::rect<float>rect,std::string label,MenuType menuDest,Decal* icon,MenuFunc onClick);
void Update(Crawler*game);
void Draw(Crawler*game,vf2d parentPos);
};

@ -0,0 +1,14 @@
#pragma once
class Menu;
class Crawler;
typedef std::function<void(Menu&,Crawler*)> MenuFunc;
enum MenuType{
TEST,
TEST_2,
///////////////////////////////////////////////////////////
/*DO NOT REMOVE!!*/ENUM_END////////////////////////////////
///////////////////////////////////////////////////////////
};

@ -8,6 +8,7 @@
#include "safemap.h"
#include "utils.h"
#include "Key.h"
#include "Menu.h"
INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
@ -344,56 +345,60 @@ void Player::Update(float fElapsedTime){
SetX(newX);
SetY(newY);
}
if(CanAct()&&attack_cooldown_timer==0&&Crawler::KEY_ATTACK.Held()){
AutoAttack();
}
if(Menu::stack.empty()){
if(CanAct()&&attack_cooldown_timer==0&&Crawler::KEY_ATTACK.Held()){
AutoAttack();
}
auto AllowedToCast=[&](Ability&ability){return !ability.precastInfo.precastTargetingRequired&&GetState()!=State::ANIMATION_LOCK;};
//If pressed is set to false, uses held instead.
auto CheckAndPerformAbility=[&](Ability&ability,InputGroup key){
if(ability.name!="???"){
if(CanAct(ability)){
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
if(key.Held()||key.Released()&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
if(GetState()==State::CASTING){
SetState(State::NORMAL);
castInfo.castTimer=castInfo.castTotalTime=0;
}
if(AllowedToCast(ability)&&ability.action(this,{})){
ability.cooldown=ability.COOLDOWN_TIME;
mana-=ability.manaCost;
}else
if(ability.precastInfo.precastTargetingRequired&&GetState()==State::NORMAL){
PrepareCast(ability);
auto AllowedToCast=[&](Ability&ability){return !ability.precastInfo.precastTargetingRequired&&GetState()!=State::ANIMATION_LOCK;};
//If pressed is set to false, uses held instead.
auto CheckAndPerformAbility=[&](Ability&ability,InputGroup key){
if(ability.name!="???"){
if(CanAct(ability)){
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
if(key.Held()||key.Released()&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
if(GetState()==State::CASTING){
SetState(State::NORMAL);
castInfo.castTimer=castInfo.castTotalTime=0;
}
if(AllowedToCast(ability)&&ability.action(this,{})){
ability.cooldown=ability.COOLDOWN_TIME;
mana-=ability.manaCost;
}else
if(ability.precastInfo.precastTargetingRequired&&GetState()==State::NORMAL){
PrepareCast(ability);
}
}
} else
if(ability.cooldown==0&&GetMana()<ability.manaCost&&key.Pressed()){
notEnoughManaDisplay={ability.name,1};
}
} else
if(ability.cooldown==0&&GetMana()<ability.manaCost&&key.Pressed()){
notEnoughManaDisplay={ability.name,1};
}
}
};
CheckAndPerformAbility(GetAbility1(),Player::KEY_ABILITY1);
CheckAndPerformAbility(GetAbility2(),Player::KEY_ABILITY2);
CheckAndPerformAbility(GetAbility3(),Player::KEY_ABILITY3);
CheckAndPerformAbility(GetAbility4(),Player::KEY_ABILITY4);
CheckAndPerformAbility(GetRightClickAbility(),Player::KEY_DEFENSIVE);
if(GetState()==State::PREP_CAST){
#define CheckAbilityKeyReleasedAndCastSpell(ability,releaseState) \
if(&ability==castPrepAbility&&releaseState){CastSpell(ability);}
CheckAbilityKeyReleasedAndCastSpell(rightClickAbility,Player::KEY_DEFENSIVE.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability,Player::KEY_ABILITY1.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability2,Player::KEY_ABILITY2.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability3,Player::KEY_ABILITY3.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability4,Player::KEY_ABILITY4.Released())
}
};
CheckAndPerformAbility(GetAbility1(),Player::KEY_ABILITY1);
CheckAndPerformAbility(GetAbility2(),Player::KEY_ABILITY2);
CheckAndPerformAbility(GetAbility3(),Player::KEY_ABILITY3);
CheckAndPerformAbility(GetAbility4(),Player::KEY_ABILITY4);
CheckAndPerformAbility(GetRightClickAbility(),Player::KEY_DEFENSIVE);
if(GetState()==State::PREP_CAST){
#define CheckAbilityKeyReleasedAndCastSpell(ability,releaseState) \
if(&ability==castPrepAbility&&releaseState){CastSpell(ability);}
CheckAbilityKeyReleasedAndCastSpell(rightClickAbility,Player::KEY_DEFENSIVE.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability,Player::KEY_ABILITY1.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability2,Player::KEY_ABILITY2.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability3,Player::KEY_ABILITY3.Released())
else
CheckAbilityKeyReleasedAndCastSpell(ability4,Player::KEY_ABILITY4.Released())
}
#pragma region Warrior

@ -0,0 +1,26 @@
#include "Crawler.h"
#include "Menu.h"
const Menu Menu::InitializeTestMenu(){
Menu testMenu({24*8,24*6});
MenuFunc quitWindow=[](Menu&menu,Crawler*game){
menu.stack.clear();
};
testMenu.AddButton(MenuButton({{24*1,24*1},{24*2,24*1}},"Close",nullptr,quitWindow));
MenuFunc doNothing=[](Menu&menu,Crawler*game){};
testMenu.AddButton(MenuButton({{24*4,24*1},{24*3,24*1}},"Test",nullptr,doNothing));
MenuFunc HurtPlayer=[](Menu&menu,Crawler*game){
game->GetPlayer()->Hurt(20,game->GetPlayer()->OnUpperLevel(),game->GetPlayer()->GetZ());
};
testMenu.AddButton(MenuButton({{24*4,24*3},{24*3,24*1}},"Hurt Player",nullptr,HurtPlayer));
testMenu.AddButton(MenuButton({{24*2,24*4.5},{24*4,24*1}},"Open Another\n Menu",TEST_2,nullptr,doNothing));
return testMenu;
}

@ -0,0 +1,20 @@
#include "Crawler.h"
#include "Menu.h"
const Menu Menu::InitializeTestSubMenu(){
Menu testSubMenu({24*4,24*5});
MenuFunc goBack=[](Menu&menu,Crawler*game){
menu.stack.pop_back();
};
testSubMenu.AddButton(MenuButton({{24*1,24*1},{24*2,24*1}},"Go Back",nullptr,goBack));
MenuFunc quitWindow=[](Menu&menu,Crawler*game){
menu.stack.clear();
};
testSubMenu.AddButton(MenuButton({{24*1,24*3},{24*3,24*1}},"Close Window",nullptr,quitWindow));
return testSubMenu;
}

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 1576
#define VERSION_BUILD 1615
#define stringify(a) stringify_(a)
#define stringify_(a) #a

Loading…
Cancel
Save