#include "game.h" #include "mathutils.h" #include "drawutils.h" #include "debug.h" #include "itos.h" #include Game::Game(stack* state_stack, SDL_Surface* display) : GameState(state_stack, display) { background = NULL; font = NULL; } Game::~Game() { if (background != NULL) SDL_FreeSurface(background); if (font != NULL) TTF_CloseFont(font); } bool Game::init() { background = DrawUtils::load("background.bmp"); if (background == NULL) { debug("Game::init(): error: Couldn't load background image"); return false; } font = TTF_OpenFont("LiberationSans-Regular.ttf", 12); if (font == NULL) { debug("Game::init(): error: Couldn't load font"); return false; } move_button = MenuButton("Move", font, 155, display->h - 95, BUTTON_MOVE); attack_button = MenuButton("Attack", font, 260, display->h - 95, BUTTON_ATTACK); build_button = MenuButton("Build", font, 155, display->h - 50, BUTTON_BUILD); return GameState::init(); } void Game::render() { int range = data.get_range(); int range_colour = 0x888888; switch(data.get_mode()) { case MODE_BUILD: range_colour = 0x0000ff; break; case MODE_MOVE: range_colour = 0x00ff00; break; case MODE_ATTACK: range_colour = 0xff0000; break; } // Background image first DrawUtils::draw(display, background, 0, 0); list vertices = data.get_vertices(); // Now paint on the targeting circle if (data.get_current_vertex(true) != NULL) { Vertex* v = data.get_current_vertex(); DrawUtils::draw_circle_filled(display, v->x, v->y, range, range_colour); } // Now paint each vertex, and any edges that it needs for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; DrawUtils::draw_circle_filled(display, v->x, v->y, v->r, v->colour); for (list::iterator subcursor = v->neighbors.begin(); subcursor != v->neighbors.end(); subcursor++) { Vertex* v1 = *subcursor; DrawUtils::draw_line(display, v->x, v->y, v1->x, v1->y, 2, v->colour); } } // Add hit points on top of the nodes for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; DrawUtils::draw_text(display, itos(v->score), v->x, v->y, font, 0x00ff00, true, true); } // ring the selected vertex and write info about it if (data.get_current_vertex() != NULL) { Vertex* v = data.get_current_vertex(); DrawUtils::draw_circle(display, v->x, v->y, v->r + 5, 0x000000); draw_stats(v); } // draw the rest of the bottom menu // horizontal line across the whole thing DrawUtils::draw_line(display, 0, display->h - 100, display->w, display->h - 100, 2, 0x000000); // vertical line to separate info pane from button pane DrawUtils::draw_line(display, 150, display->h - 100, 150, display->h, 2, 0x000000); if (data.get_current_vertex() != NULL) { draw_button(&move_button); draw_button(&build_button); draw_button(&attack_button); } SDL_Flip(display); } void Game::draw_button(MenuButton* button) { int colour = 0x000000; ButtonAction action = button->get_action(); Mode mode = data.get_mode(); // 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)) colour = 0x0000ff; else if (button->is_at(cursor_x, cursor_y)) colour = 0xff0000; button->draw(display, colour); } void Game::draw_stats(Vertex* v) { int num_lines = 4; int x = 20; int y = display->h - 76; DrawUtils::draw_text(display, "player:", x, y, font); DrawUtils::draw_text(display, dynamic_cast(v)->player->get_name(), x + 50, y, font); DrawUtils::draw_text(display, "str:", x, y + 14, font); DrawUtils::draw_text(display, itos(data.calculate_strength(v)), x + 50, y + 14, font); DrawUtils::draw_text(display, "armor:", x, y + 28, font); DrawUtils::draw_text(display, itos(data.calculate_armor(v)), x + 50, y + 28, font); DrawUtils::draw_text(display, "hp:", x, y + 42, font); DrawUtils::draw_text(display, itos(v->score), x + 50, y + 42, font); } void Game::on_lbutton_down(int x, int y) { if (y > display->h - 110) return; if (!data.endgame()) data.handle_click(x, y); } void Game::on_rbutton_down(int mX, int mY) { data.clear_current_vertex(); } void Game::on_key_down(SDLKey sym, SDLMod mod, Uint16 unicode) { if (sym == SDLK_q && mod & KMOD_CTRL) throw StateExit(); else if (sym == SDLK_a) data.set_mode(MODE_ATTACK); else if (sym == SDLK_m) data.set_mode(MODE_MOVE); else if (sym == SDLK_b) data.set_mode(MODE_BUILD); else if (sym == SDLK_s || sym == SDLK_ESCAPE) data.set_mode(MODE_SELECT); #ifdef DEBUG if (sym == SDLK_d && mod & (KMOD_ALT | KMOD_CTRL)) print_debug_info(); #endif } void Game::on_mouse_move(int mX, int mY, int relX, int relY, bool left, bool right, bool middle) { cursor_x = mX; cursor_y = mY; } #ifdef DEBUG void Game::print_debug_info() { fprintf(stderr, "Mode: %d\n", data.get_mode()); fprintf(stderr, "Turn: %s\n", data.get_turn()->get_name().c_str()); } #endif