#include "engine.hpp" #include #include Engine::Engine() : window( sf::VideoMode(400, 300), "Projet CMI", sf::Style::Default & ~sf::Style::Resize, sf::ContextSettings(0, 0, 2) ) { window.setVerticalSyncEnabled(true); } void Engine::start() { // boucle d'événements sur la fenêtre while (window.isOpen()) { sf::Event event; // traitement des évènements reçus while (window.pollEvent(event)) { // fermeture de la fenêtre if (event.type == sf::Event::Closed) { window.close(); } // suivi de l'enfoncement et du relâchement des touches if (event.type == sf::Event::KeyPressed) { state.keys[event.key.code] = true; } if (event.type == sf::Event::KeyReleased) { state.keys[event.key.code] = false; } } state.delta = clock.restart().asSeconds(); update(); draw(); } } void Engine::addObject(Object& object) { state.objects.push_back(&object); } void Engine::update() { // demande la mise à jour de tous les objets du jeu for (unsigned int i = 0; i < state.objects.size(); i++) { state.objects[i]->update(state); } // gère les collisions entre les objets for (unsigned int i = 0; i < state.objects.size(); i++) { Object* objA = state.objects[i]; for (unsigned int j = i + 1; j < state.objects.size(); j++) { Object* objB = state.objects[j]; // si les objets ne sont pas sur la même couche, // ils ne peuvent pas entrer en collision if (objA->getLayer() != objB->getLayer()) { continue; } // si les deux boîtes englobantes des deux objets, // il ne risque pas d'y avoir de collision if (!objA->getAABB()->intersects(*objB->getAABB())) { continue; } sf::Vector2f normal; // vérifie plus finement s'il y a collision et // calcule la normale if (!objA->getNormal(*objB, normal)) { continue; } sf::Vector2f codir = objB->getVelocity() - objA->getVelocity(); float dotnormal = codir.x * normal.x + codir.y * normal.y; // si les directions sont divergentes, pas besoin // de résoudre la collision if (dotnormal >= 0) { continue; } float restitution = std::min(objA->getRestitution(), objB->getRestitution()); // calcul de l'inverse des masses de A et B. Pour rappel, // une masse infinie est modélisée par 0, donc l'inverse // d'une telle masse est nul float invMassA = objA->getMass(); float invMassB = objB->getMass(); if (invMassA != 0) { invMassA = 1.f / invMassA; } if (invMassB != 0) { invMassB = 1.f / invMassB; } // calcule et applique l'impulsion de résolution de la collision float impulse = (-(1 + restitution) * dotnormal) / (invMassA + invMassB); objA->setVelocity(objA->getVelocity() - invMassA * impulse * normal); objB->setVelocity(objB->getVelocity() + invMassB * impulse * normal); } } } void Engine::draw() { // efface la scène précédente et dessine la couche de fond window.clear(sf::Color(66, 165, 245)); // chargement de la file d'affichage des objets std::priority_queue, ObjectCompare> display_queue; for (unsigned int i = 0; i < state.objects.size(); i++) { display_queue.push(state.objects[i]); } // dessin des objets de la file d'affichage couche par couche while (!display_queue.empty()) { display_queue.top()->draw(window); display_queue.pop(); } window.display(); }