This commit is contained in:
Thomas 2022-01-09 18:30:15 +01:00
parent 15dc67c348
commit a81ec496a6
No known key found for this signature in database
GPG Key ID: E538821A6CDFDAD7
16 changed files with 291 additions and 117 deletions

View File

@ -1,10 +1,5 @@
Questions que je (Thomas Rubini) voudrais poser Questions que je (Thomas Rubini) voudrais poser
- Est-ce que vous préférez l'implémentation orienté objet ou orienté macro pour lire la config ? Pourquoi ?
- Est-ce que traduire les chars A B et C (identifiants des types d'aliens) tirés de la config en valeurs d'enum est une bonne chose, pas important, ou contre-productif ?
- Est-ce que mon implémentation du réseau est bonne ?
- Est-ce mon implémentation du multithreading est bonne ?
- Est-on obligé d'utiliser size_t quand on sait que la taille du vecteur ne dépassera jamais concrètement la taille d'un int (cas précis : taille de 100 maximum, est-on obligé d'utiliser size_t de 8 bytes ?) - Est-on obligé d'utiliser size_t quand on sait que la taille du vecteur ne dépassera jamais concrètement la taille d'un int (cas précis : taille de 100 maximum, est-on obligé d'utiliser size_t de 8 bytes ?)
* Non * Non
- Que pensez-vous de la sémantique de déplacement, plutot que la référence constante ? - Que pensez-vous de la sémantique de déplacement, plutot que la référence constante ?

1
README
View File

@ -4,6 +4,7 @@ PascalCase pour les noms de classes/structures
Nommage en anglais Nommage en anglais
Pas de fonctions de +100 lignes Pas de fonctions de +100 lignes
Les guards sont de cette forme : GUARD_<filename>_H Les guards sont de cette forme : GUARD_<filename>_H
Lors d'un include, on utilise <> pour la STD, "" pour nos fichiers/MinGL
Concernant les const : Concernant les const :
Afin de limiter l'utilisation du mot const (pour garder une certaine lisibilité du code), les cas suivants n'ont pas besoin d'etre déclarés comme const : Afin de limiter l'utilisation du mot const (pour garder une certaine lisibilité du code), les cas suivants n'ont pas besoin d'etre déclarés comme const :

View File

@ -0,0 +1,50 @@
/*!
*
* @file configManagement.h
* @author RUBINI Thomas
* @author SIMAILA Djalim
* @date January 2022
* @version 1.0
* @brief config parser
*
*/
#ifndef SPACE_CONFIGMANAGEMENT_H
#define SPACE_CONFIGMANAGEMENT_H
/*
* This header will only be imported once, but Djalim told me he would hurt me
* if I didn't move it into his own header file instead of the cpp file
*/
class ConfigBuilder{
public:
ConfigData collectedData;
void parseFile(const string& fname);
void readConfig();
void dumpInternalValues() const;
private:
map<string, string> internalValues;
const string& getString(const configKey& key, const string& def) const;
const string& getString(const configKey& key) const;
char getChar(const configKey& key, char def) const;
char getChar(const configKey& key) const;
int getInt(const configKey& key) const;
int getInt(const configKey& key, int def) const;
void getColor(const configKey& key, nsGraphics::RGBAcolor& color, nsGraphics::RGBAcolor& def) const;
void getColor(const configKey& key, nsGraphics::RGBAcolor& color) const;
void getList(const configKey& key, vector<string>& vec) const;
void readGrid(const configKey& baseKey);
void readPlayer(const configKey& baseKey, PlayerDef&);
void readInvaderType(const configKey& baseKey, InvaderTypeDef&);
};
void ConfigBuilder::dumpInternalValues() const {
for(const auto& ite : internalValues){
cerr << ite.first << " -> " << ite.second << endl;
}
}
#endif

25
headers/errors.h Normal file
View File

@ -0,0 +1,25 @@
/*!
*
* @file configData.h
* @author RUBINI Thomas
* @date January 2022
* @version 1.0
* @brief Configuration file data storage
*
*/
#ifndef GUARD_ERRORS_H
#define GUARD_ERRORS_H
#include<string>
#include<stdexcept>
using namespace std;
// We keep the same case
class config_error : public runtime_error {
public:
explicit config_error(const string& msg);
};
#endif

View File

@ -202,37 +202,37 @@ private:
void moveTorpedos(); void moveTorpedos();
/*! /*!
* @brief * @brief checks if a missile collides with a player
* @return * @fn checkMissilesAndPlayers();
* @fn
*/ */
bool checkMissilesAndPlayers(); void checkMissilesAndPlayers();
/*! /*!
* @brief * @brief check if a torpedo collides with an invader
* @return * @return true if there is a collision, false elsewise
* @fn * @fn bool checkTorpedosAndInvaders();
*/ */
bool checkTorpedosAndInvaders(); bool checkTorpedosAndInvaders();
/*! /*!
* @brief * @brief check if the invaders have reach the players
* @return * @return true if they have reach the player, false elsewise
* @fn * @fn bool invadersTouchPlayer() const;
*/ */
bool invadersTouchPlayer() const; bool invadersTouchPlayer() const;
// god things // god things
/*! /*!
* * @brief change god's state to awake
* @fn void awakeGod();
*/ */
void awakeGod(); void awakeGod();
/*! /*!
* @brief * @brief make god behave
* @return * @return true if theres no invader left, false elsewise
* @fn * @fn bool manageGod();
*/ */
bool manageGod(); bool manageGod();
@ -240,28 +240,37 @@ public:
// in case someone wants to mess with the code, here's a minimal API, costs nothing to us // in case someone wants to mess with the code, here's a minimal API, costs nothing to us
/*! /*!
* * @brief constructor for the game class
* @fn Game();
*/ */
Game(); Game();
/*! /*!
* * @brief manages and changes the states of the game
* @fn void managedGames();
*/ */
void managedGames(); void managedGames();
/*! /*!
* @brief * @brief enter the main gameplay game loop
* @return * @return the value of the winners can be the players, the invaders or god
* @fn * @fn WinValue enterGameLoop();
*/ */
WinValue enterGameLoop(); WinValue enterGameLoop();
/*! /*!
* @brief * @brief reload the configuration file for a new game
* @return * @return false if an error occured, true elsewise
* @fn * @fn bool reloadConfig();
*/ */
bool reloadConfig(); bool reloadConfig();
/*!
* @brief tells if all players are dead
* @return true if all player are dead, false otherwise
* @fn bool arePlayersDead();
*/
bool arePlayersDead();
}; };
#endif #endif

