Separated game-specific graph behavior into a subclass, implemented 2 players alternating turns

This commit is contained in:
Anna Rose 2011-06-23 17:28:49 -04:00
parent b967542157
commit 5ed05fc829
7 changed files with 170 additions and 81 deletions

View File

@ -4,7 +4,7 @@ PROJECT=graphgame
CXX=g++ CXX=g++
CXXFLAGS=-DDEBUG -g CXXFLAGS=-DDEBUG -g
LDFLAGS=-lSDL LDFLAGS=-lSDL
OBJECTS=drawutils.o gamecore.o graph.o main.o mainevent.o mathutils.o OBJECTS=drawutils.o gamecore.o graph.o main.o mainevent.o mathutils.o gamedata.o
all: $(PROJECT) all: $(PROJECT)

View File

@ -5,17 +5,12 @@
int GameCore::MAX_MOVE_DISTANCE = 100; int GameCore::MAX_MOVE_DISTANCE = 100;
int GameCore::NODE_RADIUS = 12; int GameCore::NODE_RADIUS = 12;
int GameCore::PLAYER1_COLOUR = 0x4a483f;
int GameCore::PLAYER2_COLOUR = 0x090c7a;
GameCore::GameCore() GameCore::GameCore()
{ {
display = NULL; display = NULL;
background = NULL; background = NULL;
is_running = true; is_running = true;
who = PLAYER1;
} }
int GameCore::execute() int GameCore::execute()
@ -73,12 +68,12 @@ void GameCore::render()
{ {
DrawUtils::draw(display, background, 0, 0); DrawUtils::draw(display, background, 0, 0);
list<Vertex*> vertices = graph.get_vertices(); list<Vertex*> vertices = data.get_vertices();
list<Edge> edges = graph.get_edges(); list<Edge> edges = data.get_edges();
if (graph.get_current_vertex() != NULL) if (data.get_current_vertex() != NULL)
{ {
Vertex* v = graph.get_current_vertex(); Vertex* v = data.get_current_vertex();
DrawUtils::draw_circle_filled(display, v->x, v->y, DrawUtils::draw_circle_filled(display, v->x, v->y,
MAX_MOVE_DISTANCE, 0xcb1919); MAX_MOVE_DISTANCE, 0xcb1919);
} }
@ -125,26 +120,20 @@ void GameCore::on_exit()
void GameCore::on_lbutton_down(int x, int y) void GameCore::on_lbutton_down(int x, int y)
{ {
Vertex* cv = graph.get_current_vertex(); Vertex* cv = data.get_current_vertex();
if (cv != NULL && if (cv != NULL &&
(MathUtils::distance(cv->x, cv->y, x, y) (MathUtils::distance(cv->x, cv->y, x, y)
> MAX_MOVE_DISTANCE)) > MAX_MOVE_DISTANCE))
{ {
Vertex* v = graph.vertex_at(x, y); data.select_vertex(x, y);
if (v->colour == PLAYER1_COLOUR && turn == PLAYER1 ||
v->colour == PLAYER2_COLOUR && turn == PLAYER2)
graph.select_vertex(x, y);
return; return;
} }
graph.do_vertex(x, y, NODE_RADIUS, PLAYER1_COLOUR); data.do_vertex(x, y, NODE_RADIUS);
if (turn == PLAYER1) turn = PLAYER2;
else turn = PLAYER_1;
} }
void GameCore::on_rbutton_down(int mX, int mY) void GameCore::on_rbutton_down(int mX, int mY)
{ {
graph.clear_current_vertex(); data.clear_current_vertex();
} }

View File

@ -11,9 +11,7 @@
#include <SDL/SDL.h> #include <SDL/SDL.h>
#include "mainevent.h" #include "mainevent.h"
#include "graph.h" #include "gamedata.h"
enum turn {PLAYER1, PLAYER2, WIN1, WIN2};
class GameCore : public MainEvent class GameCore : public MainEvent
{ {
@ -42,13 +40,10 @@ class GameCore : public MainEvent
SDL_Surface* background; SDL_Surface* background;
// data // data
Graph graph; GameData data;
turn who;
static int NODE_RADIUS; static int NODE_RADIUS;
static int MAX_MOVE_DISTANCE; static int MAX_MOVE_DISTANCE;
static int PLAYER1_COLOUR;
static int PLAYER2_COLOUR;
}; };

76
gamedata.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "gamedata.h"
#include "mathutils.h"
int GameData::PLAYER1_COLOUR = 0x4a483f;
int GameData::PLAYER2_COLOUR = 0x090c7a;
GameData::GameData()
: Graph(true)
{
current = NULL;
player = PLAYER1;
}
GameData::~GameData() { }
void GameData::toggle_turn()
{
if (player == PLAYER1) player = PLAYER2;
else if (player == PLAYER2) player = PLAYER1;
}
void GameData::do_vertex(int x, int y, int r)
{
int colour;
if (player == PLAYER1) colour = PLAYER1_COLOUR;
if (player == PLAYER2) colour = PLAYER2_COLOUR;
if (point_in_vertex(x, y, r)) select_vertex(x, y);
else add_vertex(x, y, r, colour);
}
void GameData::select_vertex(int x, int y)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if ((MathUtils::distance(v->x, v->y, x, y) <= v->r) &&
(v->colour == PLAYER1_COLOUR && player == PLAYER1 ||
v->colour == PLAYER2_COLOUR && player == PLAYER2))
{
current = v;
return;
}
}
}
bool GameData::add_vertex(int x, int y, int r, int colour)
{
// this is the special case for adding the first vertex for each player
if (current == NULL)
{
if ((player == PLAYER1 && !player1_played) ||
(player == PLAYER2 && !player2_played))
{
Graph::add_vertex(x, y, r, colour);
if (player == PLAYER1) player1_played = true;
if (player == PLAYER2) player2_played = true;
toggle_turn();
return true;
}
return false;
}
if (Graph::add_vertex(x, y, r, colour, current))
{
clear_current_vertex();
toggle_turn();
return true;
}
return false;
}

