Abstraction de la classe Game en Level pour accueillir Editor
This commit is contained in:
parent
5df9190c0a
commit
26a363ad10
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __PTF_CONSTANTS_HPP__
|
#ifndef __PTF_CONSTANTS_HPP__
|
||||||
#define __PTF_CONSTANTS_HPP__
|
#define __PTF_CONSTANTS_HPP__
|
||||||
|
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
namespace Constants {
|
namespace Constants {
|
||||||
/**
|
/**
|
||||||
* Constante d'attraction. Utilisée dans la formule
|
* Constante d'attraction. Utilisée dans la formule
|
||||||
|
|
|
@ -1,53 +1,26 @@
|
||||||
#ifndef __PTF_GAME_HPP__
|
#ifndef __PTF_GAME_HPP__
|
||||||
#define __PTF_GAME_HPP__
|
#define __PTF_GAME_HPP__
|
||||||
|
|
||||||
#include <SFML/Audio.hpp>
|
#include "level.hpp"
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
|
||||||
#include "view.hpp"
|
|
||||||
#include "object.hpp"
|
|
||||||
#include "manager.hpp"
|
|
||||||
#include "resource_manager.hpp"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* La classe Game gère l'affichage et les objets
|
* La classe Game gère l'affichage et les objets
|
||||||
* d'une partie de jeu
|
* d'une partie de jeu
|
||||||
*/
|
*/
|
||||||
class Game : public View {
|
class Game : public Level {
|
||||||
private:
|
private:
|
||||||
std::string level_name;
|
|
||||||
sf::Sprite background;
|
|
||||||
|
|
||||||
sf::Time next_frame_time;
|
sf::Time next_frame_time;
|
||||||
|
|
||||||
std::vector<ObjectPtr> objects;
|
|
||||||
std::vector<std::pair<float, float>> level_zone;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Met à jour les objets du jeu pour
|
* Met à jour les objets du jeu pour
|
||||||
* qu'ils s'adaptent au nouvel état
|
* qu'ils s'adaptent au nouvel état
|
||||||
*/
|
*/
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
/**
|
|
||||||
* Dessine la scène du jeu couche par couche
|
|
||||||
*/
|
|
||||||
void draw();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Game(Manager& manager);
|
Game(Manager& manager);
|
||||||
virtual ~Game();
|
virtual ~Game();
|
||||||
|
|
||||||
/**
|
|
||||||
* Charge un niveau de jeu depuis le fichier donné
|
|
||||||
*/
|
|
||||||
void load(std::ifstream& file);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sauvegarde la configuration actuelle comme un niveau
|
|
||||||
*/
|
|
||||||
void save();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demande le passage à la frame suivante sur
|
* Demande le passage à la frame suivante sur
|
||||||
* cette vue
|
* cette vue
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef __PTF_OBJECT_VIEW_HPP__
|
||||||
|
#define __PTF_OBJECT_VIEW_HPP__
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include "view.hpp"
|
||||||
|
#include "object.hpp"
|
||||||
|
#include "manager.hpp"
|
||||||
|
#include "resource_manager.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* La classe Level est une abstraction des
|
||||||
|
* classes affichant une collection d'objets, comme
|
||||||
|
* les classe de l'éditeur et du jeu
|
||||||
|
*/
|
||||||
|
class Level : public View {
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
sf::Sprite background;
|
||||||
|
|
||||||
|
std::vector<ObjectPtr> objects;
|
||||||
|
std::vector<std::pair<float, float>> zone;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Dessine tous les objets et le fond à l'écran
|
||||||
|
*/
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Level(Manager& manager);
|
||||||
|
virtual ~Level();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Charge un niveau de jeu depuis le fichier donné
|
||||||
|
*/
|
||||||
|
void load(std::ifstream& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sauvegarde la configuration actuelle comme un niveau
|
||||||
|
*/
|
||||||
|
void save();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère le nom du niveau
|
||||||
|
*/
|
||||||
|
std::string getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère la liste des objets
|
||||||
|
*/
|
||||||
|
std::vector<ObjectPtr> getObjects();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère la zone du niveau
|
||||||
|
*/
|
||||||
|
std::vector<std::pair<float, float>> getZone();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
151
src/game.cpp
151
src/game.cpp
|
@ -1,114 +1,9 @@
|
||||||
#include "game.hpp"
|
#include "game.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "object.hpp"
|
|
||||||
#include "block.hpp"
|
|
||||||
#include "player.hpp"
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <queue>
|
|
||||||
#include <utility>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
/**
|
Game::Game(Manager& manager) : Level(manager),
|
||||||
* Dictionnaire associant les types d'objets
|
|
||||||
* à des instances qui seront utilisées pour la
|
|
||||||
* construction d'autres objets de ces types
|
|
||||||
*/
|
|
||||||
std::map<unsigned int, std::function<std::shared_ptr<Object>(std::ifstream&)>> object_type_map = {
|
|
||||||
{Player::TYPE_ID, Player::load},
|
|
||||||
{Block::TYPE_ID, Block::load}
|
|
||||||
};
|
|
||||||
|
|
||||||
Game::Game(Manager& manager) : View(manager),
|
|
||||||
next_frame_time(manager.getCurrentTime()) {}
|
next_frame_time(manager.getCurrentTime()) {}
|
||||||
|
Game::~Game() {}
|
||||||
Game::~Game() {
|
|
||||||
objects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::load(std::ifstream& file) {
|
|
||||||
// vide le niveau précédent s'il y a lieu
|
|
||||||
if (objects.size() != 0) {
|
|
||||||
objects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// lecture de la signture du fichier ("BAR")
|
|
||||||
char signature[3];
|
|
||||||
file.read(signature, sizeof(signature));
|
|
||||||
|
|
||||||
if (strncmp(signature, "BAR", sizeof(signature)) != 0) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"Impossible de lire le fichier : en-tête invalide"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// lecture de la version du fichier
|
|
||||||
char file_version;
|
|
||||||
file.read(&file_version, 1);
|
|
||||||
|
|
||||||
if (file_version != 0) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"Impossible de lire le fichier : version non prise en charge"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// lecture du nom du niveau
|
|
||||||
std::getline(file, level_name, '\0');
|
|
||||||
|
|
||||||
// lecture de la zone de jeu
|
|
||||||
char control_points;
|
|
||||||
file.read(&control_points, 1);
|
|
||||||
level_zone.clear();
|
|
||||||
|
|
||||||
for (int i = 0; i < control_points; i++) {
|
|
||||||
float pos_x, pos_y;
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&pos_x), sizeof(pos_x));
|
|
||||||
file.read(reinterpret_cast<char*>(&pos_y), sizeof(pos_y));
|
|
||||||
|
|
||||||
pos_x *= Constants::GRID;
|
|
||||||
pos_y *= Constants::GRID;
|
|
||||||
|
|
||||||
level_zone.push_back(std::make_pair(pos_x, pos_y));
|
|
||||||
}
|
|
||||||
|
|
||||||
// lecture des chemins de la musique et du fond
|
|
||||||
std::string music_name, background_name;
|
|
||||||
ResourceManager& resource_manager = manager.getResourceManager();
|
|
||||||
|
|
||||||
std::getline(file, music_name, '\0');
|
|
||||||
resource_manager.setMusic(music_name);
|
|
||||||
resource_manager.playMusic();
|
|
||||||
|
|
||||||
std::getline(file, background_name, '\0');
|
|
||||||
background.setTexture(resource_manager.getTexture(background_name));
|
|
||||||
|
|
||||||
// lecture du nombre de blocs
|
|
||||||
int block_count;
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(&block_count), sizeof(block_count));
|
|
||||||
block_count = ntohl(block_count);
|
|
||||||
|
|
||||||
for (int i = 0; i < block_count; i++) {
|
|
||||||
char block_type;
|
|
||||||
file.read(&block_type, 1);
|
|
||||||
|
|
||||||
// vérifie que le type est pris en charge
|
|
||||||
// pour éviter une erreur de segmentation
|
|
||||||
if (object_type_map.count(block_type) == 0) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"Impossible de lire le fichier : type d'objet inconnu"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
objects.push_back(object_type_map[block_type](file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::save() {
|
|
||||||
// TODO: faire une fonction d'enregistrement
|
|
||||||
// TODO: migrer sur une classe commune Game <-> Editor
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::frame() {
|
void Game::frame() {
|
||||||
sf::Time current_time = manager.getCurrentTime();
|
sf::Time current_time = manager.getCurrentTime();
|
||||||
|
@ -136,11 +31,11 @@ void Game::update() {
|
||||||
std::vector<CollisionData> colliding;
|
std::vector<CollisionData> colliding;
|
||||||
|
|
||||||
// détection des objets en collision
|
// détection des objets en collision
|
||||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
||||||
ObjectPtr objA = objects[i];
|
ObjectPtr objA = getObjects()[i];
|
||||||
|
|
||||||
for (unsigned int j = i + 1; j < objects.size(); j++) {
|
for (unsigned int j = i + 1; j < getObjects().size(); j++) {
|
||||||
ObjectPtr objB = objects[j];
|
ObjectPtr objB = getObjects()[j];
|
||||||
CollisionData data(*objA, *objB);
|
CollisionData data(*objA, *objB);
|
||||||
|
|
||||||
if (objA->detectCollision(*objB, data)) {
|
if (objA->detectCollision(*objB, data)) {
|
||||||
|
@ -150,8 +45,8 @@ void Game::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// intégration des forces dans la vitesse (première moitié)
|
// intégration des forces dans la vitesse (première moitié)
|
||||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
||||||
objects[i]->updateVelocity(manager, objects, Constants::PHYSICS_TIME.asSeconds() / 2);
|
getObjects()[i]->updateVelocity(manager, getObjects(), Constants::PHYSICS_TIME.asSeconds() / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// résolution des collisions détectées
|
// résolution des collisions détectées
|
||||||
|
@ -161,8 +56,8 @@ void Game::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// intégration de la vitesse dans la position
|
// intégration de la vitesse dans la position
|
||||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
||||||
objects[i]->updatePosition(Constants::PHYSICS_TIME.asSeconds());
|
getObjects()[i]->updatePosition(Constants::PHYSICS_TIME.asSeconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
// application de la correction positionnelle
|
// application de la correction positionnelle
|
||||||
|
@ -174,29 +69,7 @@ void Game::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// intégration des forces dans la vitesse (seconde moitié)
|
// intégration des forces dans la vitesse (seconde moitié)
|
||||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
||||||
objects[i]->updateVelocity(manager, objects, Constants::PHYSICS_TIME.asSeconds() / 2);
|
getObjects()[i]->updateVelocity(manager, getObjects(), Constants::PHYSICS_TIME.asSeconds() / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::draw() {
|
|
||||||
// efface la scène précédente et dessine la couche de fond
|
|
||||||
sf::RenderWindow& window = manager.getWindow();
|
|
||||||
window.clear(sf::Color(66, 165, 245));
|
|
||||||
window.draw(background);
|
|
||||||
|
|
||||||
// chargement de la file d'affichage des objets
|
|
||||||
std::priority_queue<ObjectPtr, std::vector<ObjectPtr>, ObjectCompare> display_queue;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
|
||||||
display_queue.push(objects[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// dessin des objets de la file d'affichage couche par couche
|
|
||||||
while (!display_queue.empty()) {
|
|
||||||
display_queue.top()->draw(manager);
|
|
||||||
display_queue.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.display();
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include "constants.hpp"
|
||||||
|
#include "block.hpp"
|
||||||
|
#include "player.hpp"
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <queue>
|
||||||
|
#include <utility>
|
||||||
|
#include "level.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dictionnaire associant les types d'objets
|
||||||
|
* à des instances qui seront utilisées pour la
|
||||||
|
* construction d'autres objets de ces types
|
||||||
|
*/
|
||||||
|
std::map<unsigned int, std::function<std::shared_ptr<Object>(std::ifstream&)>> object_type_map = {
|
||||||
|
{Player::TYPE_ID, Player::load},
|
||||||
|
{Block::TYPE_ID, Block::load}
|
||||||
|
};
|
||||||
|
|
||||||
|
Level::Level(Manager& manager) : View(manager) {}
|
||||||
|
Level::~Level() {
|
||||||
|
objects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Level::load(std::ifstream& file) {
|
||||||
|
// vide le niveau précédent s'il y a lieu
|
||||||
|
if (objects.size() != 0) {
|
||||||
|
objects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// lecture de la signture du fichier ("BAR")
|
||||||
|
char signature[3];
|
||||||
|
file.read(signature, sizeof(signature));
|
||||||
|
|
||||||
|
if (strncmp(signature, "BAR", sizeof(signature)) != 0) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Impossible de lire le fichier : en-tête invalide"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lecture de la version du fichier
|
||||||
|
char file_version;
|
||||||
|
file.read(&file_version, 1);
|
||||||
|
|
||||||
|
if (file_version != 0) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Impossible de lire le fichier : version non prise en charge"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lecture du nom du niveau
|
||||||
|
std::getline(file, name, '\0');
|
||||||
|
|
||||||
|
// lecture de la zone de jeu
|
||||||
|
char control_points;
|
||||||
|
file.read(&control_points, 1);
|
||||||
|
zone.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < control_points; i++) {
|
||||||
|
float pos_x, pos_y;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&pos_x), sizeof(pos_x));
|
||||||
|
file.read(reinterpret_cast<char*>(&pos_y), sizeof(pos_y));
|
||||||
|
|
||||||
|
pos_x *= Constants::GRID;
|
||||||
|
pos_y *= Constants::GRID;
|
||||||
|
|
||||||
|
zone.push_back(std::make_pair(pos_x, pos_y));
|
||||||
|
}
|
||||||
|
|
||||||
|
// lecture des chemins de la musique et du fond
|
||||||
|
std::string music_name, background_name;
|
||||||
|
ResourceManager& resource_manager = manager.getResourceManager();
|
||||||
|
|
||||||
|
std::getline(file, music_name, '\0');
|
||||||
|
resource_manager.setMusic(music_name);
|
||||||
|
resource_manager.playMusic();
|
||||||
|
|
||||||
|
std::getline(file, background_name, '\0');
|
||||||
|
background.setTexture(resource_manager.getTexture(background_name));
|
||||||
|
|
||||||
|
// lecture du nombre de blocs
|
||||||
|
int block_count;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&block_count), sizeof(block_count));
|
||||||
|
block_count = ntohl(block_count);
|
||||||
|
|
||||||
|
for (int i = 0; i < block_count; i++) {
|
||||||
|
char block_type;
|
||||||
|
file.read(&block_type, 1);
|
||||||
|
|
||||||
|
// vérifie que le type est pris en charge
|
||||||
|
// pour éviter une erreur de segmentation
|
||||||
|
if (object_type_map.count(block_type) == 0) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Impossible de lire le fichier : type d'objet inconnu"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects.push_back(object_type_map[block_type](file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Level::save() {
|
||||||
|
// TODO: faire une fonction d'enregistrement
|
||||||
|
}
|
||||||
|
|
||||||
|
void Level::draw() {
|
||||||
|
// efface la scène précédente et dessine la couche de fond
|
||||||
|
sf::RenderWindow& window = manager.getWindow();
|
||||||
|
window.clear(sf::Color(66, 165, 245));
|
||||||
|
window.draw(background);
|
||||||
|
|
||||||
|
// chargement de la file d'affichage des objets
|
||||||
|
std::priority_queue<ObjectPtr, std::vector<ObjectPtr>, ObjectCompare> display_queue;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < objects.size(); i++) {
|
||||||
|
display_queue.push(objects[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dessin des objets de la file d'affichage couche par couche
|
||||||
|
while (!display_queue.empty()) {
|
||||||
|
display_queue.top()->draw(manager);
|
||||||
|
display_queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Level::getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ObjectPtr> Level::getObjects() {
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<float, float>> Level::getZone() {
|
||||||
|
return zone;
|
||||||
|
}
|
Loading…
Reference in New Issue