2011-06-28 02:07:52 +00:00
|
|
|
#include "game.h"
|
|
|
|
#include "mathutils.h"
|
2011-06-28 02:35:52 +00:00
|
|
|
#include "drawutils.h"
|
2011-06-28 02:07:52 +00:00
|
|
|
#include "debug.h"
|
2011-07-01 17:15:30 +00:00
|
|
|
#include "itos.h"
|
2011-06-28 02:07:52 +00:00
|
|
|
#include <SDL.h>
|
2011-06-28 02:35:52 +00:00
|
|
|
|
2011-06-30 21:21:46 +00:00
|
|
|
Game::Game(stack<GameState*>* state_stack, SDL_Surface* display)
|
|
|
|
: GameState(state_stack, display)
|
2011-06-28 02:35:52 +00:00
|
|
|
{
|
|
|
|
background = NULL;
|
2011-07-01 17:15:30 +00:00
|
|
|
font = NULL;
|
2011-06-28 02:35:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-28 02:07:52 +00:00
|
|
|
Game::~Game()
|
|
|
|
{
|
2011-06-29 01:44:28 +00:00
|
|
|
if (background != NULL)
|
|
|
|
SDL_FreeSurface(background);
|
2011-07-01 17:15:30 +00:00
|
|
|
if (font != NULL)
|
|
|
|
TTF_CloseFont(font);
|
2011-07-03 14:12:47 +00:00
|
|
|
|
|
|
|
for (list<MenuButton*>::iterator cursor = buttons.begin();
|
|
|
|
cursor != buttons.end(); cursor++)
|
|
|
|
{
|
|
|
|
delete *cursor;
|
|
|
|
}
|
2011-06-28 02:07:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Game::init()
|
|
|
|
{
|
2011-06-28 02:35:52 +00:00
|
|
|
background = DrawUtils::load("background.bmp");
|
2011-07-03 20:46:16 +00:00
|
|
|
font = TTF_OpenFont("res/LiberationSans-Regular.ttf", 12);
|
2011-07-01 17:15:30 +00:00
|
|
|
|
2011-07-06 18:52:45 +00:00
|
|
|
if (background == NULL || font == NULL)
|
2011-07-01 17:15:30 +00:00
|
|
|
{
|
2011-07-03 19:16:00 +00:00
|
|
|
debug("Game::init(): error: Couldn't load some resource(s)");
|
2011-07-01 17:15:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-07-03 14:26:46 +00:00
|
|
|
int row1 = display->h - 95;
|
2011-07-04 06:23:20 +00:00
|
|
|
int row2 = display->h - 65;
|
|
|
|
int row3 = display->h - 35;
|
2011-07-03 14:26:46 +00:00
|
|
|
int col1 = 155;
|
2011-07-04 06:23:20 +00:00
|
|
|
int col2 = 255;
|
|
|
|
int col3 = 355;
|
|
|
|
int col4 = 455;
|
2011-07-03 14:26:46 +00:00
|
|
|
|
2011-07-04 06:00:43 +00:00
|
|
|
buttons.push_back(new MenuButton("Move (m)", font, col1, row1,
|
|
|
|
BUTTON_MOVE));
|
|
|
|
buttons.push_back(new MenuButton("Build (b)", font, col1, row2,
|
2011-07-03 14:12:47 +00:00
|
|
|
BUTTON_BUILD));
|
2011-07-04 06:23:20 +00:00
|
|
|
buttons.push_back(new MenuButton("Attack (a)", font, col1, row3,
|
2011-07-03 14:26:46 +00:00
|
|
|
BUTTON_ATTACK));
|
2011-07-04 06:23:20 +00:00
|
|
|
buttons.push_back(new MenuButton("Attacker (t)", font, col2, row1,
|
2011-07-03 14:26:46 +00:00
|
|
|
BUTTON_BUILD_ATTACKER));
|
2011-07-04 06:23:20 +00:00
|
|
|
buttons.push_back(new MenuButton("Defender (d)", font, col2, row2,
|
2011-07-03 14:26:46 +00:00
|
|
|
BUTTON_BUILD_DEFENDER));
|
2011-07-04 06:23:20 +00:00
|
|
|
buttons.push_back(new MenuButton("Producer (p)", font, col2, row3,
|
2011-07-03 14:26:46 +00:00
|
|
|
BUTTON_BUILD_PRODUCER));
|
2011-07-04 06:23:20 +00:00
|
|
|
buttons.push_back(new MenuButton("End Turn (e)", font, col4, row3,
|
2011-07-03 21:45:11 +00:00
|
|
|
BUTTON_END_TURN));
|
2011-07-02 21:34:11 +00:00
|
|
|
|
|
|
|
|
2011-07-06 18:24:37 +00:00
|
|
|
for (list<MenuButton*>::iterator cursor = buttons.begin();
|
|
|
|
cursor != buttons.end(); cursor++)
|
|
|
|
{
|
|
|
|
if (!(*cursor)->init())
|
|
|
|
{
|
|
|
|
debug("Failed to initialize a button");
|
|
|
|
throw StateExit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mode_changed();
|
|
|
|
|
|
|
|
|
2011-07-01 15:40:38 +00:00
|
|
|
return GameState::init();
|
2011-06-28 02:35:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-06 18:24:37 +00:00
|
|
|
void Game::iterate()
|
|
|
|
{
|
|
|
|
// handle the button iterations
|
|
|
|
for (list<MenuButton*>::iterator cursor = buttons.begin();
|
|
|
|
cursor != buttons.end(); cursor++)
|
|
|
|
{
|
|
|
|
(*cursor)->iterate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-28 02:35:52 +00:00
|
|
|
void Game::render()
|
|
|
|
{
|
|
|
|
int range = data.get_range();
|
|
|
|
int range_colour = 0x888888;
|
|
|
|
|
|
|
|
switch(data.get_mode())
|
|
|
|
{
|
2011-07-01 18:10:45 +00:00
|
|
|
case MODE_BUILD:
|
2011-06-28 02:35:52 +00:00
|
|
|
range_colour = 0x0000ff;
|
|
|
|
break;
|
2011-07-01 18:10:45 +00:00
|
|
|
case MODE_MOVE:
|
|
|
|
range_colour = 0x00ff00;
|
|
|
|
break;
|
2011-06-28 02:35:52 +00:00
|
|
|
case MODE_ATTACK:
|
|
|
|
range_colour = 0xff0000;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Background image first
|
|
|
|
DrawUtils::draw(display, background, 0, 0);
|
|
|
|
|
|
|
|
// Now paint on the targeting circle
|
2011-07-01 18:10:45 +00:00
|
|
|
if (data.get_current_vertex(true) != NULL)
|
2011-06-28 02:35:52 +00:00
|
|
|
{
|
2011-07-03 20:57:47 +00:00
|
|
|
GameVertex* v = data.get_current_vertex();
|
2011-06-28 02:35:52 +00:00
|
|
|
DrawUtils::draw_circle_filled(display, v->x, v->y, range,
|
|
|
|
range_colour);
|
|
|
|
}
|
|
|
|
|
2011-07-03 19:16:00 +00:00
|
|
|
// First draw the edges, so that they don't obscure any data
|
2011-07-03 20:57:47 +00:00
|
|
|
list<Vertex*> vertices = data.get_vertices();
|
2011-06-28 02:35:52 +00:00
|
|
|
for (list<Vertex*>::iterator cursor = vertices.begin();
|
|
|
|
cursor != vertices.end(); cursor++)
|
|
|
|
{
|
|
|
|
Vertex* v = *cursor;
|
2011-07-01 17:15:30 +00:00
|
|
|
|
2011-06-28 02:35:52 +00:00
|
|
|
for (list<Vertex*>::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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-04 05:27:56 +00:00
|
|
|
// highlight the selected vertex and write info about it
|
2011-07-01 21:44:43 +00:00
|
|
|
if (data.get_current_vertex() != NULL)
|
|
|
|
{
|
2011-07-03 20:57:47 +00:00
|
|
|
GameVertex* v = data.get_current_vertex();
|
2011-07-01 21:44:43 +00:00
|
|
|
DrawUtils::draw_circle(display, v->x, v->y, v->r + 5, 0x000000);
|
2011-07-01 22:04:15 +00:00
|
|
|
draw_stats(v);
|
2011-07-01 21:44:43 +00:00
|
|
|
}
|
|
|
|
|
2011-07-03 19:16:00 +00:00
|
|
|
// Draw each node
|
|
|
|
for (list<Vertex*>::iterator cursor = vertices.begin();
|
|
|
|
cursor != vertices.end(); cursor++)
|
|
|
|
{
|
2011-07-06 18:52:45 +00:00
|
|
|
dynamic_cast<GameVertex*>(*cursor)->render(display);
|
2011-07-03 19:16:00 +00:00
|
|
|
}
|
|
|
|
|
2011-07-02 03:47:24 +00:00
|
|
|
// draw the rest of the bottom menu
|
2011-07-06 18:24:37 +00:00
|
|
|
draw_menu_bars();
|
2011-07-06 18:52:45 +00:00
|
|
|
draw_player_info();
|
2011-07-02 21:34:11 +00:00
|
|
|
|
2011-07-04 06:23:20 +00:00
|
|
|
for (list<MenuButton*>::iterator cursor = buttons.begin();
|
|
|
|
cursor != buttons.end(); cursor++)
|
2011-07-02 21:34:11 +00:00
|
|
|
{
|
2011-07-06 18:24:37 +00:00
|
|
|
(*cursor)->render(display);
|
2011-07-02 21:34:11 +00:00
|
|
|
}
|
|
|
|
|
2011-06-28 02:35:52 +00:00
|
|
|
SDL_Flip(display);
|
2011-06-28 02:07:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-06 18:24:37 +00:00
|
|
|
void Game::draw_menu_bars()
|
2011-07-02 21:34:11 +00:00
|
|
|
{
|
2011-07-06 18:24:37 +00:00
|
|
|
// horizontal line across the whole thing
|
|
|
|
DrawUtils::draw_line(display, 0, display->h - 100,
|
|
|
|
display->w, display->h - 100, 2, 0x000000);
|
|
|
|
|
|
|
|
// vertical lines to separate info panes from button pane
|
|
|
|
DrawUtils::draw_line(display, 150, display->h - 100, 150, display->h, 2,
|
|
|
|
0x000000);
|
|
|
|
DrawUtils::draw_line(display, 540, display->h - 100, 540, display->h, 2,
|
|
|
|
0x000000);
|
|
|
|
DrawUtils::draw_line(display, display->w - 100, display->h - 100,
|
|
|
|
display->w - 100, display->h, 2,
|
|
|
|
0x000000);
|
2011-07-02 21:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-04 05:27:56 +00:00
|
|
|
void Game::draw_player_info()
|
|
|
|
{
|
|
|
|
Player* player = data.get_turn();
|
|
|
|
|
2011-07-04 06:23:20 +00:00
|
|
|
DrawUtils::draw_text(display, player->get_name(), 10, display->h - 95,
|
2011-07-04 05:27:56 +00:00
|
|
|
font);
|
|
|
|
|
|
|
|
string temp = "Energy: ";
|
|
|
|
temp += itos(player->get_energy());
|
2011-07-04 06:23:20 +00:00
|
|
|
DrawUtils::draw_text(display, temp, 10, display->h - 80, font);
|
2011-07-04 05:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-03 14:12:47 +00:00
|
|
|
void Game::handle_button_press(ButtonAction action)
|
|
|
|
{
|
|
|
|
switch (action)
|
|
|
|
{
|
|
|
|
case BUTTON_BUILD:
|
|
|
|
data.set_mode(MODE_BUILD);
|
|
|
|
break;
|
|
|
|
case BUTTON_ATTACK:
|
|
|
|
data.set_mode(MODE_ATTACK);
|
|
|
|
break;
|
|
|
|
case BUTTON_MOVE:
|
|
|
|
data.set_mode(MODE_MOVE);
|
|
|
|
break;
|
|
|
|
case BUTTON_BUILD_ATTACKER:
|
|
|
|
data.set_build_type(VERTEX_ATTACKER);
|
|
|
|
break;
|
|
|
|
case BUTTON_BUILD_DEFENDER:
|
|
|
|
data.set_build_type(VERTEX_DEFENDER);
|
|
|
|
break;
|
|
|
|
case BUTTON_BUILD_PRODUCER:
|
|
|
|
data.set_build_type(VERTEX_PRODUCER);
|
|
|
|
break;
|
2011-07-03 21:45:11 +00:00
|
|
|
case BUTTON_END_TURN:
|
|
|
|
data.toggle_turn();
|
|
|
|
break;
|
2011-07-03 14:12:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-03 20:57:47 +00:00
|
|
|
void Game::draw_stats(GameVertex* v)
|
2011-07-01 22:04:15 +00:00
|
|
|
{
|
2011-07-03 19:48:06 +00:00
|
|
|
int line_num = 0;
|
|
|
|
int line_height = 14;
|
2011-07-04 06:23:20 +00:00
|
|
|
int x = 550;
|
2011-07-03 19:48:06 +00:00
|
|
|
int y = display->h - 95;
|
|
|
|
int adj_y = y;
|
|
|
|
|
2011-07-04 06:23:20 +00:00
|
|
|
DrawUtils::draw_text(display, "owner:", x, adj_y, font);
|
2011-07-03 20:57:47 +00:00
|
|
|
DrawUtils::draw_text(display, v->player->get_name(), x + 50, adj_y, font);
|
2011-07-03 19:48:06 +00:00
|
|
|
|
|
|
|
line_num++;
|
|
|
|
adj_y = y + line_num * line_height;
|
|
|
|
DrawUtils::draw_text(display, "type:", x, adj_y, font);
|
|
|
|
string type;
|
2011-07-03 20:57:47 +00:00
|
|
|
switch(v->type)
|
2011-07-03 19:48:06 +00:00
|
|
|
{
|
|
|
|
case VERTEX_ATTACKER:
|
|
|
|
type = "attacker";
|
|
|
|
break;
|
|
|
|
case VERTEX_DEFENDER:
|
|
|
|
type = "defender";
|
|
|
|
break;
|
|
|
|
case VERTEX_PRODUCER:
|
|
|
|
type = "producer";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
DrawUtils::draw_text(display, type, x + 50, adj_y, font);
|
|
|
|
|
|
|
|
line_num++;
|
|
|
|
adj_y = y + line_num * line_height;
|
|
|
|
DrawUtils::draw_text(display, "atk:", x, adj_y, font);
|
2011-07-03 20:57:47 +00:00
|
|
|
DrawUtils::draw_text(display, itos(v->calculate_attack()),
|
2011-07-03 19:48:06 +00:00
|
|
|
x + 50, adj_y, font);
|
|
|
|
|
|
|
|
line_num++;
|
|
|
|
adj_y = y + line_num * line_height;
|
|
|
|
DrawUtils::draw_text(display, "armor:", x, adj_y, font);
|
2011-07-03 20:57:47 +00:00
|
|
|
DrawUtils::draw_text(display, itos(v->calculate_armor()),
|
2011-07-03 19:48:06 +00:00
|
|
|
x + 50, adj_y, font);
|
2011-07-01 22:04:15 +00:00
|
|
|
|
2011-07-03 19:48:06 +00:00
|
|
|
line_num++;
|
|
|
|
adj_y = y + line_num * line_height;
|
|
|
|
DrawUtils::draw_text(display, "hp:", x, adj_y, font);
|
|
|
|
DrawUtils::draw_text(display, itos(v->score), x + 50, adj_y, font);
|
2011-07-01 22:04:15 +00:00
|
|
|
|
2011-07-03 20:57:47 +00:00
|
|
|
if (v->type == VERTEX_PRODUCER)
|
2011-07-03 19:48:06 +00:00
|
|
|
{
|
|
|
|
line_num++;
|
|
|
|
adj_y = y + line_num * line_height;
|
|
|
|
|
|
|
|
DrawUtils::draw_text(display, "energy:", x, adj_y, font);
|
|
|
|
DrawUtils::draw_text(display, "25", x + 50, adj_y, font);
|
|
|
|
}
|
2011-07-01 22:04:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-28 02:07:52 +00:00
|
|
|
void Game::on_lbutton_down(int x, int y)
|
|
|
|
{
|
2011-07-03 14:12:47 +00:00
|
|
|
for (list<MenuButton*>::iterator cursor = buttons.begin();
|
|
|
|
cursor != buttons.end(); cursor++)
|
|
|
|
{
|
|
|
|
MenuButton* button = *cursor;
|
2011-07-06 18:24:37 +00:00
|
|
|
if (button->is_at(x, y))
|
|
|
|
{
|
|
|
|
handle_button_press(button->get_action());
|
|
|
|
mode_changed();
|
|
|
|
return;
|
|
|
|
}
|
2011-07-03 14:12:47 +00:00
|
|
|
}
|
2011-07-02 03:47:24 +00:00
|
|
|
|
2011-07-03 14:12:47 +00:00
|
|
|
if (y > display->h - 110) return;
|
2011-07-01 18:10:45 +00:00
|
|
|
if (!data.endgame()) data.handle_click(x, y);
|
2011-07-06 18:24:37 +00:00
|
|
|
mode_changed();
|
2011-06-28 02:07:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Game::on_rbutton_down(int mX, int mY)
|
|
|
|
{
|
|
|
|
data.clear_current_vertex();
|
2011-07-06 18:24:37 +00:00
|
|
|
mode_changed();
|
2011-06-28 02:07:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Game::on_key_down(SDLKey sym, SDLMod mod, Uint16 unicode)
|
|
|
|
{
|
|
|
|
if (sym == SDLK_q && mod & KMOD_CTRL) throw StateExit();
|
2011-07-02 00:00:19 +00:00
|
|
|
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);
|
2011-07-04 06:00:43 +00:00
|
|
|
else if (sym == SDLK_d) data.set_build_type(VERTEX_DEFENDER);
|
|
|
|
else if (sym == SDLK_p) data.set_build_type(VERTEX_PRODUCER);
|
|
|
|
else if (sym == SDLK_t) data.set_build_type(VERTEX_ATTACKER);
|
2011-07-02 00:00:19 +00:00
|
|
|
else if (sym == SDLK_s || sym == SDLK_ESCAPE) data.set_mode(MODE_SELECT);
|
2011-07-03 21:45:11 +00:00
|
|
|
else if (sym == SDLK_e) data.toggle_turn();
|
2011-07-02 00:00:19 +00:00
|
|
|
|
2011-07-06 18:24:37 +00:00
|
|
|
mode_changed();
|
|
|
|
|
2011-07-02 00:00:19 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (sym == SDLK_d && mod & (KMOD_ALT | KMOD_CTRL)) print_debug_info();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-07-02 21:34:11 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-02 00:00:19 +00:00
|
|
|
#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());
|
2011-06-28 02:07:52 +00:00
|
|
|
}
|
2011-07-02 00:00:19 +00:00
|
|
|
#endif
|
2011-07-06 18:24:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
void Game::mode_changed()
|
|
|
|
{
|
|
|
|
// Set the state for each button
|
|
|
|
for (list<MenuButton*>::iterator cursor = buttons.begin();
|
|
|
|
cursor != buttons.end(); cursor++)
|
|
|
|
{
|
|
|
|
(*cursor)->set_state(data.get_mode(), data.get_build_type(),
|
|
|
|
data.get_current_vertex());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|