40
gamedata.h Normal file
View File

@ -0,0 +1,40 @@
/* This takes the general graph code and does stuff specific to the game
* with it. It stores the current turn, selected vertex and other useful
* information
*/
#ifndef _GAMEDATA_H_
#define _GAMEDATA_H_
#include "graph.h"
enum Turn {PLAYER1, PLAYER2, WIN1, WIN2};
class GameData : public Graph
{
public:
GameData();
~GameData();
Vertex* get_current_vertex() const { return current; }
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);
bool add_vertex(int x, int y, int r, int colour);
private:
Vertex* current;
Turn player;
bool player1_played;
bool player2_played;
static int PLAYER1_COLOUR;
static int PLAYER2_COLOUR;
};
#endif

View File

@ -2,9 +2,9 @@
#include "mathutils.h" #include "mathutils.h"
#include "debug.h" #include "debug.h"
Graph::Graph() Graph::Graph(bool planar)
{ {
current_vertex = NULL; this->planar = planar;
} }
Graph::~Graph() Graph::~Graph()
@ -17,7 +17,7 @@ Graph::~Graph()
} }
} }
bool Graph::vertex_present(int x, int y, int r) bool Graph::point_in_vertex(int x, int y, int r)
{ {
for (list<Vertex*>::iterator cursor = vertices.begin(); for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++) cursor != vertices.end(); cursor++)
@ -30,6 +30,19 @@ bool Graph::vertex_present(int x, int y, int r)
} }
Vertex * Graph::vertex_at(int x, int y)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if (MathUtils::distance(v->x, v->y, x, y) <= v->r) return v;
}
return NULL;
}
bool Graph::vertex_would_overlap(int x, int y, int r) bool Graph::vertex_would_overlap(int x, int y, int r)
{ {
for (list<Vertex*>::iterator cursor = vertices.begin(); for (list<Vertex*>::iterator cursor = vertices.begin();
@ -58,30 +71,7 @@ bool Graph::crosses_edge(Edge e)
} }
void Graph::do_vertex(int x, int y, int r, int colour) bool Graph::add_vertex(int x, int y, int r, int colour, Vertex* src)
{
if (vertex_present(x, y, r)) select_vertex(x, y);
else add_vertex(x, y, r, colour);
}
Vertex* Graph::select_vertex(int x, int y)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if (MathUtils::distance(v->x, v->y, x, y) <= v->r)
{
current_vertex = v
return;
}
}
return NULL;
}
void Graph::add_vertex(int x, int y, int r, int colour)
{ {
Vertex* v = new Vertex(x, y, r, colour); Vertex* v = new Vertex(x, y, r, colour);
@ -92,36 +82,34 @@ void Graph::add_vertex(int x, int y, int r, int colour)
fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to vertex collision: x=%d, y=%d, r=%d\n", v->x, v->y, v->r); fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to vertex collision: x=%d, y=%d, r=%d\n", v->x, v->y, v->r);
#endif #endif
delete v; delete v;
return; return false;
} }
if (current_vertex == NULL) if (src != NULL)
{ {
current_vertex = v; Edge e;
vertices.push_back(v); e.a = src;
return; e.b = v;
}
Edge e; if (planar && crosses_edge(e))
e.a = current_vertex; {
e.b = v;
if (crosses_edge(e))
{
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to edge collision: x1=%d, y1=%d, x2=%d, y2=%d\n", e.a->x, e.a->y, e.b->x, e.b->y); fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to edge collision: x1=%d, y1=%d, x2=%d, y2=%d\n", e.a->x, e.a->y, e.b->x, e.b->y);
#endif #endif
delete v; delete v;
return; return false;
}
edges.push_back(e);
} }
vertices.push_back(v); vertices.push_back(v);
edges.push_back(e);
current_vertex = v;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "debug: Graph::add_vertex(): added: x=%d, y=%d, r=%d\n", v->x, v->y, v->r); fprintf(stderr, "debug: Graph::add_vertex(): added: x=%d, y=%d, r=%d\n", v->x, v->y, v->r);
#endif #endif
return true;
} }

21
graph.h
View File

@ -31,28 +31,29 @@ struct Edge
class Graph class Graph
{ {
public: public:
Graph(); Graph(bool planar);
~Graph(); virtual ~Graph();
bool vertex_present(int x, int y, int size);
list<Vertex*> get_vertices() const { return vertices; } list<Vertex*> get_vertices() const { return vertices; }
list<Edge> get_edges() const { return edges; } list<Edge> get_edges() const { return edges; }
void select_vertex(int x, int y); bool point_in_vertex(int x, int y, int size);
void do_vertex(int x, int y, int r, int colour); Vertex * vertex_at(int x, int y);
virtual bool add_vertex(int x, int y, int r, int colour, Vertex* src=NULL);
Vertex* get_current_vertex() const { return current_vertex; } bool is_planar() const { return planar; }
void clear_current_vertex() { current_vertex = NULL; } void set_planar(bool planar) { this->planar = planar; }
private: private:
void add_vertex(int x, int y, int r, int colour);
bool vertex_would_overlap(int x, int y, int r); bool vertex_would_overlap(int x, int y, int r);
bool crosses_edge(Edge e); bool crosses_edge(Edge e);
Vertex* current_vertex; protected:
list<Vertex*> vertices; list<Vertex*> vertices;
list<Edge> edges; list<Edge> edges;
private:
bool planar;
}; };
#endif #endif