Skip to content

Commit

Permalink
Improved implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
bartez33a committed Nov 4, 2023
1 parent aa48ccf commit 98edbb3
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 65 deletions.
23 changes: 19 additions & 4 deletions src/Button.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#include "Button.hpp"

Button::Button(std::string text, point_t top_left_corner, unsigned int width, unsigned int height,
void (*callback)(void), MenuLevel* next_level)
Button::Button(std::string text, sf::Vector2f top_left_corner, unsigned int width,
unsigned int height, void (*callback)(void), ButtonType button_type,
MenuLevel* next_level)
: mTextContent{text},
mCallback{callback},
MenuItem{top_left_corner},
mWidth{width},
mHeight{height},
mButtonType{button_type},
mNextLevel{next_level} {}

void Button::draw(sf::RenderWindow& window, const sf::Font& font) {
Expand All @@ -28,12 +30,25 @@ void Button::draw(sf::RenderWindow& window, const sf::Font& font) {
mText.setString(mTextContent);

// move objects in window and draw
rectangle.move(mPosition);
rectangle.setPosition(mPosition);
window.draw(rectangle);
mText.move(mPosition);

// center text
mText.setOrigin(mText.getGlobalBounds().getSize() / 2.f + mText.getLocalBounds().getPosition());
mText.setPosition(rectangle.getPosition() + (rectangle.getSize() / 2.f));
window.draw(mText);
}

void Button::select() { mIsSelected = true; }

void Button::deselect() { mIsSelected = false; }

void Button::click() {
if (mButtonType == ButtonType::Callback && mIsSelected) {
mCallback();
}
}

ButtonType Button::get_button_type() const { return mButtonType; }

MenuLevel* Button::get_next_level() const { return mNextLevel; }
21 changes: 13 additions & 8 deletions src/Button.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,28 @@
#include "MenuItem.hpp"
#include "MenuLevel.hpp"

using point_t = sf::Vector2f;
enum class ButtonType { Callback, LevelChanger };

class MenuLevel;

class Button : MenuItem {
public:
Button(std::string text, sf::Vector2f top_left_corner, unsigned int width, unsigned int height,
void (*callback)(void), ButtonType button_type, MenuLevel* next_level = nullptr);
void draw(sf::RenderWindow& window, const sf::Font& font);
void select();
void deselect();
void click();
ButtonType get_button_type() const;
MenuLevel* get_next_level() const;

private:
std::string mTextContent;
sf::Text mText;
unsigned int mWidth;
unsigned int mHeight;
void (*mCallback)(void);
bool mIsSelected = false;
MenuLevel* mNextLevel;

public:
Button(std::string text, point_t top_left_corner, unsigned int width, unsigned int height,
void (*callback)(void), MenuLevel* next_level = nullptr);
void draw(sf::RenderWindow& window, const sf::Font& font);
void select();
void deselect();
ButtonType mButtonType;
};
76 changes: 43 additions & 33 deletions src/GameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,37 @@

#include "Size.hpp"

void main_menu_start_callback(void) { std::cout << "Start clicked!\n"; }
void main_menu_options_callback(void) { std::cout << "Options clicked!\n"; }
void main_menu_exit_callback(void) { std::cout << "Exit clicked!\n"; }
// define static variables
bool GameManager::request_state_change = false;
GameManagerState GameManager::desired_state = GameManagerState::InvalidState;

void options_back_callback(void) { std::cout << "Options: back clicked\n"; }

// button -> text, callback, clickable, nextLevel
// Button callbacks:
void main_menu_start_callback(void) {
GameManager::request_state_change = true;
GameManager::desired_state = GameManagerState::Started;
}
void main_menu_exit_callback(void) {
GameManager::request_state_change = true;
GameManager::desired_state = GameManagerState::Exit;
}

// define menus
extern MenuLevel options;

const unsigned int buttonWidth = WIDTH / 5;
const unsigned int buttonHeight = HEIGHT / 10;
constexpr unsigned int verticalSpacing = 20;

MenuLevel main_menu{
{{"Start", point_t((WIDTH - buttonWidth) / 2, verticalSpacing + buttonHeight * 1), buttonWidth,
buttonHeight, main_menu_start_callback, nullptr},
{"Options", point_t((WIDTH - buttonWidth) / 2, verticalSpacing + buttonHeight * 3),
buttonWidth, buttonHeight, main_menu_options_callback, &options},
{"Exit", point_t((WIDTH - buttonWidth) / 2, verticalSpacing + buttonHeight * 5), buttonWidth,
buttonHeight, main_menu_exit_callback, nullptr}}};
{{"Start", sf::Vector2f((WIDTH - buttonWidth) / 2, verticalSpacing + buttonHeight * 1),
buttonWidth, buttonHeight, main_menu_start_callback, ButtonType::Callback, nullptr},
{"Options", sf::Vector2f((WIDTH - buttonWidth) / 2, verticalSpacing + buttonHeight * 3),
buttonWidth, buttonHeight, nullptr, ButtonType::LevelChanger, &options},
{"Exit", sf::Vector2f((WIDTH - buttonWidth) / 2, verticalSpacing + buttonHeight * 5),
buttonWidth, buttonHeight, main_menu_exit_callback, ButtonType::Callback, nullptr}}};

