2016-04-08 13:53:30 +00:00
|
|
|
#include <cmath>
|
2016-03-28 13:05:18 +00:00
|
|
|
#include "game.hpp"
|
2016-04-08 13:53:30 +00:00
|
|
|
#include "player.hpp"
|
2016-03-20 13:32:34 +00:00
|
|
|
#include "constants.hpp"
|
2016-03-04 15:29:31 +00:00
|
|
|
|
2016-04-05 23:13:00 +00:00
|
|
|
Game::Game(Manager& manager) : Level(manager),
|
2016-04-06 13:21:46 +00:00
|
|
|
widget_timer(manager, false),
|
2016-04-05 23:13:00 +00:00
|
|
|
next_frame_time(manager.getCurrentTime()),
|
2016-04-09 13:53:12 +00:00
|
|
|
test_mode(false), return_state(nullptr) {}
|
2016-04-03 20:08:11 +00:00
|
|
|
|
2016-04-03 19:05:27 +00:00
|
|
|
Game::~Game() {}
|
2016-03-28 17:57:55 +00:00
|
|
|
|
2016-04-09 00:32:11 +00:00
|
|
|
void Game::begin() {
|
|
|
|
Level::begin();
|
2016-04-10 00:11:37 +00:00
|
|
|
|
|
|
|
mode = Game::Mode::NORMAL;
|
2016-04-09 02:36:30 +00:00
|
|
|
getWindow().setFramerateLimit(0);
|
2016-04-05 18:07:58 +00:00
|
|
|
}
|
|
|
|
|
2016-04-09 21:57:23 +00:00
|
|
|
void Game::processEvent(const sf::Event& event) {
|
|
|
|
Level::processEvent(event);
|
|
|
|
|
2016-04-10 00:11:37 +00:00
|
|
|
if (event.type == sf::Event::KeyPressed) {
|
|
|
|
// appui sur espace en mode test : retour à l'éditeur
|
|
|
|
if (event.key.code == sf::Keyboard::Space && test_mode) {
|
|
|
|
test_mode = false;
|
|
|
|
getManager().setState(return_state);
|
2016-04-10 04:53:31 +00:00
|
|
|
return_state = nullptr;
|
2016-04-10 00:11:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// appui sur échap : échange entre le mode pause et normal
|
|
|
|
if (event.key.code == sf::Keyboard::Escape) {
|
|
|
|
if (mode == Game::Mode::NORMAL) {
|
|
|
|
mode = Game::Mode::PAUSED;
|
|
|
|
} else if (mode == Game::Mode::PAUSED) {
|
|
|
|
mode = Game::Mode::NORMAL;
|
|
|
|
}
|
|
|
|
}
|
2016-04-09 21:57:23 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-09 00:32:11 +00:00
|
|
|
|
2016-04-09 21:57:23 +00:00
|
|
|
void Game::frame() {
|
2016-04-09 00:32:11 +00:00
|
|
|
// titre de la fenêtre
|
2016-04-09 02:36:30 +00:00
|
|
|
getManager().setTitle(getName());
|
|
|
|
sf::Time current_time = getManager().getCurrentTime();
|
2016-04-07 22:19:01 +00:00
|
|
|
|
2016-04-03 18:19:48 +00:00
|
|
|
if (current_time >= next_frame_time) {
|
|
|
|
// si nous sommes en retard ou dans les temps
|
|
|
|
// on replanifie la prochaine frame
|
2016-04-10 02:47:02 +00:00
|
|
|
next_frame_time += Manager::FRAME_TIME;
|
2016-04-03 18:19:48 +00:00
|
|
|
|
2016-04-10 00:11:37 +00:00
|
|
|
// on met à jour la physique d'un cran temporel,
|
|
|
|
// si on est en mode normal
|
|
|
|
if (mode == Game::Mode::NORMAL) {
|
|
|
|
update();
|
|
|
|
}
|
2016-03-04 15:29:31 +00:00
|
|
|
|
2016-04-10 00:11:37 +00:00
|
|
|
// on s'assure que la caméra soit centrée sur nos joueurs
|
2016-04-08 22:26:47 +00:00
|
|
|
ensureCentered();
|
2016-04-08 13:53:30 +00:00
|
|
|
|
2016-04-03 18:19:48 +00:00
|
|
|
// si on a encore suffisamment de temps, on dessine
|
|
|
|
if (current_time < next_frame_time) {
|
|
|
|
draw();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// si nous sommes en avance, on endort le processus
|
|
|
|
// le temps nécessaire pour revenir dans les temps
|
|
|
|
sf::sleep(next_frame_time - current_time);
|
|
|
|
}
|
2016-04-07 22:19:01 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 13:21:46 +00:00
|
|
|
void Game::draw() {
|
2016-04-09 02:36:30 +00:00
|
|
|
sf::Vector2i window_size = (sf::Vector2i) getWindow().getSize();
|
2016-04-06 13:21:46 +00:00
|
|
|
|
2016-04-08 00:35:17 +00:00
|
|
|
// dessin des objets du niveau
|
|
|
|
Level::draw();
|
2016-04-06 13:21:46 +00:00
|
|
|
|
2016-04-08 00:35:17 +00:00
|
|
|
// dessin du timer
|
2016-04-06 13:21:46 +00:00
|
|
|
widget_timer.setTimeLeft(getTotalTime());
|
2016-04-08 00:35:17 +00:00
|
|
|
widget_timer.draw(sf::Vector2f(window_size.x / 2 - 50, 0));
|
2016-04-06 13:21:46 +00:00
|
|
|
}
|
|
|
|
|
2016-04-08 22:26:47 +00:00
|
|
|
void Game::ensureCentered() {
|
|
|
|
std::vector<ObjectPtr>& objects = getObjects();
|
|
|
|
|
|
|
|
sf::Vector2f total_position;
|
|
|
|
int player_count = 0;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < objects.size(); i++) {
|
|
|
|
if (Player* player = dynamic_cast<Player*>(objects[i].get())) {
|
|
|
|
total_position += player->getPosition();
|
|
|
|
player_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sf::View camera = getCamera();
|
2016-04-10 04:53:31 +00:00
|
|
|
|
|
|
|
if (player_count == 0) {
|
|
|
|
// on évite la division par zéro
|
|
|
|
camera.setCenter(sf::Vector2f(0, 0));
|
|
|
|
} else {
|
|
|
|
// on place la caméra à la position médiane de tous les joueurs
|
|
|
|
camera.setCenter(total_position / (float) player_count);
|
|
|
|
}
|
|
|
|
|
2016-04-08 22:26:47 +00:00
|
|
|
setCamera(camera);
|
|
|
|
}
|
|
|
|
|
2016-03-30 12:03:52 +00:00
|
|
|
void Game::update() {
|
2016-03-28 00:03:56 +00:00
|
|
|
std::vector<CollisionData> colliding;
|
|
|
|
|
|
|
|
// détection des objets en collision
|
2016-04-03 19:05:27 +00:00
|
|
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
2016-04-09 13:32:42 +00:00
|
|
|
ObjectPtr obj_a = getObjects()[i];
|
2016-03-13 18:07:35 +00:00
|
|
|
|
2016-04-03 19:05:27 +00:00
|
|
|
for (unsigned int j = i + 1; j < getObjects().size(); j++) {
|
2016-04-09 13:32:42 +00:00
|
|
|
ObjectPtr obj_b = getObjects()[j];
|
|
|
|
CollisionData data(*obj_a, *obj_b);
|
2016-03-28 00:03:56 +00:00
|
|
|
|
2016-04-09 13:32:42 +00:00
|
|
|
if (obj_a->detectCollision(*obj_b, data)) {
|
2016-03-28 00:03:56 +00:00
|
|
|
colliding.push_back(data);
|
|
|
|
}
|
2016-03-13 18:07:35 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-27 21:43:05 +00:00
|
|
|
|
2016-04-08 13:53:30 +00:00
|
|
|
// intégration des forces dans la vitesse (seconde moitié)
|
2016-04-03 19:05:27 +00:00
|
|
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
2016-04-09 02:36:30 +00:00
|
|
|
getObjects()[i]->updateVelocity(*this);
|
2016-03-27 21:43:05 +00:00
|
|
|
}
|
|
|
|
|
2016-03-28 00:03:56 +00:00
|
|
|
// résolution des collisions détectées
|
|
|
|
for (unsigned int i = 0; i < colliding.size(); i++) {
|
|
|
|
CollisionData& collided = colliding[i];
|
2016-04-09 13:32:42 +00:00
|
|
|
collided.obj_a.solveCollision(*this, collided.obj_b, collided.normal);
|
2016-03-28 00:03:56 +00:00
|
|
|
}
|
|
|
|
|
2016-03-27 21:43:05 +00:00
|
|
|
// intégration de la vitesse dans la position
|
2016-04-03 19:05:27 +00:00
|
|
|
for (unsigned int i = 0; i < getObjects().size(); i++) {
|
2016-04-09 02:36:30 +00:00
|
|
|
getObjects()[i]->updatePosition();
|
2016-03-27 21:43:05 +00:00
|
|
|
}
|
|
|
|
|
2016-03-28 00:03:56 +00:00
|
|
|
// application de la correction positionnelle
|
|
|
|
for (unsigned int i = 0; i < colliding.size(); i++) {
|
|
|
|
CollisionData& collided = colliding[i];
|
2016-04-09 13:32:42 +00:00
|
|
|
collided.obj_a.positionalCorrection(
|
|
|
|
collided.obj_b, collided.normal, collided.depth
|
2016-03-28 00:03:56 +00:00
|
|
|
);
|
|
|
|
}
|
2016-03-04 15:29:31 +00:00
|
|
|
}
|
2016-04-05 23:13:00 +00:00
|
|
|
|
2016-04-10 00:11:37 +00:00
|
|
|
bool Game::getTestMode() {
|
|
|
|
return test_mode;
|
|
|
|
}
|
|
|
|
|
2016-04-09 13:53:12 +00:00
|
|
|
void Game::setTestMode(std::shared_ptr<State> set_return_state) {
|
|
|
|
return_state = set_return_state;
|
2016-04-05 23:13:00 +00:00
|
|
|
test_mode = true;
|
|
|
|
}
|
2016-04-10 00:11:37 +00:00
|
|
|
|
|
|
|
Game::Mode Game::getMode() {
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Game::setMode(Game::Mode set_mode) {
|
|
|
|
mode = set_mode;
|
|
|
|
}
|