skizzle/src/game.cpp

177 lines
4.8 KiB
C++
Raw Normal View History

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
Game::Game(Manager& manager) : Level(manager),
widget_timer(manager, false),
next_frame_time(manager.getCurrentTime()),
test_mode(false), return_state(nullptr) {}
2016-04-03 20:08:11 +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
2016-04-10 15:40:04 +00:00
if (getMusic() != "") {
getResourceManager().playMusic(getMusic());
} else {
getResourceManager().stopMusic();
}
2016-04-10 00:11:37 +00:00
mode = Game::Mode::NORMAL;
getWindow().setFramerateLimit(0);
}
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);
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
getManager().setTitle(getName());
sf::Time current_time = getManager().getCurrentTime();
if (current_time >= next_frame_time) {
// si nous sommes en retard ou dans les temps
// on replanifie la prochaine frame
next_frame_time += Manager::FRAME_TIME;
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
ensureCentered();
2016-04-08 13:53:30 +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);
}
}
void Game::draw() {
sf::Vector2i window_size = (sf::Vector2i) getWindow().getSize();
// dessin des objets du niveau
Level::draw();
// on passe au dessin d'éléments d'interface.
// Changement de vue sur la vue par défaut
getManager().useGUIView();
// dessin du timer
widget_timer.setTimeLeft(getTotalTime());
widget_timer.draw(sf::Vector2f(window_size.x / 2 - 50, 0));
}
void Game::ensureCentered() {
std::vector<Player::Ptr>& players = getPlayers();
sf::Vector2f total_position;
sf::View camera = getCamera();
unsigned int player_count = players.size();
for (unsigned int i = 0; i < player_count; i++) {
total_position += players[i]->getPosition();
}
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);
}
setCamera(camera);
}
2016-03-30 12:03:52 +00:00
void Game::update() {
std::vector<CollisionData> colliding;
std::vector<Object::Ptr>& objects = getObjects();
// détection des objets en collision
for (unsigned int i = 0; i < objects.size(); i++) {
Object::Ptr obj_a = objects[i];
for (unsigned int j = i + 1; j < objects.size(); j++) {
Object::Ptr obj_b = objects[j];
CollisionData data;
data.obj_a = obj_a;
data.obj_b = obj_b;
if (obj_a->detectCollision(obj_b, data)) {
colliding.push_back(data);
}
}
}
2016-04-08 13:53:30 +00:00
// intégration des forces dans la vitesse (seconde moitié)
for (unsigned int i = 0; i < objects.size(); i++) {
objects[i]->updateVelocity(*this);
}
// résolution des collisions détectées
for (unsigned int i = 0; i < colliding.size(); i++) {
CollisionData& collided = colliding[i];
collided.obj_a->solveCollision(*this, collided.obj_b, collided.normal);
}
// intégration de la vitesse dans la position
for (unsigned int i = 0; i < objects.size(); i++) {
objects[i]->updatePosition();
}
// application de la correction positionnelle
for (unsigned int i = 0; i < colliding.size(); i++) {
CollisionData& collided = colliding[i];
collided.obj_a->positionalCorrection(
2016-04-09 13:32:42 +00:00
collided.obj_b, collided.normal, collided.depth
);
}
2016-03-04 15:29:31 +00:00
}
2016-04-10 00:11:37 +00:00
bool Game::getTestMode() {
return test_mode;
}
void Game::setTestMode(std::shared_ptr<State> set_return_state) {
return_state = set_return_state;
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;
}