MenuLevel options{{"Back", point_t(WIDTH / 2 - buttonWidth, 2 * buttonHeight + 20), buttonWidth,
buttonHeight, options_back_callback, &main_menu}};
MenuLevel options{{"Back", sf::Vector2f(WIDTH / 2 - buttonWidth, 2 * buttonHeight + 20),
buttonWidth, buttonHeight, nullptr, ButtonType::LevelChanger, &main_menu}};

GameManager::GameManager()
: mWindow{sf::VideoMode(WIDTH, HEIGHT), "TankBotFight"},
Expand All @@ -34,10 +41,8 @@ GameManager::GameManager()

void GameManager::start() {
while (mWindow.isOpen()) {
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (mWindow.pollEvent(event)) {
// "close requested" event: we close the window
if (event.type == sf::Event::Closed) {
mGameManagerState = GameManagerState::Exit;
}
Expand All @@ -55,27 +60,11 @@ void GameManager::start() {
mWindow.display();
}
}
#include <iostream>

void GameManager::performStateMachine(const sf::Event& event) {
switch (mGameManagerState) {
case GameManagerState::MainMenu:
mMainMenu.process_and_draw(event);
/*
[this]() {
std::string input;
std::cout << "Welcome to the game!\n";
std::cout << "1. Play\n2. Exit\nSelect: ";
std::cin >> input;
switch (input[0]) {
case '1':
mGameManagerState = GameManagerState::Started;
break;
case '2':
mGameManagerState = GameManagerState::Exit;
break;
}
}();
*/
break;
case GameManagerState::Started:
mBoard.play(event);
Expand All @@ -84,4 +73,25 @@ void GameManager::performStateMachine(const sf::Event& event) {
mWindow.close();
break;
}

// check if state change is requested
if (request_state_change) {
request_state_change = false;
transitState();
}
}

void GameManager::transitState() {
switch (mGameManagerState) {
case GameManagerState::MainMenu:
if (desired_state == GameManagerState::Started) {
mGameManagerState = GameManagerState::Started;
} else if (desired_state == GameManagerState::Exit) {
mGameManagerState = GameManagerState::Exit;
}
break;
case GameManagerState::Started:
// TODO -> pause game
break;
}
}
14 changes: 9 additions & 5 deletions src/GameManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,26 @@ enum class GameManagerState {
MainMenu,
Started,
Exit,
InvalidState,
};

class GameManager {
public:
GameManager();
void start();
void performStateMachine(const sf::Event& event);
void transitState();

private:
// objects
GameManagerState mGameManagerState = GameManagerState::MainMenu;
sf::RenderWindow mWindow;
MainMenu mMainMenu;
Board mBoard;
static bool request_state_change;
static GameManagerState desired_state;

// methods
public:
void start();
void transitState(GameManagerState desired_state);
void performStateMachine(const sf::Event& event);
// friends: buttons' callbacks
friend void main_menu_start_callback(void);
friend void main_menu_exit_callback(void);
};
8 changes: 6 additions & 2 deletions src/MainMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ MainMenu::MainMenu(sf::RenderWindow& window, std::initializer_list<MenuLevel*> m
}

void MainMenu::process_and_draw(const sf::Event& event) {
// check if menu should be changed
if (mCurrentLevel->is_level_change_requested()) {
mCurrentLevel->reset_level_request();
mCurrentLevel = mCurrentLevel->get_next_level();
}

// process inputs
mCurrentLevel->processEvents(event);

// draw menu
mCurrentLevel->draw(mWindow, mFont);

// perform actions
}
1 change: 0 additions & 1 deletion src/MainMenu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class MainMenu {
public:
MainMenu(sf::RenderWindow& window, std::initializer_list<MenuLevel*> menu_level_ptrs,
MenuLevel* current_level);

void process_and_draw(const sf::Event& event);

private:
Expand Down
6 changes: 3 additions & 3 deletions src/MenuItem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#include <SFML/Graphics.hpp>

class MenuItem {
protected:
sf::Vector2f mPosition;

public:
MenuItem(sf::Vector2f position);

protected:
sf::Vector2f mPosition;
};
26 changes: 21 additions & 5 deletions src/MenuLevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
MenuLevel::MenuLevel(std::initializer_list<Button> buttons) : mButtons{buttons} {}

void MenuLevel::processEvents(const sf::Event& event) {
// process input
// process keyboard inputs
static sf::Keyboard::Key lastPressedKey;
if (event.type == sf::Event::KeyPressed) {
if (lastPressedKey != event.key.code) {
Expand All @@ -20,25 +20,41 @@ void MenuLevel::processEvents(const sf::Event& event) {
mSelectedButton = 0;
}
}

if (event.key.code == sf::Keyboard::Enter) {
if (mButtons.size()) {
if (mButtons[mSelectedButton].get_button_type() == ButtonType::Callback) {
mButtons[mSelectedButton].click();
} else if (mButtons[mSelectedButton].get_button_type() == ButtonType::LevelChanger) {
mNextLevel = mButtons[mSelectedButton].get_next_level();
mRequestLevelChange = true;
}
}
}
}

lastPressedKey = event.key.code;
} else if (event.type == sf::Event::KeyReleased) {
lastPressedKey = sf::Keyboard::Unknown;
}
}

void MenuLevel::draw(sf::RenderWindow& window, const sf::Font& font) {
// select button - draw outline
// process button selection
for (int i = 0; i < mButtons.size(); ++i) {
if (i == mSelectedButton) {
mButtons[i].select();
} else {
mButtons[i].deselect();
}
}
}

bool MenuLevel::is_level_change_requested() const { return mRequestLevelChange; }

MenuLevel* MenuLevel::get_next_level() const { return mNextLevel; }

// draw buttons
void MenuLevel::reset_level_request() { mRequestLevelChange = false; }

void MenuLevel::draw(sf::RenderWindow& window, const sf::Font& font) {
for (auto& button : mButtons) {
button.draw(window, font);
}
Expand Down
14 changes: 10 additions & 4 deletions src/MenuLevel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@
class Button;

class MenuLevel {
std::vector<Button> mButtons;
MenuLevel* mPrevLevel;
int mSelectedButton = 0;

public:
MenuLevel(std::initializer_list<Button> buttons);
void draw(sf::RenderWindow&, const sf::Font& font);
void processEvents(const sf::Event& event);
bool is_level_change_requested() const;
MenuLevel* get_next_level() const;
void reset_level_request();

private:
std::vector<Button> mButtons;
int mSelectedButton = 0;
bool mIsClicked = false;
bool mRequestLevelChange = false;
MenuLevel* mNextLevel;
};

0 comments on commit 98edbb3

Please sign in to comment.