treewars/game.cpp

224 lines
5.3 KiB
C++

#include "game.h"
#include "mathutils.h"
#include "drawutils.h"
#include "debug.h"
#include "itos.h"
#include <SDL.h>
Game::Game(stack<GameState*>* 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<Vertex*> 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<Vertex*>::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<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);
}
}
// Add hit points on top of the nodes
for (list<Vertex*>::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<GameVertex*>(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