push
This commit is contained in:
		
							parent
							
								
									15dc67c348
								
							
						
					
					
						commit
						a81ec496a6
					
				@ -1,10 +1,5 @@
 | 
			
		||||
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 ?)
 | 
			
		||||
* Non
 | 
			
		||||
- Que pensez-vous de la sémantique de déplacement, plutot que la référence constante ?
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								README
									
									
									
									
									
								
							@ -4,6 +4,7 @@ PascalCase pour les noms de classes/structures
 | 
			
		||||
Nommage en anglais
 | 
			
		||||
Pas de fonctions de +100 lignes
 | 
			
		||||
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 :
 | 
			
		||||
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 :
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								headers/configManagement.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								headers/configManagement.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										25
									
								
								headers/errors.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@ -202,37 +202,37 @@ private:
 | 
			
		||||
	void moveTorpedos();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @return
 | 
			
		||||
	* @fn 
 | 
			
		||||
 	* @brief checks if a missile collides with a player 
 | 
			
		||||
	* @fn checkMissilesAndPlayers(); 
 | 
			
		||||
 	*/
 | 
			
		||||
	bool checkMissilesAndPlayers();
 | 
			
		||||
	void checkMissilesAndPlayers();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @return
 | 
			
		||||
	* @fn 
 | 
			
		||||
 	* @brief check if a torpedo collides with an invader
 | 
			
		||||
	* @return true if there is a collision, false elsewise
 | 
			
		||||
	* @fn bool checkTorpedosAndInvaders(); 
 | 
			
		||||
 	*/
 | 
			
		||||
	bool checkTorpedosAndInvaders();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @return
 | 
			
		||||
	* @fn 
 | 
			
		||||
 	* @brief check if the invaders have reach the players
 | 
			
		||||
	* @return true if they have reach the player, false elsewise
 | 
			
		||||
	* @fn bool invadersTouchPlayer() const;
 | 
			
		||||
 	*/
 | 
			
		||||
	bool invadersTouchPlayer() const;
 | 
			
		||||
 | 
			
		||||
	// god things
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
 	* 
 | 
			
		||||
 	* @brief change god's state to awake
 | 
			
		||||
	* @fn void awakeGod(); 
 | 
			
		||||
 	*/
 | 
			
		||||
	void awakeGod();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @return
 | 
			
		||||
	* @fn 
 | 
			
		||||
 	* @brief make god behave
 | 
			
		||||
	* @return true if theres no invader left, false elsewise
 | 
			
		||||
	* @fn 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
 | 
			
		||||
    
 | 
			
		||||
	/*!
 | 
			
		||||
 	* 
 | 
			
		||||
 	* @brief constructor for the game class
 | 
			
		||||
	* @fn Game(); 
 | 
			
		||||
 	*/
 | 
			
		||||
	Game();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* 
 | 
			
		||||
 	* @brief manages and changes the states of the game
 | 
			
		||||
	* @fn void managedGames(); 
 | 
			
		||||
 	*/
 | 
			
		||||
	void managedGames();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @return
 | 
			
		||||
	* @fn 
 | 
			
		||||
 	* @brief enter the main gameplay game loop
 | 
			
		||||
	* @return the value of the winners can be the players, the invaders or god 
 | 
			
		||||
	* @fn WinValue enterGameLoop(); 
 | 
			
		||||
 	*/
 | 
			
		||||
	WinValue enterGameLoop();
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @return
 | 
			
		||||
	* @fn 
 | 
			
		||||
 	* @brief reload the configuration file for a new game
 | 
			
		||||
	* @return false if an error occured, true elsewise
 | 
			
		||||
	* @fn 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
 | 
			
		||||
@ -6,6 +6,9 @@
 | 
			
		||||
 * @version 1.0
 | 
			
		||||
 * @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
 | 
			
		||||
@ -15,7 +18,7 @@
 | 
			
		||||
