2016-04-12 16:11:36 +00:00
|
|
|
#include "manager.hpp"
|
2016-04-09 03:43:40 +00:00
|
|
|
#include "level.hpp"
|
2016-04-03 19:05:27 +00:00
|
|
|
#include "player.hpp"
|
2016-04-09 03:43:40 +00:00
|
|
|
#include "block.hpp"
|
2016-04-17 21:10:30 +00:00
|
|
|
#include "utility.hpp"
|
2016-04-09 03:43:40 +00:00
|
|
|
#include "gravity_block.hpp"
|
2016-04-11 11:35:29 +00:00
|
|
|
#include "switch_block.hpp"
|
2016-04-11 01:51:51 +00:00
|
|
|
#include "finish_block.hpp"
|
|
|
|
#include "kill_block.hpp"
|
2016-04-11 00:20:40 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
2016-04-11 01:51:51 +00:00
|
|
|
#include <iostream>
|
2016-04-03 19:05:27 +00:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <cstring>
|
2016-04-11 01:23:15 +00:00
|
|
|
#include <functional>
|
2016-04-03 19:05:27 +00:00
|
|
|
#include <queue>
|
|
|
|
|
2016-04-09 14:31:09 +00:00
|
|
|
/**
|
2016-04-12 16:11:36 +00:00
|
|
|
* Définition des variables et fonctions globales internes
|
|
|
|
* (accessibles uniquement dans ce fichier)
|
2016-04-09 14:31:09 +00:00
|
|
|
*/
|
2016-04-12 16:11:36 +00:00
|
|
|
namespace {
|
|
|
|
/**
|
|
|
|
* Constante de gravité
|
|
|
|
*/
|
|
|
|
const float GRAVITY = 235;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constante de déplacement des objets à déplacement manuel
|
|
|
|
*/
|
|
|
|
const float MOVE = 200;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Numéro actuel de version du format de fichier
|
|
|
|
*/
|
|
|
|
const unsigned int VERSION_NUMBER = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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<Object::Ptr(std::ifstream&)>> object_type_map = {
|
|
|
|
{Player::TYPE_ID, Player::load},
|
|
|
|
{Block::TYPE_ID, Block::load},
|
|
|
|
{GravityBlock::TYPE_ID, GravityBlock::load},
|
|
|
|
{FinishBlock::TYPE_ID, FinishBlock::load},
|
|
|
|
{KillBlock::TYPE_ID, KillBlock::load},
|
|
|
|
{SwitchBlock::TYPE_ID, SwitchBlock::load}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lecture du niveau dont le chemin absolu complet est en paramètre.
|
|
|
|
* Les métadonnées sont stockées dans les variables passées par référence.
|
|
|
|
* La callback object() est appelée séquentiellement avec les objets du niveau
|
|
|
|
*/
|
|
|
|
void loadLevel(
|
|
|
|
std::string path, sf::String& name, int& total_time,
|
|
|
|
std::vector<sf::Vector2f>& zone,
|
|
|
|
std::string& background, std::string& music,
|
|
|
|
std::function<Object::Ptr(Object::Ptr)> object_callback = {}
|
|
|
|
) {
|
|
|
|
// ouverture du fichier
|
|
|
|
std::ifstream file;
|
|
|
|
file.open(path, std::ios::binary | std::ios::in);
|
|
|
|
|
|
|
|
// on vérifie que le fichier ait correctement été ouvert en lecture
|
|
|
|
if (file.fail()) {
|
|
|
|
throw std::runtime_error(
|
|
|
|
"Impossible de charger le niveau \"" + name + "\" " +
|
|
|
|
"(" + std::string(strerror(errno)) + ")"
|
|
|
|
);
|
|
|
|
}
|
2016-04-10 07:41:26 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture de la signature du fichier ("BAR")
|
|
|
|
char signature[3];
|
|
|
|
file.read(signature, 3);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
if (strncmp(signature, "BAR", 3) != 0) {
|
|
|
|
throw std::runtime_error(
|
|
|
|
"Impossible de charger le niveau \"" + name + "\" " +
|
|
|
|
"(en-tête invalide)"
|
|
|
|
);
|
|
|
|
}
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture de la version du fichier
|
|
|
|
char file_version;
|
|
|
|
file.read(&file_version, 1);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
if (file_version != VERSION_NUMBER) {
|
|
|
|
throw std::runtime_error(
|
|
|
|
"Impossible de charger le niveau \"" + name + "\" " +
|
|
|
|
"(version non prise en charge)"
|
|
|
|
);
|
|
|
|
}
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture du nom du niveau
|
|
|
|
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-12 16:11:36 +00:00
|
|
|
// lecture du temps total du niveau
|
|
|
|
file.read(reinterpret_cast<char*>(&total_time), 4);
|
|
|
|
total_time = ntohl(total_time);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture de la zone de jeu
|
|
|
|
char control_points;
|
|
|
|
file.read(&control_points, 1);
|
|
|
|
zone.clear();
|
2016-04-05 18:16:20 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
for (int i = 0; i < control_points; i++) {
|
|
|
|
float pos_x, pos_y;
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
file.read(reinterpret_cast<char*>(&pos_x), 4);
|
|
|
|
file.read(reinterpret_cast<char*>(&pos_y), 4);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
pos_x *= Manager::GRID;
|
|
|
|
pos_y *= Manager::GRID;
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
zone.push_back(sf::Vector2f(pos_x, pos_y));
|
|
|
|
}
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture des chemins de la musique et du fond
|
|
|
|
std::getline(file, music, '\0');
|
|
|
|
std::getline(file, background, '\0');
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture des objets si une callback a été fournie
|
|
|
|
int object_count;
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
if (!object_callback) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
file.read(reinterpret_cast<char*>(&object_count), 4);
|
|
|
|
object_count = ntohl(object_count);
|
2016-04-11 01:23:15 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
for (int i = 0; i < object_count; i++) {
|
|
|
|
char object_type;
|
|
|
|
file.read(&object_type, 1);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// vérifie que le type est pris en charge
|
|
|
|
// pour éviter une erreur de segmentation
|
|
|
|
if (object_type_map.count(object_type) == 0) {
|
|
|
|
throw std::runtime_error(
|
|
|
|
"Impossible de charger le niveau \"" + name + "\" " +
|
|
|
|
"(type d'objet " + std::to_string(object_type) + " inconnu)"
|
|
|
|
);
|
|
|
|
}
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-12 16:11:36 +00:00
|
|
|
// lecture de l'objet
|
|
|
|
object_callback(object_type_map[object_type](file));
|
2016-04-03 19:05:27 +00:00
|
|
|
}
|
2016-04-11 01:23:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Level::Level(Manager& manager) : State(manager) {
|
2016-04-11 19:11:34 +00:00
|
|
|
gravity_direction = GravityDirection::SOUTH;
|
|
|
|
|
2016-04-11 01:23:15 +00:00
|
|
|
// métadonnées par défaut
|
2016-04-11 21:07:05 +00:00
|
|
|
setName(sf::String("Nouveau niveau"));
|
2016-04-11 20:03:28 +00:00
|
|
|
current_path = getResourceManager().getLevelPath("new_level.dat");
|
2016-04-11 21:07:05 +00:00
|
|
|
setTotalTime(30);
|
2016-04-11 01:23:15 +00:00
|
|
|
|
|
|
|
// zone de jeu par défaut
|
2016-04-17 19:19:13 +00:00
|
|
|
int size = 8;
|
|
|
|
|
|
|
|
zone.push_back(sf::Vector2f(-size * Manager::GRID, -size * Manager::GRID));
|
|
|
|
zone.push_back(sf::Vector2f(size * Manager::GRID, -size * Manager::GRID));
|
|
|
|
zone.push_back(sf::Vector2f(size * Manager::GRID, size * Manager::GRID));
|
|
|
|
zone.push_back(sf::Vector2f(-size * Manager::GRID, size * Manager::GRID));
|
2016-04-11 01:23:15 +00:00
|
|
|
|
|
|
|
// ressources par défaut
|
2016-04-11 21:07:05 +00:00
|
|
|
setMusic("");
|
|
|
|
setBackground("");
|
2016-04-11 20:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Level::~Level() {}
|
2016-04-11 01:23:15 +00:00
|
|
|
|
2016-04-17 13:25:21 +00:00
|
|
|
void Level::enable() {
|
|
|
|
// positionnement par défaut de la caméra
|
|
|
|
sf::Vector2u window_size = getWindow().getSize();
|
|
|
|
|
|
|
|
camera.setSize(window_size.x, window_size.y);
|
|
|
|
camera.setCenter(0, 0);
|
|
|
|
camera_angle = 180.f;
|
|
|
|
}
|
|
|
|
|
2016-04-11 20:03:28 +00:00
|
|
|
sf::String Level::getLevelName(std::string path) {
|
|
|
|
sf::String name;
|
|
|
|
int total_time;
|
|
|
|
std::vector<sf::Vector2f> zone;
|
|
|
|
std::string background;
|
|
|
|
std::string music;
|
|
|
|
|
|
|
|
loadLevel(path, name, total_time, zone, background, music);
|
|
|
|
return name;
|
2016-04-11 01:23:15 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 01:51:51 +00:00
|
|
|
void Level::load(std::string path) {
|
2016-04-11 01:23:15 +00:00
|
|
|
loadLevel(
|
2016-04-11 01:51:51 +00:00
|
|
|
path, name, total_time,
|
2016-04-11 01:23:15 +00:00
|
|
|
zone, background, music,
|
|
|
|
std::bind(&Level::addObject, this, std::placeholders::_1)
|
|
|
|
);
|
2016-04-11 19:20:05 +00:00
|
|
|
|
2016-04-11 21:07:05 +00:00
|
|
|
setTotalTime(total_time);
|
|
|
|
setMusic(music);
|
2016-04-11 01:51:51 +00:00
|
|
|
current_path = path;
|
2016-04-03 19:05:27 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 01:51:51 +00:00
|
|
|
void Level::save(std::string path) {
|
2016-04-10 07:41:26 +00:00
|
|
|
std::ofstream file;
|
2016-04-11 01:51:51 +00:00
|
|
|
file.open(path, std::ios::binary | std::ios::out);
|
2016-04-10 07:41:26 +00:00
|
|
|
|
|
|
|
// on vérifie que le fichier ait correctement été ouvert en lecture
|
|
|
|
if (file.fail()) {
|
|
|
|
throw std::runtime_error(
|
|
|
|
"Impossible d'enregistrer le niveau \"" + name + "\" " +
|
|
|
|
"(" + std::string(strerror(errno)) + ")"
|
|
|
|
);
|
|
|
|
}
|
2016-04-10 04:53:45 +00:00
|
|
|
|
|
|
|
// écriture de la signture du fichier ("BAR")
|
|
|
|
char signature[3] = {'B', 'A', 'R'};
|
|
|
|
file.write(signature, 3);
|
|
|
|
|
|
|
|
// écriture de la version du fichier
|
|
|
|
char file_version = VERSION_NUMBER;
|
|
|
|
file.write(&file_version, 1);
|
|
|
|
|
|
|
|
// écriture du nom du niveau
|
|
|
|
char *write_name = (char*) name.toAnsiString().data();
|
|
|
|
file.write(write_name, name.getSize() + 1);
|
|
|
|
|
|
|
|
// écriture du temps total du niveau
|
|
|
|
int conv_total_time = htonl(total_time);
|
|
|
|
file.write(reinterpret_cast<char*>(&conv_total_time), 4);
|
|
|
|
|
|
|
|
// écriture de la zone de jeu
|
|
|
|
char control_points = (char) zone.size();
|
|
|
|
file.write(&control_points, 1);
|
|
|
|
|
|
|
|
for (int i = 0; i < control_points; i++) {
|
2016-04-12 16:11:36 +00:00
|
|
|
float pos_x = zone[i].x / Manager::GRID;
|
|
|
|
float pos_y = zone[i].y / Manager::GRID;
|
2016-04-10 04:53:45 +00:00
|
|
|
|
|
|
|
file.write(reinterpret_cast<char*>(&pos_x), 4);
|
|
|
|
file.write(reinterpret_cast<char*>(&pos_y), 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// écriture des noms de la musique et du fond
|
|
|
|
char *write_music = (char*) music.data();
|
|
|
|
file.write(write_music, music.size() + 1);
|
2016-04-09 20:36:07 +00:00
|
|
|
|
2016-04-10 04:53:45 +00:00
|
|
|
char *write_background = (char*) background.data();
|
|
|
|
file.write(write_background, background.size() + 1);
|
|
|
|
|
|
|
|
// écriture des objets
|
|
|
|
int object_count = htonl(objects.size());
|
|
|
|
file.write(reinterpret_cast<char*>(&object_count), 4);
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < objects.size(); i++) {
|
|
|
|
char object_type = objects[i]->getTypeId();
|
|
|
|
file.write(&object_type, 1);
|
|
|
|
|
|
|
|
// écriture de l'objet
|
|
|
|
objects[i]->save(file);
|
|
|
|
}
|
2016-04-11 01:51:51 +00:00
|
|
|
|
|
|
|
std::cout << "Sauvegardé : " << path << std::endl;
|
2016-04-03 19:05:27 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 00:20:40 +00:00
|
|
|
void Level::save() {
|
2016-04-11 01:51:51 +00:00
|
|
|
save(current_path);
|
2016-04-11 00:20:40 +00:00
|
|
|
}
|
|
|
|
|
2016-04-08 00:35:17 +00:00
|
|
|
void Level::processEvent(const sf::Event& event) {
|
2016-04-08 00:21:19 +00:00
|
|
|
// lorsque la fenêtre est redimensionnée, mise à jour
|
|
|
|
// de la taille de la caméra
|
|
|
|
if (event.type == sf::Event::Resized) {
|
|
|
|
camera.setSize(event.size.width, event.size.height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-03 19:05:27 +00:00
|
|
|
void Level::draw() {
|
2016-04-09 02:36:30 +00:00
|
|
|
sf::RenderWindow& window = getWindow();
|
2016-04-15 13:13:34 +00:00
|
|
|
sf::Vector2u window_size = window.getSize();
|
2016-04-08 00:21:19 +00:00
|
|
|
|
2016-04-09 14:31:09 +00:00
|
|
|
// animation de la rotation de la caméra
|
2016-04-17 21:10:30 +00:00
|
|
|
camera_angle = Utility::animateValue(
|
|
|
|
camera_angle, 5,
|
|
|
|
std::fmod((float) gravity_direction * 90, 360)
|
|
|
|
);
|
2016-04-09 15:37:12 +00:00
|
|
|
|
|
|
|
camera.setRotation(camera_angle + 180);
|
2016-04-08 00:21:19 +00:00
|
|
|
window.setView(camera);
|
|
|
|
|
2016-04-12 19:04:44 +00:00
|
|
|
// efface la scène précédente
|
2016-04-03 19:05:27 +00:00
|
|
|
window.clear(sf::Color(66, 165, 245));
|
2016-04-10 04:53:45 +00:00
|
|
|
|
2016-04-15 13:13:34 +00:00
|
|
|
// on englobe la caméra dans un rectangle circonscrit, dans
|
|
|
|
// le cas où elle serait en rotation
|
|
|
|
sf::Vector2f camera_corners[] = {
|
|
|
|
pixelToCoords(sf::Vector2i(0, 0)),
|
|
|
|
pixelToCoords(sf::Vector2i(window_size.x, 0)),
|
|
|
|
pixelToCoords(sf::Vector2i(window_size.x, window_size.y)),
|
|
|
|
pixelToCoords(sf::Vector2i(0, window_size.y))
|
|
|
|
};
|
|
|
|
|
|
|
|
sf::Vector2f camera_topleft = camera_corners[0];
|
|
|
|
sf::Vector2f camera_botright = camera_corners[0];
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < 4; i++) {
|
|
|
|
camera_topleft.x = std::min(camera_topleft.x, camera_corners[i].x);
|
|
|
|
camera_topleft.y = std::min(camera_topleft.y, camera_corners[i].y);
|
|
|
|
camera_botright.x = std::max(camera_botright.x, camera_corners[i].x);
|
|
|
|
camera_botright.y = std::max(camera_botright.y, camera_corners[i].y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// on dessine le fond s'il y en a un
|
2016-04-10 04:53:45 +00:00
|
|
|
if (background != "") {
|
2016-04-12 19:04:44 +00:00
|
|
|
sf::Texture& bg_texture = getResourceManager().getTexture(background);
|
2016-04-15 13:13:34 +00:00
|
|
|
sf::Vector2f bg_size = (sf::Vector2f) bg_texture.getSize();
|
2016-04-12 19:04:44 +00:00
|
|
|
|
2016-04-15 13:13:34 +00:00
|
|
|
background_sprite.setTexture(bg_texture);
|
2016-04-12 19:04:44 +00:00
|
|
|
|
2016-04-15 13:13:34 +00:00
|
|
|
// on regarde la position du coin où il faut commencer à
|
|
|
|
// dessiner le fond, et la zone sur laquelle il faut le dessiner
|
|
|
|
int x_left = std::floor(camera_topleft.x / bg_size.x);
|
|
|
|
int y_top = std::floor(camera_topleft.y / bg_size.y);
|
|
|
|
int x_right = std::ceil(camera_botright.x / bg_size.x);
|
|
|
|
int y_bottom = std::ceil(camera_botright.y / bg_size.y);
|
2016-04-12 19:04:44 +00:00
|
|
|
|
2016-04-15 13:13:34 +00:00
|
|
|
// et on dessine aux positions calculées
|
|
|
|
for (int x = x_left; x < x_right; x++) {
|
|
|
|
for (int y = y_top; y < y_bottom; y++) {
|
2016-04-12 19:04:44 +00:00
|
|
|
background_sprite.setPosition(sf::Vector2f(
|
|
|
|
x * (bg_size.x), y * (bg_size.y)
|
|
|
|
));
|
|
|
|
|
|
|
|
window.draw(background_sprite);
|
|
|
|
}
|
|
|
|
}
|
2016-04-10 04:53:45 +00:00
|
|
|
}
|
|
|
|
|
2016-04-15 13:13:34 +00:00
|
|
|
// tri des objets par ordre d'affichage
|
|
|
|
std::sort(
|
|
|
|
objects.begin(), objects.end(),
|
|
|
|
[](const Object::Ptr &a, const Object::Ptr &b) {
|
|
|
|
sf::Vector2f a_pos = a->getPosition();
|
|
|
|
sf::Vector2f b_pos = b->getPosition();
|
2016-04-03 19:05:27 +00:00
|
|
|
|
2016-04-15 13:13:34 +00:00
|
|
|
return a_pos.x - a_pos.y + a->getLayer()
|
|
|
|
< b_pos.x - b_pos.y + b->getLayer();
|
|
|
|
}
|
|
|
|
);
|
2016-04-03 19:05:27 +00:00
|
|
|
|
|
|
|
// dessin des objets de la file d'affichage couche par couche
|
2016-04-15 13:13:34 +00:00
|
|
|
for (auto it = objects.begin(); it != objects.end(); it++) {
|
|
|
|
sf::Vector2i screen_pos = coordsToPixel((*it)->getPosition());
|
|
|
|
sf::FloatRect aabb = (*it)->getAABB();
|
|
|
|
|
|
|
|
// si l'objet est visible à l'écran, on le dessine
|
|
|
|
if (screen_pos.x >= -aabb.width && screen_pos.y >= -aabb.height &&
|
|
|
|
screen_pos.x <= window_size.x + aabb.width &&
|
|
|
|
screen_pos.y <= window_size.y + aabb.height) {
|
|
|
|
(*it)->draw(*this);
|
|
|
|
}
|
2016-04-03 19:05:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10 04:53:45 +00:00
|
|
|
std::string Level::getMusic() const {
|
|
|
|
return music;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Level::setMusic(std::string set_music) {
|
|
|
|
music = set_music;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Level::getBackground() const {
|
2016-04-06 12:02:11 +00:00
|
|
|
return background;
|
|
|
|
}
|
|
|
|
|
2016-04-10 04:53:45 +00:00
|
|
|
void Level::setBackground(std::string set_background) {
|
2016-04-06 12:02:11 +00:00
|
|
|
background = set_background;
|
|
|
|
}
|
|
|
|
|
2016-04-09 02:58:46 +00:00
|
|
|
sf::Vector2f Level::getGravity() const {
|
2016-04-09 14:12:18 +00:00
|
|
|
switch (gravity_direction) {
|
|
|
|
case GravityDirection::NORTH:
|
|
|
|
return sf::Vector2f(0, -GRAVITY);
|
|
|
|
|
|
|
|
case GravityDirection::EAST:
|
|
|
|
return sf::Vector2f(GRAVITY, 0);
|
|
|
|
|
|
|
|
case GravityDirection::SOUTH:
|
|
|
|
return sf::Vector2f(0, GRAVITY);
|
|
|
|
|
|
|
|
case GravityDirection::WEST:
|
|
|
|
return sf::Vector2f(-GRAVITY, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sf::Vector2f(0, 0);
|
2016-04-09 02:58:46 +00:00
|
|
|
}
|
|
|
|
|
2016-04-09 14:12:18 +00:00
|
|
|
sf::Vector2f Level::getLeftDirection() const {
|
|
|
|
switch (gravity_direction) {
|
2016-04-09 02:58:46 +00:00
|
|
|
case GravityDirection::NORTH:
|
2016-04-09 14:12:18 +00:00
|
|
|
return sf::Vector2f(MOVE, 0);
|
2016-04-09 02:58:46 +00:00
|
|
|
|
2016-04-09 03:43:40 +00:00
|
|
|
case GravityDirection::EAST:
|
2016-04-09 14:12:18 +00:00
|
|
|
return sf::Vector2f(0, MOVE);
|
2016-04-09 02:58:46 +00:00
|
|
|
|
|
|
|
case GravityDirection::SOUTH:
|
2016-04-09 14:12:18 +00:00
|
|
|
return sf::Vector2f(-MOVE, 0);
|
2016-04-09 02:58:46 +00:00
|
|
|
|
2016-04-09 03:43:40 +00:00
|
|
|
case GravityDirection::WEST:
|
2016-04-09 14:12:18 +00:00
|
|
|
return sf::Vector2f(0, -MOVE);
|
2016-04-09 02:58:46 +00:00
|
|
|
}
|
2016-04-09 14:12:18 +00:00
|
|
|
|
|
|
|
return sf::Vector2f(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
sf::Vector2f Level::getRightDirection() const {
|
|
|
|
return -1.f * getLeftDirection();
|
|
|
|
}
|
|
|
|
|
|
|
|
GravityDirection Level::getGravityDirection() {
|
|
|
|
return gravity_direction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Level::setGravityDirection(GravityDirection set_gravity_direction) {
|
|
|
|
gravity_direction = set_gravity_direction;
|
2016-04-09 02:58:46 +00:00
|
|
|
}
|
|
|
|
|
2016-04-10 19:18:21 +00:00
|
|
|
std::vector<Object::Ptr>& Level::getObjects() {
|
2016-04-03 19:05:27 +00:00
|
|
|
return objects;
|
|
|
|
}
|
|
|
|
|
2016-04-10 05:37:09 +00:00
|
|
|
const std::vector<Object::Ptr>& Level::getObjects() const {
|
2016-04-09 02:36:30 +00:00
|
|
|
return objects;
|
|
|
|
}
|
|
|
|
|
2016-04-10 19:18:21 +00:00
|
|
|
std::vector<Player::Ptr>& Level::getPlayers() {
|
|
|
|
return players;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<Player::Ptr>& Level::getPlayers() const {
|
|
|
|
return players;
|
|
|
|
}
|
|
|
|
|
2016-04-10 23:36:20 +00:00
|
|
|
Object::Ptr Level::addObject(Object::Ptr object) {
|
2016-04-10 19:18:21 +00:00
|
|
|
// si c'est un joueur, on le met dans le tableau des joueurs
|
|
|
|
// et on lui attribue un numéro
|
|
|
|
if (object->getTypeId() == Player::TYPE_ID) {
|
2016-04-10 23:36:20 +00:00
|
|
|
// on n'autorise pas plus de deux joueurs
|
|
|
|
if (players.size() >= 2) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-04-10 19:18:21 +00:00
|
|
|
Player::Ptr player = std::dynamic_pointer_cast<Player>(object);
|
|
|
|
|
|
|
|
player->setPlayerNumber(players.size());
|
|
|
|
players.push_back(std::dynamic_pointer_cast<Player>(object));
|
|
|
|
}
|
|
|
|
|
|
|
|
objects.push_back(object);
|
2016-04-10 23:36:20 +00:00
|
|
|
return object;
|
2016-04-10 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Level::removeObject(Object::Ptr object) {
|
|
|
|
// si c'est un joueur, on le supprime de la liste des joueurs
|
|
|
|
if (object->getTypeId() == Player::TYPE_ID) {
|
|
|
|
Player::Ptr player = std::dynamic_pointer_cast<Player>(object);
|
|
|
|
players.erase(std::remove(
|
|
|
|
players.begin(), players.end(), player
|
|
|
|
), players.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
// on supprime l'objet de la liste d'objets
|
|
|
|
objects.erase(std::remove(
|
|
|
|
objects.begin(), objects.end(), object
|
|
|
|
), objects.end());
|
|
|
|
}
|
|
|
|
|
2016-04-10 06:33:09 +00:00
|
|
|
std::vector<sf::Vector2f>& Level::getZone() {
|
2016-04-03 19:05:27 +00:00
|
|
|
return zone;
|
|
|
|
}
|
2016-04-07 22:19:01 +00:00
|
|
|
|
2016-04-10 06:33:09 +00:00
|
|
|
const std::vector<sf::Vector2f>& Level::getZone() const {
|
2016-04-09 02:36:30 +00:00
|
|
|
return zone;
|
|
|
|
}
|
|
|
|
|
|
|
|
sf::View Level::getCamera() const {
|
2016-04-08 00:21:19 +00:00
|
|
|
return camera;
|
|
|
|
}
|
|
|
|
|
2016-04-08 22:26:47 +00:00
|
|
|
sf::Vector2f Level::pixelToCoords(sf::Vector2i pixel) {
|
2016-04-09 02:36:30 +00:00
|
|
|
sf::RenderWindow& window = getWindow();
|
2016-04-08 00:21:19 +00:00
|
|
|
sf::View old_view = window.getView();
|
|
|
|
|
|
|
|
window.setView(camera);
|
2016-04-08 22:26:47 +00:00
|
|
|
sf::Vector2f coords = window.mapPixelToCoords(pixel);
|
2016-04-08 00:21:19 +00:00
|
|
|
window.setView(old_view);
|
|
|
|
|
2016-04-08 22:26:47 +00:00
|
|
|
return coords;
|
|
|
|
}
|
|
|
|
|
|
|
|
sf::Vector2i Level::coordsToPixel(sf::Vector2f coords) {
|
2016-04-09 02:36:30 +00:00
|
|
|
sf::RenderWindow& window = getWindow();
|
2016-04-08 22:26:47 +00:00
|
|
|
sf::View old_view = window.getView();
|
|
|
|
|
|
|
|
window.setView(camera);
|
|
|
|
sf::Vector2i pixel = window.mapCoordsToPixel(coords);
|
|
|
|
window.setView(old_view);
|
|
|
|
|
|
|
|
return pixel;
|
2016-04-07 22:19:01 +00:00
|
|
|
}
|
|
|
|
|
2016-04-08 00:21:19 +00:00
|
|
|
void Level::setCamera(sf::View set_camera) {
|
|
|
|
camera = set_camera;
|
2016-04-07 22:19:01 +00:00
|
|
|
}
|