summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormario <mario@notk.org>2011-11-30 03:46:41 +0100
committermario <mario@notk.org>2011-11-30 03:46:41 +0100
commit871745156d679f82f3be060af83dfd51a3416f09 (patch)
treec17729ebf4c28991e02029e46ecb6d122b77c152
parentf5c32b3b880deb0ff2eee7243e3f112469841e95 (diff)
~Doxygen-style commented. Not exactly doxygen but compatible and close enough.
-rw-r--r--AIController.h6
-rw-r--r--Cell.h13
-rw-r--r--Controller.h10
-rw-r--r--Field.h17
-rw-r--r--Game.cpp7
-rw-r--r--Game.h36
-rw-r--r--KeyboardController.h12
-rw-r--r--MainWindow.h70
-rw-r--r--Player.h58
-rw-r--r--TrollTron.cpp164
10 files changed, 363 insertions, 30 deletions
diff --git a/AIController.h b/AIController.h
index 3bbd54f..9d10f17 100644
--- a/AIController.h
+++ b/AIController.h
@@ -11,6 +11,9 @@
#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
#endif
+/**
+ * Artificial intelligence
+ **/
class AIController : public Controller
{
@@ -22,6 +25,9 @@ public:
void reset();
private:
+ /**
+ * Decide if and in what direction it will turn. Optimized to ben "smart" (with parameters)
+ **/
void turnRandom();
Field& m_field;
diff --git a/Cell.h b/Cell.h
index 2e86a76..c50f17c 100644
--- a/Cell.h
+++ b/Cell.h
@@ -32,11 +32,22 @@ public:
virtual ~Cell(void);
public:
-
+ /**
+ * Changes the state of this cell
+ **/
void setState(CellState cs);
+ /**
+ * Returns the cell's state.
+ **/
CellState getState();
+ /**
+ * If a player is or was on the cell, return it
+ **/
Player* getPlayer();
+ /**
+ * Define that a player is currently on this cell.
+ **/
void setPlayer(Player* pPlayer);
private:
diff --git a/Controller.h b/Controller.h
index 1f7936b..0a8fa66 100644
--- a/Controller.h
+++ b/Controller.h
@@ -4,12 +4,17 @@
#include "Game.h"
#include "Player.h"
+/**
+ * Pure virtual class for anything that can move a player.
+ **/
class Controller
{
public:
Controller(Player* pPlayer);
virtual ~Controller(void);
-
+ /**
+ * Returns the associatedplayer
+ **/
Player* getPlayer();
/**
@@ -17,6 +22,9 @@ public:
* m_player directly in order to take decisions.
**/
virtual void think() = 0;
+ /**
+ * Reinits the controller.
+ **/
virtual void reset() = 0;
protected:
diff --git a/Field.h b/Field.h
index 174dd1a..af2e698 100644
--- a/Field.h
+++ b/Field.h
@@ -16,10 +16,27 @@ class Field
public:
Field(uint width = 0, uint height = 0);
virtual ~Field(void);
+
+public:
+ /**
+ * Inits the fields at a givens size and empties it.
+ **/
void init(uint width, uint height);
+ /**
+ * Draw all players for several cycles. Initial, final AND intermediate positions will be drawn.
+ **/
bool drawAllPlayers(uint numCycles);
+ /**
+ * Returns a specific cell given its coordinates.
+ **/
Cell& getCell(Coordinates c);
+ /**
+ * Returns the size of the field
+ **/
Coordinates getMaxCoordinates();
+ /**
+ * Redefines the value of a cell.
+ **/
void setCell(Coordinates coord, Cell cell);
private:
diff --git a/Game.cpp b/Game.cpp
index 40c98f9..8f8fcab 100644
--- a/Game.cpp
+++ b/Game.cpp
@@ -11,7 +11,12 @@ Game::Game(int width, int height): m_width(width), m_height(height)
initField(width, height);
m_vpPlayers.clear();
}
-
+void Game::setSize(int width, int height)
+{
+ m_width =width;
+ m_height =height;
+ initField(width, height);
+}
Game::~Game(void)
{
while(m_vpPlayers.size() > 0)
diff --git a/Game.h b/Game.h
index 93bc5d8..f9a5969 100644
--- a/Game.h
+++ b/Game.h
@@ -16,17 +16,49 @@ public:
virtual ~Game(void);
public:
-
+ /**
+ * Pauses the game
+ **/
void pauseGame();
+ /**
+ * Resumes the game
+ **/
void resumeGame();
+ /**
+ * Toggle between pause & resume
+ **/
void toggleGame();
+ /**
+ * Returns true if the game is not paused
+ **/
bool isRunning();
+ /**
+ * Restarts the game. It will not be paused. All dead player will live again, at original positions and original directions.
+ **/
void restart();
+ /**
+ * Starts the game the first time. The game will be paused.
+ **/
void start();
+ /**
+ * Go for 1 round if enough time passed
+ **/
void updateGame(uint timeElapsedMs);
+ /**
+ * Returns a specific player giver its ID
+ **/
Player* getPlayerByID(PlayerNumber id);
+ /**
+ * Returns the field
+ **/
Field& getField();
- void init(int width, int height, PlayerNumber num);
+ /**
+ * Changed the size of the game and the field
+ **/
+ void setSize(int width, int height);
+ /**
+ * Adds a new player with default parameters.
+ **/
Player* addPlayer();
private:
diff --git a/KeyboardController.h b/KeyboardController.h
index 127a01e..bce2b16 100644
--- a/KeyboardController.h
+++ b/KeyboardController.h
@@ -21,6 +21,9 @@ typedef enum
class MainWindow;
+/**
+ * A class that links keybard inputs and player moves
+ **/
class KeyboardController :
public Controller
{
@@ -35,8 +38,17 @@ public:
virtual ~KeyboardController(void);
public:
+ /**
+ * Is called when a key is pressed
+ **/
void PressKey(KeyCode key);
+ /**
+ * Is called when a decision is required
+ **/
void think();
+ /**
+ * Resets the controller (does nothing here)
+ **/
void reset();
private:
diff --git a/MainWindow.h b/MainWindow.h
index 6292f01..89ff76b 100644
--- a/MainWindow.h
+++ b/MainWindow.h
@@ -27,46 +27,108 @@ enum TextAlign {
};
// Functions defines for C callbacks
+/**
+ * Called when the window is resized.
+ * May not work yet on all platforms.
+ **/
void f_onChangeSize(int w, int h);
+/**
+ * Called when timer finishes.
+ **/
void f_onTimer(int v=0);
+/**
+ * Called when we want to redisplay (Idle)
+ **/
void f_onDisplay();
+/**
+ * Called when an ASCII key is pressed.
+ **/
void f_onNormalKeyPressed(unsigned char key, int x, int y);
+/**
+ * Called when a special key is pressed.
+ **/
void f_onSpecialKeyPressed(int key, int x, int y);
-
+/**
+ * Transforms an hexadecimal color into its 3 channels, as floats (0.f - 1.f)
+ **/
void hex2fColor(uint color, float &out_red, float &out_green, float &out_blue);
+/**
+ * Singleton : display window
+ **/
class MainWindow
{
private :
+
MainWindow(); // constructor is private,
MainWindow( MainWindow const & ); // copy constructor is private
MainWindow &operator=( MainWindow const & ); // Assignment operator
virtual ~MainWindow(); // ... and destructor.
+
public:
+ /**
+ * Retrieves (create if necessary) the single instance of the class.
+ **/
static MainWindow &getInstance();
public:
+ /**
+ * Initializes freeglut (glutinit)
+ **/
void init(int *argcp, char **argv);
+ /**
+ * Defines window size and name, creates it and defines proper projection matrix
+ **/
void create(std::string name, int x, int y, int width, int height);
+ /**
+ * Registers callbacks and start glut's infinite loop.
+ **/
void startLoop();
- // The field has the info of what to draw
+ /**
+ * Sets the Field we want to draw from
+ **/
void setField(Field* pField);
+ /**
+ * Returns the field we draw from.
+ **/
Field* getField();
- // The game needs to be updated whenever we want to update the display content.
+ /**
+ * Sets the game we will periodically update
+ **/
void setGame(Game* pGame);
+ /**
+ * Returns the game we will periodically update
+ **/
Game* getGame();
-
+ /**
+ * Dynamically allocate a new KeyboardController, register it and return it.
+ **/
KeyboardController* generateNewKeyboardController(Player *pPlayer, KeyCode leftKey, KeyCode rightKey);
public: // Callbacks
+ /**
+ * Is called when window size is changed
+ **/
void onChangeSize(int w, int h);
+ /**
+ * Is called when display is redrawn
+ **/
void onRenderScene();
+ /**
+ * is called every (X) ms.
+ **/
void onTimer();
+ /**
+ * Is called when a special key is pressed
+ **/
void onSpecialKeyPressed(int key);
+ /**
+ * is called when an ASCII key is pressed
+ **/
void onNormalKeyPressed(uint8 key);
private:
diff --git a/Player.h b/Player.h
index b7fd264..0719c70 100644
--- a/Player.h
+++ b/Player.h
@@ -12,8 +12,17 @@ class Controller;
class Player
{
public:
+ /**
+ * Constructor.
+ **/
Player(void);
+ /**
+ * Constructor with initial values.
+ **/
Player(PlayerNumber PlayerID, Coordinates InitialPoint, VelocityVector initialVel);
+ /**
+ * Destructor.
+ **/
virtual ~Player(void);
public:
@@ -22,28 +31,65 @@ public:
* of all the crossed cells.
**/
std::vector<Coordinates> move();
+ /**
+ * Changes the direction (and possibly speed) the player is facing.
+ **/
void setVelocity(VelocityVector v);
+ /**
+ * Apply new coordinates to the player. This is used when starting/restarting the game.
+ **/
void setCoordinates(Coordinates c);
+ /**
+ * Defines the Player ID.
+ **/
void setNumber(PlayerNumber n);
+ /**
+ * Returns the player ID.
+ **/
+ PlayerNumber getNumber();
+ /**
+ * Sets the player alive.
+ * It's alive ! ALIIIIIIIIIIIIVE !!!
+ **/
void revive();
-
+ /**
+ * (self explanatory)
+ **/
+ void kill();
/**
* Tries to change the direction the player is facing.
* Returns false and do nothing if the player is heading the opposite
* or the same way. Only possible change is 90°.
**/
bool changeDirection(VelocityVector v);
+ /**
+ *Turns toward left
+ **/
void turnLeft();
+ /**
+ * Turns toward right
+ **/
void turnRight();
-
+ /**
+ * Returns the current velocity vector.
+ **/
VelocityVector getVelocity();
+ /**
+ * Returns the current coordinates.
+ **/
Coordinates getCoordinates();
-
+ /**
+ * Returns true if the player is alive.
+ **/
bool isAlive();
- void kill();
-
- PlayerNumber getNumber();
+ /**
+ * Returns the current controller.
+ * NULL when initialized, it is assigned later.
+ **/
Controller* getController(); // may be NULL
+ /**
+ * Defines the controller.
+ **/
void setController(Controller* pController);
private:
diff --git a/TrollTron.cpp b/TrollTron.cpp
index 5c3ff2f..ca28e23 100644
--- a/TrollTron.cpp
+++ b/TrollTron.cpp
@@ -1,38 +1,172 @@
// TrollTron.cpp : définit le point d'entrée pour l'application console.
#include <iostream>
+#include <time.h>
#include "MainWindow.h"
#include "KeyboardController.h"
#include "AIController.h"
-#include <time.h>
-int main(int argc, char **argv) {
- // init GLUT and create window
- MainWindow& mainWindow = MainWindow::getInstance();
- mainWindow.init(&argc, argv);
- // This will define the size and position, in pixel, of the window, originally. It can be moved and resized.
- mainWindow.create("Troll Tron", 100, 100, 320, 320);
+int main(int argc, char **argv) {
srand((unsigned) time(NULL));
// This will define the grid
Game game(100, 100);
+ // init GLUT and create window
+ MainWindow& mainWindow = MainWindow::getInstance();
+ mainWindow.init(&argc, argv);
+
+ const KeyCode keys[] = {KEY_LEFT, KEY_RIGHT, KEY_A, KEY_E, KEY_I, KEY_P, KEY_C, KEY_B};
+ const PlayerNumber maxNumHumanPlayers = 4;
+ PlayerNumber currNumHumanPlayers = 0;
+ PlayerNumber currNumPlayers = 0;
+
+ Player *pPlayer;
- Player *pPlayer = game.addPlayer();
- pPlayer->setController(mainWindow.generateNewKeyboardController(pPlayer, KEY_LEFT, KEY_RIGHT));
+ /*
+ * Usage (regex style) : trolltron(.exe)? (player|easy|medium|hard)+ (gameWidth game height)? (windowWidht windowHeight)?
+ * 4 human players max. 1 player min (human or not)
+ * if undefined, gameWidth gameHeight = 100 100, windowWidth windowHeight = 320 320
+ */
- pPlayer = game.addPlayer();
- pPlayer->setController(new AIController(pPlayer, game.getField(), 3, 3));
+ // If this bool goes to true, then the parameters are messed up
+ //We don't start the game and display the usage
+ bool argFail = false;
+ // The higher the easier
+ int botDifficulty;
+ // Start at 1 because 0 is the path/name
+ int argNum=1;
+ // We need this to see if we have either 0, 2 or 4 numbers passed and where to store them
+ char pairOfValuesDefined = 0;
+ // Default values
+ uint gameWidth = 100;
+ uint gameHeight = 100;
+ int windowWidth = 320;
+ int windowHeight = 320;
- pPlayer = game.addPlayer();
- pPlayer->setController(new AIController(pPlayer, game.getField(), 3, 3));
+ // Go through all parameters
+ while(argNum < argc)
+ {
+ // If it's not a number
+ if (atoi(argv[argNum]) == 0)
+ {
+ // If we started to inputing numbers, we shouldn't input players anymore
+ if (pairOfValuesDefined > 0)
+ {
+ argFail = true;
+ }
+ // If it's "player"
+ if (! strcmp(argv[argNum], "player"))
+ {
+ if(currNumHumanPlayers < maxNumHumanPlayers)
+ {
+
- pPlayer = game.addPlayer();
- pPlayer->setController(new AIController(pPlayer, game.getField(), 3, 3));
+ // Add him
+ pPlayer = game.addPlayer();
+ // And create its controller
+ pPlayer->setController(mainWindow.generateNewKeyboardController(pPlayer,
+ keys[currNumHumanPlayers*2],
+ keys[currNumHumanPlayers*2+1]));
+ // Count 1 more (human) player
+ currNumPlayers ++;
+ currNumHumanPlayers ++;
+ }
+ }
+ else
+ {
+ bool isABot = false;
+ // If it's "easy"
+ if(! strcmp(argv[argNum], "easy"))
+ {
+
+ isABot = true;
+ botDifficulty = 10;
+ }
+ else if(! strcmp(argv[argNum], "medium"))
+ {
+ isABot = true;
+ botDifficulty = 3;
+ }
+ else if(! strcmp(argv[argNum], "hard"))
+ {
+ isABot = true;
+ botDifficulty = 1;
+ }
+ if(isABot)
+ {
+ // Count 1 more (non human) player
+ currNumPlayers ++;
+ pPlayer = game.addPlayer();
+ // And instanciate its AI
+ pPlayer->setController(new AIController(pPlayer, game.getField(), botDifficulty, botDifficulty));
+ }
+ }
+
+ }
+ // Else if it IS a number
+ else
+ {
+ // Numbers are only valid as pairs
+ if (atoi(argv[argNum]) > 0 && argNum < argc -1 && atoi(argv[argNum+1]) > 0)
+ {
+ // Depending on if it's...
+ switch(pairOfValuesDefined)
+
+ {
+ //The first pair : game dimensions
+ case 0:
+ pairOfValuesDefined ++;
+ gameWidth = atoi(argv[argNum]);
+ gameHeight = atoi(argv[argNum+1]);
+ // It's a pair so we take 2 args at once
+ argNum ++;
+ break;
+ //The 2nd pair : window dimensions
+ case 1:
+ pairOfValuesDefined ++;
+ windowWidth = atoi(argv[argNum]);
+ windowHeight = atoi(argv[argNum+1]);
+ argNum ++;
+ break;
+ // Another pair : user mistake
+ default:
+ argFail = true;
+ }
+ }
+ // If we input an odd number of numbers
+ else
+ {
+ argFail = true;
+ }
+ }
+ argNum++;
+
+ if(argFail)
+ {
+ // Stop looping, we lost already
+ break;
+ }
+ }
+ // If too many or too few players;
+ if(currNumHumanPlayers > maxNumHumanPlayers || currNumPlayers < 1)
+ {
+ argFail = true;
+ }
+ if(argFail)
+ {
+ std::cout << "Usage (regex style) : trolltron(.exe)? (player|easy|medium|hard)+ (gameWidth gameHeight)? (windowWidht windowHeight)?" << std::endl;
+ std::cout << "4 human players max. 1 player min (human or not)" << std::endl;
+ std::cout << "if undefined, gameWidth gameHeight = 100 100, windowWidth windowHeight = 320 320" << std::endl;
+ exit(1);
+ }
+ // This will define the size and position, in pixel, of the window, originally. It can be moved and resized.
+ mainWindow.create("Troll Tron", 100, 100, windowWidth, windowWidth);
+ game.setSize(gameWidth, gameHeight);
mainWindow.setField(&(game.getField()));
mainWindow.setGame(&game);
game.start();