#include "invadersGrid.h"
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * @brief
 | 
			
		||||
 * @brief list of all known god states
 | 
			
		||||
 */
 | 
			
		||||
enum class GodState{
 | 
			
		||||
	NONE,
 | 
			
		||||
@ -40,18 +43,18 @@ enum class GodState{
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * @class God
 | 
			
		||||
 * @brief 
 | 
			
		||||
 * @brief stores all God's data
 | 
			
		||||
 */
 | 
			
		||||
class God{
 | 
			
		||||
public:
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
 	* @brief god's current state
 | 
			
		||||
 	*/
 | 
			
		||||
	GodState state;
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
 	* @brief manage all sorts of things, gods secrets remains unknown
 | 
			
		||||
 	*/
 | 
			
		||||
	unsigned counter;
 | 
			
		||||
 | 
			
		||||
@ -59,34 +62,34 @@ public:
 | 
			
		||||
	// 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;
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
 	* @brief y pixel coordinate of the invader thrown by the hand of god
 | 
			
		||||
 	*/
 | 
			
		||||
	unsigned thrownInvPosY;
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
 	* @brief type of the invader thrown by the hand of god
 | 
			
		||||
 	*/
 | 
			
		||||
	InvaderType thrownInvType;
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
 	* @brief direction of the thrown invader movement
 | 
			
		||||
 	*/
 | 
			
		||||
	Position thrownVector;
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
 	* @brief position of a point for bezier's curve
 | 
			
		||||
 	*/
 | 
			
		||||
	Position thrownTransition;
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
 	* @brief
 | 
			
		||||
	* @param[in] screenWidth : 
 | 
			
		||||
	* @return
 | 
			
		||||
 	* @brief give initial the pixel coordinates of god's right hand
 | 
			
		||||
	* @param[in] screenWidth : width of the screen in pixel
 | 
			
		||||
	* @return pixel coordinates of the hand
 | 
			
		||||
	* @fn Position getRightHandPos(unsigned screenWidth) const; 
 | 
			
		||||
 	*/
 | 
			
		||||
	Position getRightHandPos(unsigned screenWidth) const;
 | 
			
		||||
 | 
			
		||||
@ -53,7 +53,7 @@ public:
 | 
			
		||||
	 * @return
 | 
			
		||||
	 * @fn 
 | 
			
		||||
	 */
 | 
			
		||||
	unsigned randomValid() const;
 | 
			
		||||
	unsigned randomValidInv() const;
 | 
			
		||||
}; // class InvadersColumn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -18,17 +18,62 @@
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * @struct ScoreLink
 | 
			
		||||
 * @brief Makes a link between a player username and their score
 | 
			
		||||
 */
 | 
			
		||||
struct ScoreLink{
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
	* @brief player username
 | 
			
		||||
	*/
 | 
			
		||||
	string name;
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
	* @brief player 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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * @class ScoresManager
 | 
			
		||||
 * @brief manage the score in the game and inside the score file 
 | 
			
		||||
 */
 | 
			
		||||
class ScoresManager {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
	* @brief list of pairs of player names and their score
 | 
			
		||||
	*/
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
	* @brief read the score file and put all of its data inside the list of score
 | 
			
		||||
	* @fn void readFile(); 
 | 
			
		||||
	*/
 | 
			
		||||
	void readFile();
 | 
			
		||||
	
 | 
			
		||||
	/*!
 | 
			
		||||
	* @brief write the score list into the score file
 | 
			
		||||
	* @fn void writeFile() const; 
 | 
			
		||||
	*/
 | 
			
		||||
	void writeFile() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
#define GUARD_UTILS_H
 | 
			
		||||
 | 
			
		||||
@ -28,11 +38,14 @@
 | 
			
		||||
using namespace std;
 | 
			
		||||
using nsGraphics::RGBAcolor;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * @brief list of win values
 | 
			
		||||
 */
 | 
			
		||||
enum class WinValue{
 | 
			
		||||
	NOBODY, // should never be used
 | 
			
		||||
	PLAYERS,
 | 
			
		||||
	INVADERS,
 | 
			
		||||
	GOD,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,9 +55,25 @@ typedef unsigned playerID;
 | 
			
		||||
#define PLAYER2 1
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -11,33 +11,9 @@
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#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){
 | 
			
		||||
	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
 | 
			
		||||
 * 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) {
 | 
			
		||||
	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;
 | 
			
		||||
	unsigned listIndex;
 | 
			
		||||
@ -91,7 +67,7 @@ void ConfigBuilder::parseFile(const string& fname) {
 | 
			
		||||
 | 
			
		||||
		}else{
 | 
			
		||||
			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 value = line.substr(match + 1);
 | 
			
		||||
			trimSpaces(key);
 | 
			
		||||
@ -148,7 +124,7 @@ void ConfigBuilder::readGrid(const configKey& baseKey) {
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ConfigBuilder::getInt(const configKey& key) const {
 | 
			
		||||
	return stoi(getString(key));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char ConfigBuilder::getChar(const configKey& key) const {
 | 
			
		||||
	return getString(key)[0];
 | 
			
		||||
const string& ConfigBuilder::getString(const configKey& key, const string& def) const {
 | 
			
		||||
	try{
 | 
			
		||||
		return getString(key);
 | 
			
		||||
	}catch(config_error& e){
 | 
			
		||||
		cerr << e.what() << endl;
 | 
			
		||||
		return def;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const string& ConfigBuilder::getString(const configKey& key) const {
 | 
			
		||||
	if(internalValues.contains(key)){
 | 
			
		||||
		return internalValues.at(key);
 | 
			
		||||
	}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 {
 | 
			
		||||
	size_t i=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{
 | 
			
		||||
		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 == "teal")color = nsGraphics::KTeal;
 | 
			
		||||
	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() {
 | 
			
		||||
	map<string, string> strValues;
 | 
			
		||||
	ConfigBuilder builder;
 | 
			
		||||
@ -275,7 +281,7 @@ bool Game::reloadConfig() {
 | 
			
		||||
		builder.parseFile("config.yml");
 | 
			
		||||
		parsed = true;
 | 
			
		||||
		builder.readConfig();
 | 
			
		||||
	}catch(runtime_error& e){
 | 
			
		||||
	}catch(config_error& e){
 | 
			
		||||
		if(parsed)cerr << "An error occured while reading the configuration :" << endl;
 | 
			
		||||
		else cerr << "An error occured while parsing the configuration :" << endl;
 | 
			
		||||
		cerr << e.what() << endl;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								src/errors.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/errors.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
 | 
			
		||||
config_error::config_error(const string& msg) : runtime_error(msg) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -60,7 +60,6 @@ void Game::managedGames() {
 | 
			
		||||
// we assume the game has been played before, and so we need to clean used members
 | 
			
		||||
void Game::initGame(){
 | 
			
		||||
	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)
 | 
			
		||||
	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();
 | 
			
		||||
		remCollidingProjectiles();
 | 
			
		||||
		moveTorpedos();
 | 
			
		||||
		remCollidingProjectiles();
 | 
			
		||||
 | 
			
		||||
		if(checkMissilesAndPlayers())return WinValue::INVADERS;
 | 
			
		||||
		checkMissilesAndPlayers();
 | 
			
		||||
		if(checkTorpedosAndInvaders())return WinValue::PLAYERS;
 | 
			
		||||
 | 
			
		||||
		if(arePlayersDead())return WinValue::INVADERS;
 | 
			
		||||
 | 
			
		||||
		displayAll(fps);
 | 
			
		||||
 | 
			
		||||
		pm.endFrame();
 | 
			
		||||
@ -146,3 +148,10 @@ WinValue Game::enterGameLoop(){ // returns when game is finished
 | 
			
		||||
Position Game::invIndexToPos(unsigned x, unsigned y) const {
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -48,10 +48,6 @@ void Game::managePlayers(){
 | 
			
		||||
	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(){
 | 
			
		||||
	if(grid.empty())return false; // If there are no more invaders we don't need to manage them
 | 
			
		||||
	// 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(){
 | 
			
		||||
 | 
			
		||||
	auto miss = missiles.begin();
 | 
			
		||||
@ -150,7 +142,7 @@ void Game::moveTorpedos() {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Game::checkMissilesAndPlayers() {
 | 
			
		||||
void Game::checkMissilesAndPlayers() {
 | 
			
		||||
	auto miss_ite = missiles.begin();
 | 
			
		||||
	while(miss_ite!=missiles.end()){
 | 
			
		||||
		bool wasColliding = false;
 | 
			
		||||
@ -171,7 +163,6 @@ bool Game::checkMissilesAndPlayers() {
 | 
			
		||||
		if(wasColliding)missiles.erase(miss_ite);
 | 
			
		||||
		else ++miss_ite;
 | 
			
		||||
	}
 | 
			
		||||
	return false; // TODO manage death animation
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Game::checkTorpedosAndInvaders() {
 | 
			
		||||
@ -202,7 +193,7 @@ bool Game::checkTorpedosAndInvaders() {
 | 
			
		||||
 | 
			
		||||
					grid[i][alienIndex] = InvaderType::NONE;
 | 
			
		||||
 | 
			
		||||
					if(updateColumns()) return true;
 | 
			
		||||
					if(!areThereInvadersLeft()) return true;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,11 @@ void Game::awakeGod() {
 | 
			
		||||
/**
 | 
			
		||||
 * @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() {
 | 
			
		||||
	switch (god.state) {
 | 
			
		||||
		case GodState::NONE: {
 | 
			
		||||
@ -35,19 +40,18 @@ bool Game::manageGod() {
 | 
			
		||||
				++god.counter;
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			if (areThereInvadersLeft()) {
 | 
			
		||||
 | 
			
		||||
			// init throw
 | 
			
		||||
			god.counter = 0;
 | 
			
		||||
			god.state = GodState::RETRIEVE1;
 | 
			
		||||
			god.thrownInvPosX = grid.randomValidCol();
 | 
			
		||||
				god.thrownInvPosY = grid[god.thrownInvPosX].randomValid();
 | 
			
		||||
			god.thrownInvPosY = grid[god.thrownInvPosX].randomValidInv();
 | 
			
		||||
			god.thrownInvType = InvaderType::NONE;
 | 
			
		||||
 | 
			
		||||
			god.thrownTransition.setX(pm.getScreenWidth() - GOD_HAND_DISTANCE - GOD_HAND_SIZE);
 | 
			
		||||
			god.thrownTransition.setY(basePos.getY() + INV_GET_POS(god.thrownInvPosY));
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		}
 | 
			
		||||
		case GodState::RETRIEVE1: {
 | 
			
		||||
			if (god.counter < 100) {
 | 
			
		||||
				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
 | 
			
		||||
			 * 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: {
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	throw runtime_error("SHOULD NOT HAPPEN : invalid action for god : ID="+ to_string(static_cast<int>(god.state)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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};
 | 
			
		||||
}
 | 
			
		||||
@ -27,7 +27,7 @@ unsigned InvadersColumn::getOutterInvader() const {
 | 
			
		||||
 | 
			
		||||
// these are used to invoke rand() as less as possible
 | 
			
		||||
 | 
			
		||||
unsigned InvadersColumn::randomValid() const {
 | 
			
		||||
unsigned InvadersColumn::randomValidInv() const {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	unsigned validTotal = 0;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,3 @@
 | 
			
		||||
 | 
			
		||||
#include <utils.h>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
bool areLinesColliding(unsigned start1, unsigned end1, unsigned start2, unsigned end2){
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user