diff --git a/Makefile b/Makefile index acad14a..52591e3 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ OBJECTS=\ main.o \ drawutils.o mathutils.o timer.o itos.o \ graph.o gamedata.o player.o vertex.o gamevertex.o \ -menubutton.o \ +entity.o menubutton.o \ mainevent.o gamestate.o game.o titlescreen.o all: $(PROJECT) diff --git a/game.cpp b/game.cpp index 1ed832d..244ed5c 100644 --- a/game.cpp +++ b/game.cpp @@ -4,7 +4,7 @@ #include "debug.h" #include "itos.h" #include - +using std::pair; Game::Game(stack* state_stack, SDL_Surface* display) : GameState(state_stack, display) @@ -76,10 +76,34 @@ bool Game::init() BUTTON_END_TURN)); + for (list::iterator cursor = buttons.begin(); + cursor != buttons.end(); cursor++) + { + if (!(*cursor)->init()) + { + debug("Failed to initialize a button"); + throw StateExit(); + } + } + + mode_changed(); + + return GameState::init(); } +void Game::iterate() +{ + // handle the button iterations + for (list::iterator cursor = buttons.begin(); + cursor != buttons.end(); cursor++) + { + (*cursor)->iterate(); + } +} + + void Game::render() { int range = data.get_range(); @@ -142,7 +166,22 @@ void Game::render() } // draw the rest of the bottom menu + draw_menu_bars(); + for (list::iterator cursor = buttons.begin(); + cursor != buttons.end(); cursor++) + { + (*cursor)->render(display); + } + + draw_player_info(); + + SDL_Flip(display); +} + + +void Game::draw_menu_bars() +{ // horizontal line across the whole thing DrawUtils::draw_line(display, 0, display->h - 100, display->w, display->h - 100, 2, 0x000000); @@ -155,51 +194,6 @@ void Game::render() DrawUtils::draw_line(display, display->w - 100, display->h - 100, display->w - 100, display->h, 2, 0x000000); - - for (list::iterator cursor = buttons.begin(); - cursor != buttons.end(); cursor++) - { - MenuButton* button = *cursor; - - if (!(button->get_action() & BUTTON_END_TURN) && - (data.get_current_vertex() == NULL || - data.get_current_vertex()->player != data.get_turn())) - continue; - - if ((button->get_action() & (BUTTON_BUILD_ATTACKER | - BUTTON_BUILD_DEFENDER | - BUTTON_BUILD_PRODUCER)) && - data.get_mode() != MODE_BUILD) - continue; - - draw_button(button); - } - - draw_player_info(); - - SDL_Flip(display); -} - - -void Game::draw_button(MenuButton* button) -{ - int colour = 0x000000; - ButtonAction action = button->get_action(); - Mode mode = data.get_mode(); - VertexType build_type = data.get_build_type(); - - // fixme - there's really got to be a better way... - if ((action == BUTTON_BUILD && mode == MODE_BUILD) || - (action == BUTTON_ATTACK && mode == MODE_ATTACK) || - (action == BUTTON_MOVE && mode == MODE_MOVE) || - (action == BUTTON_BUILD_ATTACKER && build_type == VERTEX_ATTACKER) || - (action == BUTTON_BUILD_DEFENDER && build_type == VERTEX_DEFENDER) || - (action == BUTTON_BUILD_PRODUCER && build_type == VERTEX_PRODUCER) - ) - colour = 0x0000ff; - else if (button->is_at(cursor_x, cursor_y)) colour = 0xff0000; - - button->draw(display, colour); } @@ -331,17 +325,24 @@ void Game::on_lbutton_down(int x, int y) cursor != buttons.end(); cursor++) { MenuButton* button = *cursor; - if (button->is_at(x, y)) handle_button_press(button->get_action()); + if (button->is_at(x, y)) + { + handle_button_press(button->get_action()); + mode_changed(); + return; + } } if (y > display->h - 110) return; if (!data.endgame()) data.handle_click(x, y); + mode_changed(); } void Game::on_rbutton_down(int mX, int mY) { data.clear_current_vertex(); + mode_changed(); } @@ -357,6 +358,8 @@ void Game::on_key_down(SDLKey sym, SDLMod mod, Uint16 unicode) else if (sym == SDLK_s || sym == SDLK_ESCAPE) data.set_mode(MODE_SELECT); else if (sym == SDLK_e) data.toggle_turn(); + mode_changed(); + #ifdef DEBUG if (sym == SDLK_d && mod & (KMOD_ALT | KMOD_CTRL)) print_debug_info(); #endif @@ -377,3 +380,16 @@ void Game::print_debug_info() fprintf(stderr, "Turn: %s\n", data.get_turn()->get_name().c_str()); } #endif + + +void Game::mode_changed() +{ + // Set the state for each button + for (list::iterator cursor = buttons.begin(); + cursor != buttons.end(); cursor++) + { + (*cursor)->set_state(data.get_mode(), data.get_build_type(), + data.get_current_vertex()); + } + +} diff --git a/game.h b/game.h index 2e00db4..ce66f1a 100644 --- a/game.h +++ b/game.h @@ -28,7 +28,7 @@ class Game : public GameState protected: void render(); - void iterate() {} + void iterate(); // event handlers void on_lbutton_down(int x, int y); @@ -39,11 +39,12 @@ class Game : public GameState private: void draw_stats(GameVertex* v); - void draw_button(MenuButton* button); void draw_node(GameVertex* v); void draw_player_info(); + void draw_menu_bars(); void handle_button_press(ButtonAction action); + void mode_changed(); // data GameData data; diff --git a/menubutton.cpp b/menubutton.cpp index 69e8547..47bf824 100644 --- a/menubutton.cpp +++ b/menubutton.cpp @@ -3,7 +3,8 @@ MenuButton::MenuButton(string text, TTF_Font* font, int x, int y, - ButtonAction action) + ButtonAction action, int colour, int hover_colour, + int selected_colour, int background_colour) { this->text = text; this->x = x; @@ -11,29 +12,99 @@ MenuButton::MenuButton(string text, TTF_Font* font, int x, int y, this->font = font; this->action = action; + this->colour = colour; + this->hover_colour = hover_colour; + this->selected_colour = selected_colour; + this->background_colour = background_colour; +} + + +bool MenuButton::init() +{ hover = false; + selected = false; + visible = true; + return true; } -void MenuButton::set_hover(bool is_hovering) +void MenuButton::set_selected(bool is_selected) { - hover = is_hovering; + selected = is_selected; } -void MenuButton::draw(SDL_Surface* display, int colour, int background_colour) +void MenuButton::set_visible(bool is_visible) { + visible = is_visible; +} + + +void MenuButton::iterate() +{ + int x, y; + SDL_GetMouseState(&x, &y); + if (is_at(x, y)) hover = true; + else hover = false; +} + + +void MenuButton::render(SDL_Surface* display) +{ + if (!visible) return; + + int colour_to_use = colour; + if (selected) colour_to_use = selected_colour; + else if (hover) colour_to_use = hover_colour; + SDL_Rect pen = {x, y, 80, 20}; SDL_FillRect(display, &pen, background_colour); int temp_colour = 0x000000; - DrawUtils::draw_text(display, text, x + 40, y + 10, font, colour, 1, 1); + DrawUtils::draw_text(display, text, x + 40, y + 10, font, colour_to_use, + 1, 1); } bool MenuButton::is_at(int test_x, int test_y) { + if (!visible) return false; return test_x >= x && test_y >= y && test_x <= x + 100 && test_y <= y + 40; } + + +void MenuButton::set_state(Mode mode, VertexType type, GameVertex* current) +{ + selected = false; + visible = false; + + if (action & BUTTON_END_TURN) + { + visible = true; + return; + } + + if ((mode & MODE_ATTACK && action & BUTTON_ATTACK) || + (mode & MODE_MOVE && action & BUTTON_MOVE) || + (mode & MODE_BUILD && action & BUTTON_BUILD) || + (type & VERTEX_ATTACKER && action & BUTTON_BUILD_ATTACKER) || + (type & VERTEX_DEFENDER && action & BUTTON_BUILD_DEFENDER) || + (type & VERTEX_PRODUCER && action & BUTTON_BUILD_PRODUCER) + ) + selected = true; + + // If we have selected one of our vertices, and we're one of the three + // main buttons, be visible + if (current != NULL && action & (BUTTON_ATTACK | BUTTON_MOVE | + BUTTON_BUILD)) + visible = true; + + // If we're one of the other three, and we're in MODE_BUILD, we're visible + if (mode & MODE_BUILD && action & (BUTTON_BUILD_ATTACKER | + BUTTON_BUILD_DEFENDER | + BUTTON_BUILD_PRODUCER)) + visible = true; +} + diff --git a/menubutton.h b/menubutton.h index 4d762f0..794316a 100644 --- a/menubutton.h +++ b/menubutton.h @@ -8,6 +8,9 @@ #include #include #include +#include "entity.h" +#include "gamedata.h" +#include "gamevertex.h" using std::string; @@ -17,27 +20,45 @@ enum ButtonAction {BUTTON_BUILD=0x1, BUTTON_ATTACK=0x2, BUTTON_MOVE=0x4, BUTTON_BUILD_ATTACKER=0x8, BUTTON_BUILD_DEFENDER=0x10, BUTTON_BUILD_PRODUCER=0x20, BUTTON_END_TURN=0x40}; -class MenuButton +class MenuButton : public Entity { public: MenuButton(string text = "", TTF_Font* font = NULL, int x = 0, int y = 0, - ButtonAction action = BUTTON_BUILD); + ButtonAction action = BUTTON_BUILD, int colour=0x000000, + int hover_colour=0xff0000, int selected_colour=0x0000ff, + int background_colour=0x888888); // Selectable buttons change colour for the duration they are selected, // and should ignore clicks while selected - void set_hover(bool is_hovering); - void draw(SDL_Surface* display, int colour = 0x000000, - int background_colour = 0x888888); + void set_selected(bool is_selected); + void set_visible(bool is_visible); + + bool init(); + void render(SDL_Surface* display); + void iterate(); bool is_at(int test_x, int test_y); ButtonAction get_action() const { return action; } + + // To get some complexity out of the Game class, let's teach MenuButton + // how to handle her own state, based on the current Mode and VertexType + // This isn't wonderful coupling, but it'll do + void set_state(Mode mode, VertexType type, GameVertex* current); + private: string text; int x; int y; + int colour; + int hover_colour; + int selected_colour; + int background_colour; + bool hover; + bool selected; + bool visible; TTF_Font* font;