2016-04-03 19:05:27 +00:00
|
|
|
#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
|
|
|
|
*/
|
2016-04-06 11:54:03 +00:00
|
|
|
std::map<unsigned int, std::function<ObjectPtr(std::ifstream&)>> object_type_map = {
|
2016-04-03 19:05:27 +00:00
|
|
|
{Player::TYPE_ID, Player::load},
|
|
|
|
{Block::TYPE_ID, Block::load}
|
|
|
|
};
|
|
|
|
|
2016-04-07 09:23:31 +00:00
|
|
|
Level::Level(Manager& manager) : View(manager), total_time(30) {}
|
2016-04-03 19:05:27 +00:00
|
|
|
Level::~Level() {
|
2016-04-07 22:19:01 +00:00
|
|
|
setViewCenter(sf::Vector2f(0, 0));
|
2016-04-03 19:05:27 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2016-04-07 22:19:01 +00:00
|
|
|
// positionnement de la vue au centre
|
|
|
|
setViewCenter(sf::Vector2f(0, 0));
|
|
|
|
|
2016-04-03 19:05:27 +00:00
|
|
|
// 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
|
2016-04-06 12:02:11 +00:00
|
|
|
std::string std_name;
|
|
|
|
std::getline(file, std_name, '\0');
|
|
|
|
name = sf::String(std_name);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-05 18:16:20 +00:00
|
|
|
// lecture du temps total du niveau
|
|
|
|
file.read(reinterpret_cast<char*>(&total_time), sizeof(total_time));
|
|
|
|
total_time = ntohl(total_time);
|
|
|
|
|
2016-04-03 19:05:27 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2016-04-07 22:19:01 +00:00
|
|
|
bool Level::frame() {
|
|
|
|
const std::vector<sf::Event>& events = manager.getEvents();
|
|
|
|
|
|
|
|
// traitement des événements
|
|
|
|
for (unsigned int i = 0; i < events.size(); i++) {
|
|
|
|
if (processEvent(events[i])) {
|
|
|
|
// /!\ On arrête là si on a demandé l'interruption.
|
|
|
|
// Il est important de ne plus appeler aucune autre
|
|
|
|
// fonction de la classe pour éviter une erreur
|
|
|
|
// de segmentation
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-04-03 19:05:27 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 12:02:11 +00:00
|
|
|
sf::String Level::getName() const {
|
2016-04-03 19:05:27 +00:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2016-04-06 12:02:11 +00:00
|
|
|
void Level::setName(sf::String set_name) {
|
2016-04-05 18:16:20 +00:00
|
|
|
name = set_name;
|
|
|
|
}
|
|
|
|
|
2016-04-06 12:02:11 +00:00
|
|
|
int Level::getTotalTime() const {
|
2016-04-05 18:16:20 +00:00
|
|
|
return total_time;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Level::setTotalTime(int set_total_time) {
|
2016-04-05 22:30:18 +00:00
|
|
|
// faisons rester le temps entre 10s et 59:59
|
|
|
|
set_total_time = std::min(set_total_time, 3599);
|
|
|
|
set_total_time = std::max(set_total_time, 10);
|
|
|
|
|
2016-04-05 18:16:20 +00:00
|
|
|
total_time = set_total_time;
|
|
|
|
}
|
|
|
|
|
2016-04-06 12:02:11 +00:00
|
|
|
sf::Sprite Level::getBackground() const {
|
|
|
|
return background;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Level::setBackground(sf::Sprite set_background) {
|
|
|
|
background = set_background;
|
|
|
|
}
|
|
|
|
|
2016-04-04 18:25:17 +00:00
|
|
|
std::vector<ObjectPtr>& Level::getObjects() {
|
2016-04-03 19:05:27 +00:00
|
|
|
return objects;
|
|
|
|
}
|
|
|
|
|
2016-04-05 18:16:20 +00:00
|
|
|
std::vector<std::pair<float, float>>& Level::getZone() {
|
2016-04-03 19:05:27 +00:00
|
|
|
return zone;
|
|
|
|
}
|
2016-04-07 22:19:01 +00:00
|
|
|
|
|
|
|
sf::Vector2f Level::getViewCenter() {
|
|
|
|
return manager.getWindowView().getCenter();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Level::setViewCenter(sf::Vector2f set_view_center) {
|
|
|
|
manager.getWindowView().setCenter(set_view_center);
|
|
|
|
}
|