Laid the groundwork for a more complex game - introduced a couple of bugs (can attack from anywhere, can't select another of your own vertices in attack mode...)

This commit is contained in:
Anna Rose 2011-07-01 14:10:45 -04:00
parent d1c11799f4
commit 4daaced5d7
6 changed files with 138 additions and 64 deletions

View File

@ -7,7 +7,7 @@ LDFLAGS=`sdl-config --libs` -lSDL_ttf
OBJECTS=\
main.o \
drawutils.o mathutils.o timer.o itos.o \
graph.o gamedata.o \
graph.o gamedata.o player.o \
mainevent.o gamestate.o game.o titlescreen.o
all: $(PROJECT)

View File

@ -5,8 +5,6 @@
#include "itos.h"
#include <SDL.h>
int Game::NODE_RADIUS = 10;
Game::Game(stack<GameState*>* state_stack, SDL_Surface* display)
: GameState(state_stack, display)
@ -54,9 +52,12 @@ void Game::render()
switch(data.get_mode())
{
case MODE_MOVE:
case MODE_BUILD:
range_colour = 0x0000ff;
break;
case MODE_MOVE:
range_colour = 0x00ff00;
break;
case MODE_ATTACK:
range_colour = 0xff0000;
break;
@ -68,7 +69,7 @@ void Game::render()
list<Vertex*> vertices = data.get_vertices();
// Now paint on the targeting circle
if (data.get_current_vertex() != NULL)
if (data.get_current_vertex(true) != NULL)
{
Vertex* v = data.get_current_vertex();
DrawUtils::draw_circle_filled(display, v->x, v->y, range,
@ -104,7 +105,7 @@ void Game::render()
void Game::on_lbutton_down(int x, int y)
{
data.do_vertex(x, y, NODE_RADIUS);
if (!data.endgame()) data.handle_click(x, y);
}
@ -119,4 +120,5 @@ void Game::on_key_down(SDLKey sym, SDLMod mod, Uint16 unicode)
if (sym == SDLK_q && mod & KMOD_CTRL) throw StateExit();
if (sym == SDLK_a) data.set_mode(MODE_ATTACK);
if (sym == SDLK_m) data.set_mode(MODE_MOVE);
if (sym == SDLK_b) data.set_mode(MODE_BUILD);
}

View File

@ -10,102 +10,114 @@ using std::list;
int GameData::PLAYER1_COLOUR = 0x4a483f;
int GameData::PLAYER2_COLOUR = 0x090c7a;
int GameData::BASE_MOVE_RADIUS = 75;
int GameData::BASE_BUILD_RADIUS = 75;
int GameData::NODE_RADIUS = 10;
GameData::GameData()
: Graph(true)
{
current = NULL;
player = PLAYER1;
mode = MODE_MOVE;
mode = MODE_BUILD;
player1 = Player(PLAYER1_COLOUR);
player2 = Player(PLAYER2_COLOUR);
turn = &player1;
}
GameData::~GameData() { }
Vertex* GameData::get_current_vertex(bool only_mine) const
{
if (only_mine)
{
if (current != NULL &&
current->colour == turn->get_colour()) return current;
return NULL;
}
return current;
}
void GameData::toggle_turn()
{
mode = MODE_MOVE;
current = NULL;
if (!turn->has_played())
{
set_mode(MODE_BUILD);
turn->set_played();
}
else set_mode(MODE_SELECT);
if (!endgame())
{
if (player == PLAYER1) player = PLAYER2;
else if (player == PLAYER2) player = PLAYER1;
if (turn == &player1) turn = &player2;
else if (turn == &player2) turn = &player1;
}
}
void GameData::do_vertex(int x, int y, int r)
void GameData::handle_click(int x, int y)
{
if (current != NULL &&
(MathUtils::distance(current->x, current->y, current->z, x, y, 0)
> get_range()))
{
select_vertex(x, y);
return;
}
int r = 10;
int colour;
if (player == PLAYER1) colour = PLAYER1_COLOUR;
if (player == PLAYER2) colour = PLAYER2_COLOUR;
colour = turn->get_colour();
if (mode == MODE_MOVE)
if (mode == MODE_SELECT)
{
if (point_in_vertex(x, y, 0)) select_vertex(x, y);
else add_vertex(x, y, 0, r, colour);
}
if (mode == MODE_ATTACK)
else if (mode == MODE_BUILD)
{
if (point_in_vertex(x, y, 0)) select_vertex(x, y, true);
if (!point_in_vertex(x, y, 0)) add_vertex(x, y, 0, r, colour);
}
else if (mode == MODE_ATTACK)
{
Vertex* v = vertex_at(x, y, 0);
if (v == NULL) return;
if (v->colour == colour) select_vertex(x, y);
else attack_vertex(v);
if (v->colour != colour) attack_vertex(v);
}
}
void GameData::select_vertex(int x, int y)
void GameData::select_vertex(int x, int y, bool only_mine)
{
Vertex * v = vertex_at(x, y, 0);
if (v == NULL) return;
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if ((MathUtils::distance(v->x, v->y, v->z, x, y, 0) <= v->r) &&
(v->colour == PLAYER1_COLOUR && player == PLAYER1 ||
v->colour == PLAYER2_COLOUR && player == PLAYER2))
if (only_mine && v->colour == turn->get_colour())
{
current = v;
return;
}
}
current = v;
}
bool GameData::add_vertex(int x, int y, int z, int r, int colour)
{
if (mode == MODE_ATTACK) return false;
if (current == NULL)
{
// this is the special case for adding the first vertex for each player
if ((player == PLAYER1 && !player1_played) ||
(player == PLAYER2 && !player2_played))
if (!turn->has_played())
{
Graph::add_vertex(x, y, z, r, colour, 10);
#ifdef DEBUG
fprintf(stderr, "debug: GameData::add_vertex(): strength=%2.f\n",
calculate_strength(*(vertices.rbegin())));
#endif
if (player == PLAYER1) player1_played = true;
if (player == PLAYER2) player2_played = true;
toggle_turn();
return true;
}
return false;
}
if (current->colour != turn->get_colour()) return false;
if (Graph::add_vertex(x, y, z, r, colour, 10, current))
{
#ifdef DEBUG
@ -176,15 +188,22 @@ float GameData::calculate_strength_r(Vertex* node, unsigned int depth, list<Vert
}
Mode GameData::set_mode(Mode m)
{
mode = m;
}
int GameData::get_range(Vertex* node)
{
if (node == NULL) node = current;
if (node == NULL) return 0;
else if (mode == MODE_MOVE) return BASE_MOVE_RADIUS;
else if (mode == MODE_MOVE) return turn->get_energy();
else if (mode == MODE_BUILD) return BASE_BUILD_RADIUS;
else if (mode == MODE_ATTACK)
{
int range = BASE_MOVE_RADIUS;
int range = BASE_BUILD_RADIUS;
list<Vertex*> neighbors = node->neighbors;
for(list<Vertex*>::iterator cursor = neighbors.begin();
@ -223,17 +242,15 @@ void GameData::attack_vertex(Vertex* target)
bool GameData::endgame()
{
if (!(player1_played && player2_played)) return false;
if (!(player1.has_played() && player2.has_played())) return false;
if (get_colour(PLAYER1_COLOUR).empty())
if (get_colour(player1.get_colour()).empty())
{
player = WIN2;
debug("Gamedata::endgame(): player 2 wins\n");
return true;
}
if (get_colour(PLAYER2_COLOUR).empty())
if (get_colour(player2.get_colour()).empty())
{
player = WIN1;
debug("Gamedata::endgame(): player 1 wins\n");
return true;
}

View File

@ -7,9 +7,9 @@
#define _GAMEDATA_H_
#include "graph.h"
#include "player.h"
enum Turn {PLAYER1, PLAYER2, WIN1, WIN2};
enum Mode {MODE_MOVE, MODE_ATTACK};
enum Mode {MODE_MOVE, MODE_ATTACK, MODE_BUILD, MODE_SELECT};
enum VertexType {ATTACKER, DEFENDER, PRODUCER};
class GameVertex : public Vertex
@ -25,20 +25,20 @@ class GameData : public Graph
GameData();
~GameData();
Vertex* get_current_vertex() const { return current; }
Vertex* get_current_vertex(bool only_mine = false) const;
void clear_current_vertex() { current = NULL; }
void toggle_turn();
// select or add vertex, as appropriate
void do_vertex(int x, int y, int r);
void select_vertex(int x, int y);
void handle_click(int x, int y);
void select_vertex(int x, int y, bool only_mine = false);
void attack_vertex(Vertex* target);
bool add_vertex(int x, int y, int z, int r, int colour);
Mode get_mode() const { return mode; }
Mode set_mode(Mode m) { mode = m; }
Mode set_mode(Mode m);
// returns the move/attack range for the specified node
// (or the selected node if node == NULL)
@ -46,22 +46,22 @@ class GameData : public Graph
// check for (and set, if needed) winner
bool endgame();
Turn get_turn() const { return player; }
Player* get_turn() const { return turn; }
float calculate_strength(Vertex* node);
private:
float calculate_strength_r(Vertex* node, unsigned int depth, list<Vertex*>& visited);
Vertex* current;
Turn player;
Mode mode;
bool player1_played;
bool player2_played;
Player player1, player2;
Player* turn;
static int PLAYER1_COLOUR;
static int PLAYER2_COLOUR;
static int BASE_MOVE_RADIUS;
static int BASE_BUILD_RADIUS;
static int NODE_RADIUS;
};
#endif

28
player.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "player.h"
Player::Player(unsigned int colour)
{
this->colour = colour;
energy = 50;
}
void Player::add_energy(unsigned int amount)
{
energy += amount;
}
bool Player::spend_energy(unsigned int amount)
{
if (amount > energy) return false;
energy -= amount;
return true;
}
void Player::set_played()
{
played = true;
}

27
player.h Normal file
View File

@ -0,0 +1,27 @@
/* Holds some useful data about each player
*/
#ifndef _PLAYER_H_
#define _PLAYER_H_
class Player
{
public:
Player(unsigned int colour = 0x000000);
unsigned int get_energy() const { return energy; }
unsigned int get_colour() const { return colour; }
void add_energy(unsigned int amount);
bool spend_energy(unsigned int amount);
bool has_played() const { return played; }
void set_played();
private:
unsigned int energy;
unsigned int colour;
bool played;
};
#endif