View File

@ -6,6 +6,9 @@
* @version 1.0 * @version 1.0
* @brief Special entity known as "God" * @brief Special entity known as "God"
* *
* Well, i (Djalim) discovered that Thomas put God in the game
* I didnt think it was a good idea but no man can stop Thomas
*
*/ */
#ifndef GUARD_GOD_H #ifndef GUARD_GOD_H
@ -15,7 +18,7 @@
#include "invadersGrid.h" #include "invadersGrid.h"
/*! /*!
* @brief * @brief list of all known god states
*/ */
enum class GodState{ enum class GodState{
NONE, NONE,
@ -40,18 +43,18 @@ enum class GodState{
/*! /*!
* @class God * @class God
* @brief * @brief stores all God's data
*/ */
class God{ class God{
public: public:
/*! /*!
* @brief * @brief god's current state
*/ */
GodState state; GodState state;
/*! /*!
* @brief * @brief manage all sorts of things, gods secrets remains unknown
*/ */
unsigned counter; unsigned counter;
@ -59,34 +62,34 @@ public:
// we do not use a Position because it is used for pixel X and Y // we do not use a Position because it is used for pixel X and Y
/*! /*!
* @brief * @brief x pixel coordinate of the invader thrown by the hand of god
*/ */
unsigned thrownInvPosX; unsigned thrownInvPosX;
/*! /*!
* @brief * @brief y pixel coordinate of the invader thrown by the hand of god
*/ */
unsigned thrownInvPosY; unsigned thrownInvPosY;
/*! /*!
* @brief * @brief type of the invader thrown by the hand of god
*/ */
InvaderType thrownInvType; InvaderType thrownInvType;
/*! /*!
* @brief * @brief direction of the thrown invader movement
*/ */
Position thrownVector; Position thrownVector;
/*! /*!
* @brief * @brief position of a point for bezier's curve
*/ */
Position thrownTransition; Position thrownTransition;
/*! /*!
* @brief * @brief give initial the pixel coordinates of god's right hand
* @param[in] screenWidth : * @param[in] screenWidth : width of the screen in pixel
* @return * @return pixel coordinates of the hand
* @fn Position getRightHandPos(unsigned screenWidth) const; * @fn Position getRightHandPos(unsigned screenWidth) const;
*/ */
Position getRightHandPos(unsigned screenWidth) const; Position getRightHandPos(unsigned screenWidth) const;

View File

@ -53,7 +53,7 @@ public:
* @return * @return
* @fn * @fn
*/ */
unsigned randomValid() const; unsigned randomValidInv() const;
}; // class InvadersColumn }; // class InvadersColumn

View File

@ -18,17 +18,62 @@
using namespace std; using namespace std;
/*!
* @struct ScoreLink
* @brief Makes a link between a player username and their score
*/
struct ScoreLink{ struct ScoreLink{
/*!
* @brief player username
*/
string name; string name;
/*!
* @brief player score
*/
unsigned score; unsigned score;
/*!
* @brief constructor of the struct
* @param[in] name : player username
* @param[in] score : player score
* @fn ScoreLink(string name, unsigned score);
*/
ScoreLink(string name, unsigned score); ScoreLink(string name, unsigned score);
}; };
/*!
* @class ScoresManager
* @brief manage the score in the game and inside the score file
*/
class ScoresManager { class ScoresManager {
public: public:
/*!
* @brief list of pairs of player names and their score
*/
vector<ScoreLink> scores; vector<ScoreLink> scores;
/*!
* @brief add player name and their score in the list of scores
* @param[in] name : player name
* @param[in] score : player score
* @fn void inputScore(string name, unsigned score);
*/
void inputScore(string name, unsigned score); void inputScore(string name, unsigned score);
/*!
* @brief read the score file and put all of its data inside the list of score
* @fn void readFile();
*/
void readFile(); void readFile();
/*!
* @brief write the score list into the score file
* @fn void writeFile() const;
*/
void writeFile() const; void writeFile() const;
}; };

View File

@ -1,3 +1,13 @@
/*!
*
* @file utils.h
* @author RUBINI Thomas
* @date January 2022
* @version 1.0
* @brief utilies for the game
*
*/
#ifndef GUARD_UTILS_H #ifndef GUARD_UTILS_H
#define GUARD_UTILS_H #define GUARD_UTILS_H
@ -28,11 +38,14 @@
using namespace std; using namespace std;
using nsGraphics::RGBAcolor; using nsGraphics::RGBAcolor;
/*!
* @brief list of win values
*/
enum class WinValue{ enum class WinValue{
NOBODY, // should never be used NOBODY, // should never be used
PLAYERS, PLAYERS,
INVADERS, INVADERS,
GOD,
}; };
@ -42,9 +55,25 @@ typedef unsigned playerID;
#define PLAYER2 1 #define PLAYER2 1
// didn't want to use Position because of the semantic with x and y // didn't want to use Position because of the semantic with x and y
/*!
* @brief tells if 2 lines are colliding in a 1 dimentionnal space
* @param[in] start1 : position of the first point of the first line
* @param[in] end1: posision of the last point of the first line
* @param[in] start2 : position of the first point of the seconde line
* @param[in] end2: posision of the last point of the second line
* @return true if they are
olliding, false elsewise */
bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned end2); bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned end2);
// change draw position for a specified size (keeps the same center) // change draw position for a specified size (keeps the same center)
/*!
* @brief change the size of a Position object
* @param[in,out] pos : Position object
* @param[in] sizeFrom: current size of the objet
* @param[in] sizeTo : new size of the object
*/
void applyTransformation(Position& pos, unsigned sizeFrom, unsigned sizeTo); void applyTransformation(Position& pos, unsigned sizeFrom, unsigned sizeTo);
#endif #endif

View File

@ -11,33 +11,9 @@
#include <fstream> #include <fstream>
#include "game.h" #include "game.h"
#include "configManagement.h"
#include "errors.h"
// you will MOVE THIS OUT OF THIS FILE
class ConfigBuilder{
public:
ConfigData collectedData;
void parseFile(const string& fname);
void readConfig();
void dumpInternalValues() const;
private:
map<string, string> internalValues;
const string& getString(const configKey& key) const;
char getChar(const configKey& key) const;
int getInt(const configKey& key) const;
void getColor(const configKey& key, nsGraphics::RGBAcolor&) const;
void getList(const configKey& key, vector<string>&) const;
void readGrid(const configKey& baseKey);
void readPlayer(const configKey& baseKey, PlayerDef&);
void readInvaderType(const configKey& baseKey, InvaderTypeDef&);
};
void ConfigBuilder::dumpInternalValues() const {
for(const auto& ite : internalValues){
cerr << ite.first << " -> " << ite.second << endl;
}
}
void trimSpaces(string& str){ void trimSpaces(string& str){
str.erase(0, str.find_first_not_of(' ')); str.erase(0, str.find_first_not_of(' '));
@ -56,12 +32,12 @@ void sanitizeValue(string& val) {
/* /*
* WARNING : This implementation of YAML is not meant to be complete, but to work with our specific needs * WARNING : This implementation of YAML is not meant to be complete, but to work with our specific needs
* It also can't detect and report errors in a non YAML-compliant file * It also can't detect and report errors in a non-YAML-compliant file
*/ */
void ConfigBuilder::parseFile(const string& fname) { void ConfigBuilder::parseFile(const string& fname) {
ifstream file(fname); ifstream file(fname);
if(!file.is_open())throw runtime_error("Error while opening config.yml. Check file location ?"); if(!file.is_open())throw config_error("Error while opening config.yml. Check file location ?");
vector<string> keyParts; vector<string> keyParts;
unsigned listIndex; unsigned listIndex;
@ -91,7 +67,7 @@ void ConfigBuilder::parseFile(const string& fname) {
}else{ }else{
match = line.find(':'); match = line.find(':');
if (match == string::npos)throw runtime_error("Invalid line : " + line); if (match == string::npos)throw config_error("Invalid line : " + line);
string key = line.substr(0, match); string key = line.substr(0, match);
string value = line.substr(match + 1); string value = line.substr(match + 1);
trimSpaces(key); trimSpaces(key);
@ -148,7 +124,7 @@ void ConfigBuilder::readGrid(const configKey& baseKey) {
break; break;
} }
default:{ default:{
throw runtime_error("Invalid invader ID in grid definition : "+ to_string(s[i])); throw config_error("Invalid invader ID in grid definition : "+ to_string(s[i]));
} }
} }
} }
@ -212,26 +188,60 @@ void ConfigBuilder::readConfig() {
getColor("projectiles.torpedos.color", collectedData.torpedosColor); getColor("projectiles.torpedos.color", collectedData.torpedosColor);
} }
int ConfigBuilder::getInt(const configKey& key) const { const string& ConfigBuilder::getString(const configKey& key, const string& def) const {
return stoi(getString(key)); try{
return getString(key);
}catch(config_error& e){
cerr << e.what() << endl;
return def;
} }
char ConfigBuilder::getChar(const configKey& key) const {
return getString(key)[0];
} }
const string& ConfigBuilder::getString(const configKey& key) const { const string& ConfigBuilder::getString(const configKey& key) const {
if(internalValues.contains(key)){ if(internalValues.contains(key)){
return internalValues.at(key); return internalValues.at(key);
}else{ }else{
throw runtime_error("Non-existent key requested : "+key); throw config_error("Non-existent key requested : "+key);
}
}
int ConfigBuilder::getInt(const configKey& key) const {
try{
return stoi(getString(key));
}catch(invalid_argument& e){
cerr << e.what() << endl;
throw config_error("Invalid int data for key "+key+" : |"+getString(key)+"|");
}
}
int ConfigBuilder::getInt(const configKey& key, int def) const {
try{
return getInt(key);
}catch(config_error& e){
cerr << e.what() << endl;
return def;
}
}
char ConfigBuilder::getChar(const configKey& key) const {
string s = getString(key);
if(s.size()!=1)throw config_error("Invalid char data for key "+key+" : |"+s+"|");
return s[0];
}
char ConfigBuilder::getChar(const configKey& key, char def) const {
try{
return getChar(key);
}catch(config_error& e){
cerr << e.what() << endl;
return def;
} }
} }
void ConfigBuilder::getList(const configKey& key, vector<string>& toPopulate) const { void ConfigBuilder::getList(const configKey& key, vector<string>& toPopulate) const {
size_t i=0; size_t i=0;
string fullKey = key+".0"; string fullKey = key+".0";
if(!internalValues.contains(fullKey))throw runtime_error("Non-existent list key requested : "+key); if(!internalValues.contains(fullKey))throw config_error("Non-existent list key requested : "+key);
do{ do{
toPopulate.push_back(internalValues.at(fullKey)); toPopulate.push_back(internalValues.at(fullKey));
@ -259,14 +269,10 @@ void ConfigBuilder::getColor(const configKey& key, nsGraphics::RGBAcolor& color)
else if (colorStr == "purple")color = nsGraphics::KPurple; else if (colorStr == "purple")color = nsGraphics::KPurple;
else if (colorStr == "teal")color = nsGraphics::KTeal; else if (colorStr == "teal")color = nsGraphics::KTeal;
else if (colorStr == "navy")color = nsGraphics::KNavy; else if (colorStr == "navy")color = nsGraphics::KNavy;
else throw runtime_error("Invalid color string : "+colorStr); else throw config_error("Invalid color string : "+colorStr);
} }
/**
*
* @return false if there was an error
*/
bool Game::reloadConfig() { bool Game::reloadConfig() {
map<string, string> strValues; map<string, string> strValues;
ConfigBuilder builder; ConfigBuilder builder;
@ -275,7 +281,7 @@ bool Game::reloadConfig() {
builder.parseFile("config.yml"); builder.parseFile("config.yml");
parsed = true; parsed = true;
builder.readConfig(); builder.readConfig();
}catch(runtime_error& e){ }catch(config_error& e){
if(parsed)cerr << "An error occured while reading the configuration :" << endl; if(parsed)cerr << "An error occured while reading the configuration :" << endl;
else cerr << "An error occured while parsing the configuration :" << endl; else cerr << "An error occured while parsing the configuration :" << endl;
cerr << e.what() << endl; cerr << e.what() << endl;

5
src/errors.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "errors.h"
config_error::config_error(const string& msg) : runtime_error(msg) {
}

View File

@ -60,7 +60,6 @@ void Game::managedGames() {
// we assume the game has been played before, and so we need to clean used members // we assume the game has been played before, and so we need to clean used members
void Game::initGame(){ void Game::initGame(){
grid = confData.grid; // will copy the grid grid = confData.grid; // will copy the grid
updateColumns(); // Would have liked to to that in the "config grid", but.. I'm lazy
// we re-construct players objects, we don't have to clear all members and can rely on the construction value (set in .h file) // we re-construct players objects, we don't have to clear all members and can rely on the construction value (set in .h file)
players.clear(); players.clear();
@ -114,16 +113,19 @@ WinValue Game::enterGameLoop(){ // returns when game is finished
} }
} }
manageGod(); if(manageGod())return WinValue::PLAYERS;
if(arePlayersDead())return WinValue::GOD;
moveMissiles(); moveMissiles();
remCollidingProjectiles(); remCollidingProjectiles();
moveTorpedos(); moveTorpedos();
remCollidingProjectiles(); remCollidingProjectiles();
if(checkMissilesAndPlayers())return WinValue::INVADERS; checkMissilesAndPlayers();
if(checkTorpedosAndInvaders())return WinValue::PLAYERS; if(checkTorpedosAndInvaders())return WinValue::PLAYERS;
if(arePlayersDead())return WinValue::INVADERS;
displayAll(fps); displayAll(fps);
pm.endFrame(); pm.endFrame();
@ -146,3 +148,10 @@ WinValue Game::enterGameLoop(){ // returns when game is finished
Position Game::invIndexToPos(unsigned x, unsigned y) const { Position Game::invIndexToPos(unsigned x, unsigned y) const {
return basePos+Position(INV_GET_POS(x), INV_GET_POS(y)); return basePos+Position(INV_GET_POS(x), INV_GET_POS(y));
} }
bool Game::arePlayersDead() {
for(Player& p : players){
if(!p.isEliminated())return false;
}
return true;
}

View File

@ -48,10 +48,6 @@ void Game::managePlayers(){
for(unsigned i=0;i<players.size();++i)manageOnePlayer(i); for(unsigned i=0;i<players.size();++i)manageOnePlayer(i);
} }
/** Makes the invaders play once, and check lower bounds
*
* @return true if the invaders went down from one line (and we should check lower boundary), else false
*/
bool Game::manageInvaders(){ bool Game::manageInvaders(){
if(grid.empty())return false; // If there are no more invaders we don't need to manage them if(grid.empty())return false; // If there are no more invaders we don't need to manage them
// shoot // shoot
@ -94,10 +90,6 @@ bool Game::manageInvaders(){
} }
/** makes projectiles move, and manage collisions between them and everything
*
* @return 1 if the invaders are all dead, 2 if the player is dead, else 0
*/
void Game::remCollidingProjectiles(){ void Game::remCollidingProjectiles(){
auto miss = missiles.begin(); auto miss = missiles.begin();
@ -150,7 +142,7 @@ void Game::moveTorpedos() {
} }
} }
bool Game::checkMissilesAndPlayers() { void Game::checkMissilesAndPlayers() {
auto miss_ite = missiles.begin(); auto miss_ite = missiles.begin();
while(miss_ite!=missiles.end()){ while(miss_ite!=missiles.end()){
bool wasColliding = false; bool wasColliding = false;
@ -171,7 +163,6 @@ bool Game::checkMissilesAndPlayers() {
if(wasColliding)missiles.erase(miss_ite); if(wasColliding)missiles.erase(miss_ite);
else ++miss_ite; else ++miss_ite;
} }
return false; // TODO manage death animation
} }
bool Game::checkTorpedosAndInvaders() { bool Game::checkTorpedosAndInvaders() {
@ -202,7 +193,7 @@ bool Game::checkTorpedosAndInvaders() {
grid[i][alienIndex] = InvaderType::NONE; grid[i][alienIndex] = InvaderType::NONE;
if(updateColumns()) return true; if(!areThereInvadersLeft()) return true;
break; break;
} }
} }

View File

@ -18,6 +18,11 @@ void Game::awakeGod() {
/** /**
* @returns true if we can finish the game * @returns true if we can finish the game
*/ */
/*
* This is a really long function, but I feel like it's still readable because of the switch, and..
* Honestly I think splitting it into multiple small functions would be ugly
*/
bool Game::manageGod() { bool Game::manageGod() {
switch (god.state) { switch (god.state) {
case GodState::NONE: { case GodState::NONE: {
@ -35,19 +40,18 @@ bool Game::manageGod() {
++god.counter; ++god.counter;
return false; return false;
} }
if (areThereInvadersLeft()) {
// init throw // init throw
god.counter = 0; god.counter = 0;
god.state = GodState::RETRIEVE1; god.state = GodState::RETRIEVE1;
god.thrownInvPosX = grid.randomValidCol(); god.thrownInvPosX = grid.randomValidCol();
god.thrownInvPosY = grid[god.thrownInvPosX].randomValid(); god.thrownInvPosY = grid[god.thrownInvPosX].randomValidInv();
god.thrownInvType = InvaderType::NONE; god.thrownInvType = InvaderType::NONE;
god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE); god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE);
god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY)); god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY));
return false; return false;
} }
}
case GodState::RETRIEVE1: { case GodState::RETRIEVE1: {
if (god.counter < 100) { if (god.counter < 100) {
god.counter += 2; god.counter += 2;
@ -132,14 +136,19 @@ bool Game::manageGod() {
* we do not need to reset other members, they'll be treated as non-initialized * we do not need to reset other members, they'll be treated as non-initialized
* When we cycle back between states * When we cycle back between states
*/ */
return false;
// We could have optimized that, but it's more readable like this and hopefully the compiler will optimize it itself
if(areThereInvadersLeft())return false;
else return true;
} }
case GodState::YOLO: { case GodState::YOLO: {
} }
} }
throw runtime_error("SHOULD NOT HAPPEN : invalid action for god : ID="+ to_string(static_cast<int>(god.state)));
} }
Position God::getRightHandPos(unsigned screenWidth) const { Position God::getRightHandPos(unsigned screenWidth) const {
return Position(screenWidth - GOD_HAND_DISTANCE - GOD_HAND_SIZE, 0); return {screenWidth - GOD_HAND_DISTANCE - GOD_HAND_SIZE, 0};
} }

View File

@ -27,7 +27,7 @@ unsigned InvadersColumn::getOutterInvader() const {
// these are used to invoke rand() as less as possible // these are used to invoke rand() as less as possible
unsigned InvadersColumn::randomValid() const { unsigned InvadersColumn::randomValidInv() const {
unsigned validTotal = 0; unsigned validTotal = 0;

View File

@ -1,6 +1,3 @@
#include <utils.h>
#include "utils.h" #include "utils.h"
bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned end2){ bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned end2){