Merge branch 'master' of https://github.com/matteodelabre/projet-cmi
This commit is contained in:
commit
328ccb40a2
|
@ -0,0 +1,18 @@
|
||||||
|
# Vendredi 25 Mars - Cours Projet CMI -
|
||||||
|
|
||||||
|
## Compte-rendu de la semaine
|
||||||
|
|
||||||
|
* Rémi : affinage des constantes, recherche de bugs du moteur
|
||||||
|
* Maëlle : mise en place de la caméra, conception initiale des textures, musiques
|
||||||
|
* Mattéo : correction des collisions et du moteur physique en général
|
||||||
|
|
||||||
|
## Ce jour
|
||||||
|
|
||||||
|
* Correction d'un bug de collisions.
|
||||||
|
* Recherche d'autres bugs.
|
||||||
|
* Distinction des deux joueurs.
|
||||||
|
* Conception (sur papier) des niveaux.
|
||||||
|
|
||||||
|
## Répartition des tâches
|
||||||
|
|
||||||
|
Cf. Gant.
|
|
@ -2,7 +2,6 @@
|
||||||
#define __PTF_BLOCK_HPP__
|
#define __PTF_BLOCK_HPP__
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
#include <iostream>
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "engine_state.hpp"
|
#include "engine_state.hpp"
|
||||||
|
|
||||||
|
@ -24,13 +23,10 @@ public:
|
||||||
std::unique_ptr<sf::FloatRect> getAABB();
|
std::unique_ptr<sf::FloatRect> getAABB();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcule les informations sur une éventuelle collision de
|
* Récupère l'identifiant de type de cet objet
|
||||||
* cet objet avec un autre : la normale et la profondeur
|
|
||||||
*/
|
*/
|
||||||
virtual bool getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth);
|
static constexpr unsigned int TYPE_ID = 1;
|
||||||
virtual bool getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth);
|
unsigned int getTypeId();
|
||||||
virtual bool getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef __PTF_COLLISION_HPP__
|
||||||
|
#define __PTF_COLLISION_HPP__
|
||||||
|
|
||||||
|
#include "object.hpp"
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Collision {
|
||||||
|
typedef bool (*collision_data)(Object&, Object&, sf::Vector2f&, float&);
|
||||||
|
typedef std::map<std::pair<unsigned int, unsigned int>, collision_data> collision_dispatcher;
|
||||||
|
extern collision_dispatcher dispatch;
|
||||||
|
|
||||||
|
bool playerToBlock(Object& objA, Object& objB, sf::Vector2f& normal, float& depth);
|
||||||
|
bool blockToPlayer(Object& objA, Object& objB, sf::Vector2f& normal, float& depth);
|
||||||
|
bool playerToPlayer(Object& objA, Object& objB, sf::Vector2f& normal, float& depth);
|
||||||
|
bool blockToBlock(Object& objA, Object& objB, sf::Vector2f& normal, float& depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -52,12 +52,9 @@ public:
|
||||||
virtual std::unique_ptr<sf::FloatRect> getAABB() = 0;
|
virtual std::unique_ptr<sf::FloatRect> getAABB() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcule les informations sur une éventuelle collision de
|
* Récupère l'identifiant de type de cet objet
|
||||||
* cet objet avec un autre : la normale et la profondeur
|
|
||||||
*/
|
*/
|
||||||
virtual bool getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth);
|
virtual unsigned int getTypeId() = 0;
|
||||||
virtual bool getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth) = 0;
|
|
||||||
virtual bool getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Détecte s'il y a collision entre cet objet
|
* Détecte s'il y a collision entre cet objet
|
||||||
|
@ -169,4 +166,3 @@ struct ObjectCompare {
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,10 @@ public:
|
||||||
std::unique_ptr<sf::FloatRect> getAABB();
|
std::unique_ptr<sf::FloatRect> getAABB();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcule les informations sur une éventuelle collision de
|
* Récupère l'identifiant de type de cet objet
|
||||||
* cet objet avec un autre : la normale et la profondeur
|
|
||||||
*/
|
*/
|
||||||
virtual bool getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth);
|
static constexpr unsigned int TYPE_ID = 0;
|
||||||
virtual bool getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth);
|
unsigned int getTypeId();
|
||||||
virtual bool getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renvoie le rayon de la balle
|
* Renvoie le rayon de la balle
|
||||||
|
@ -50,7 +48,6 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifie le numéro du joueur
|
* Modifie le numéro du joueur
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void setPlayerNumber(unsigned int set_number);
|
void setPlayerNumber(unsigned int set_number);
|
||||||
};
|
};
|
||||||
|
|
BIN
res/ball.bmp
BIN
res/ball.bmp
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
BIN
res/block.bmp
BIN
res/block.bmp
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
Binary file not shown.
|
@ -39,52 +39,6 @@ std::unique_ptr<sf::FloatRect> Block::getAABB() {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Block::getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth) {
|
unsigned int Block::getTypeId() {
|
||||||
return obj.getCollisionInfo(*this, normal, depth);
|
return Block::TYPE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Block::getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth) {
|
|
||||||
// la collision Block -> Player est la collision Player -> Block
|
|
||||||
// avec une normale de collision retournée
|
|
||||||
bool result = obj.getCollisionInfo(*this, normal, depth);
|
|
||||||
normal *= -1.f;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Block::getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth) {
|
|
||||||
std::unique_ptr<sf::FloatRect> aabb = getAABB();
|
|
||||||
std::unique_ptr<sf::FloatRect> obj_aabb = obj.getAABB();
|
|
||||||
sf::Vector2f relpos = getPosition() - obj.getPosition();
|
|
||||||
|
|
||||||
float overlap_x = aabb->width / 2 + obj_aabb->width / 2 - std::abs(relpos.x);
|
|
||||||
float overlap_y = aabb->height / 2 + obj_aabb->height / 2 - std::abs(relpos.y);
|
|
||||||
|
|
||||||
// si il n'y a pas de chauvauchement sur l'axe X et Y, pas de collision
|
|
||||||
if (overlap_x <= 0 || overlap_y <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// on choisit l'axe de pénétration maximale pour calculer la normale
|
|
||||||
if (overlap_x < overlap_y) {
|
|
||||||
if (relpos.x < 0) {
|
|
||||||
normal.x = -1;
|
|
||||||
} else {
|
|
||||||
normal.x = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
normal.y = 0;
|
|
||||||
depth = overlap_x;
|
|
||||||
} else {
|
|
||||||
if (relpos.y < 0) {
|
|
||||||
normal.y = -1;
|
|
||||||
} else {
|
|
||||||
normal.y = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
normal.x = 0;
|
|
||||||
depth = overlap_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
#include "collision.hpp"
|
||||||
|
#include "player.hpp"
|
||||||
|
#include "block.hpp"
|
||||||
|
#include "object.hpp"
|
||||||
|
#include <utility>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace Collision {
|
||||||
|
// initialisation du dictionnaire associant les types
|
||||||
|
// impliqués dans une collision à leur fonction de résolution
|
||||||
|
collision_dispatcher dispatch = {
|
||||||
|
{std::make_pair(Player::TYPE_ID, Block::TYPE_ID), &playerToBlock},
|
||||||
|
{std::make_pair(Block::TYPE_ID, Player::TYPE_ID), &blockToPlayer},
|
||||||
|
{std::make_pair(Player::TYPE_ID, Player::TYPE_ID), &playerToPlayer},
|
||||||
|
{std::make_pair(Block::TYPE_ID, Block::TYPE_ID), &blockToBlock}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool playerToBlock(Object& objA, Object& objB, sf::Vector2f& normal, float& depth) {
|
||||||
|
Player player = dynamic_cast<Player&>(objA);
|
||||||
|
Block block = dynamic_cast<Block&>(objB);
|
||||||
|
|
||||||
|
// recherche du point le plus proche du centre de la
|
||||||
|
// balle sur le bloc. On regarde la position relative
|
||||||
|
// du cercle par rapport au bloc
|
||||||
|
std::unique_ptr<sf::FloatRect> aabb = block.getAABB();
|
||||||
|
sf::Vector2f relpos = block.getPosition() - player.getPosition();
|
||||||
|
sf::Vector2f closest = relpos;
|
||||||
|
|
||||||
|
// on restreint la position relative pour rester
|
||||||
|
// à l'intérieur du bloc
|
||||||
|
if (closest.x < -aabb->width / 2) {
|
||||||
|
closest.x = -aabb->width / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest.x > aabb->width / 2) {
|
||||||
|
closest.x = aabb->width / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest.y < -aabb->height / 2) {
|
||||||
|
closest.y = -aabb->height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest.y > aabb->height / 2) {
|
||||||
|
closest.y = aabb->height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// si la position n'a pas été changée, elle
|
||||||
|
// était déjà à l'intérieur du cercle : le cercle
|
||||||
|
// est dans le bloc
|
||||||
|
float isInside = false;
|
||||||
|
|
||||||
|
if (relpos == closest) {
|
||||||
|
isInside = true;
|
||||||
|
|
||||||
|
// on se colle au bord le plus proche du bloc
|
||||||
|
if (std::abs(relpos.x) > std::abs(relpos.y)) {
|
||||||
|
if (closest.x > 0) {
|
||||||
|
closest.x = aabb->width / 2;
|
||||||
|
} else {
|
||||||
|
closest.x = -aabb->width / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (closest.y > 0) {
|
||||||
|
closest.y = aabb->height / 2;
|
||||||
|
} else {
|
||||||
|
closest.y = -aabb->height / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// la normale est portée par la direction
|
||||||
|
// du point le plus proche au centre de la balle
|
||||||
|
sf::Vector2f prenormal = relpos - closest;
|
||||||
|
float squaredLength = prenormal.x * prenormal.x + prenormal.y * prenormal.y;
|
||||||
|
|
||||||
|
// si la balle est à l'extérieur et que
|
||||||
|
// la normale est plus longue que son rayon,
|
||||||
|
// il n'y a pas collision
|
||||||
|
if (!isInside && squaredLength >= player.getRadius() * player.getRadius()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float length = std::sqrt(squaredLength);
|
||||||
|
depth = player.getRadius() - length;
|
||||||
|
|
||||||
|
if (length != 0) {
|
||||||
|
normal = prenormal / length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInside) {
|
||||||
|
normal *= -1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool blockToPlayer(Object& objA, Object& objB, sf::Vector2f& normal, float& depth) {
|
||||||
|
// la collision Block -> Player est la collision Player -> Block
|
||||||
|
// avec une normale de collision retournée
|
||||||
|
bool result = playerToBlock(objB, objA, normal, depth);
|
||||||
|
normal *= -1.f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool playerToPlayer(Object& objA, Object& objB, sf::Vector2f& normal, float& depth) {
|
||||||
|
Player playerA = dynamic_cast<Player&>(objA);
|
||||||
|
Player playerB = dynamic_cast<Player&>(objB);
|
||||||
|
|
||||||
|
sf::Vector2f dir = playerB.getPosition() - playerA.getPosition();
|
||||||
|
float squaredLength = dir.x * dir.x + dir.y * dir.y;
|
||||||
|
float totalRadius = playerB.getRadius() + playerA.getRadius();
|
||||||
|
|
||||||
|
// si les deux balles sont à une distance supérieure
|
||||||
|
// à la somme de leurs deux rayons, il n'y a pas eu collision
|
||||||
|
if (squaredLength > totalRadius * totalRadius) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float length = std::sqrt(squaredLength);
|
||||||
|
|
||||||
|
// les balles sont sur la même position.
|
||||||
|
// Renvoie une normale apte à séparer les deux balles
|
||||||
|
if (length == 0) {
|
||||||
|
depth = totalRadius;
|
||||||
|
normal.x = 0;
|
||||||
|
normal.y = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// il y a eu collision
|
||||||
|
depth = totalRadius - length;
|
||||||
|
normal = dir / length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool blockToBlock(Object& objA, Object& objB, sf::Vector2f& normal, float& depth) {
|
||||||
|
Block blockA = dynamic_cast<Block&>(objA);
|
||||||
|
Block blockB = dynamic_cast<Block&>(objB);
|
||||||
|
|
||||||
|
std::unique_ptr<sf::FloatRect> aabb = blockA.getAABB();
|
||||||
|
std::unique_ptr<sf::FloatRect> obj_aabb = blockB.getAABB();
|
||||||
|
sf::Vector2f relpos = blockB.getPosition() - blockA.getPosition();
|
||||||
|
|
||||||
|
float overlap_x = aabb->width / 2 + obj_aabb->width / 2 - std::abs(relpos.x);
|
||||||
|
float overlap_y = aabb->height / 2 + obj_aabb->height / 2 - std::abs(relpos.y);
|
||||||
|
|
||||||
|
// si il n'y a pas de chauvauchement sur l'axe X et Y, pas de collision
|
||||||
|
if (overlap_x <= 0 || overlap_y <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on choisit l'axe de pénétration maximale pour calculer la normale
|
||||||
|
if (overlap_x < overlap_y) {
|
||||||
|
if (relpos.x < 0) {
|
||||||
|
normal.x = -1;
|
||||||
|
} else {
|
||||||
|
normal.x = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
normal.y = 0;
|
||||||
|
depth = overlap_x;
|
||||||
|
} else {
|
||||||
|
if (relpos.y < 0) {
|
||||||
|
normal.y = -1;
|
||||||
|
} else {
|
||||||
|
normal.y = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
normal.x = 0;
|
||||||
|
depth = overlap_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,9 +43,10 @@ void Engine::start() {
|
||||||
if (event.type == sf::Event::KeyReleased) {
|
if (event.type == sf::Event::KeyReleased) {
|
||||||
state.keys[event.key.code] = false;
|
state.keys[event.key.code] = false;
|
||||||
}
|
}
|
||||||
// lorsque la fenêtre est redimensionnée par l'utilisateur
|
|
||||||
if (event.type == sf::Event::Resized){
|
// lorsque la fenêtre est redimensionnée par l'utilisateur,
|
||||||
// mise à jour de la caméra en fonction de la taille de la fenêtre
|
// mise à jour de la caméra en fonction de la taille de la fenêtre
|
||||||
|
if (event.type == sf::Event::Resized) {
|
||||||
sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
|
sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
|
||||||
window.setView(sf::View(visibleArea));
|
window.setView(sf::View(visibleArea));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
|
#include "collision.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
Object::Object(float x, float y) :
|
Object::Object(float x, float y) :
|
||||||
|
@ -75,16 +75,12 @@ void Object::draw(sf::RenderWindow& window, ResourceManager& resources) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::update(EngineState& state) {
|
void Object::update(EngineState& state) {
|
||||||
// intégration de la vitesse dans la position
|
|
||||||
position += velocity * Constants::PHYSICS_TIME;
|
|
||||||
|
|
||||||
// intégration des forces appliquées sur l'objet dans la vitesse
|
// intégration des forces appliquées sur l'objet dans la vitesse
|
||||||
acceleration = getForces(state) * getMassInvert();
|
acceleration = getForces(state) * getMassInvert();
|
||||||
velocity += acceleration * Constants::PHYSICS_TIME;
|
velocity += acceleration * Constants::PHYSICS_TIME;
|
||||||
}
|
|
||||||
|
|
||||||
bool Object::getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth) {
|
// intégration de la vitesse dans la position
|
||||||
return obj.getCollisionInfo(*this, normal, depth);
|
position += velocity * Constants::PHYSICS_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::collide(Object& obj) {
|
void Object::collide(Object& obj) {
|
||||||
|
@ -105,7 +101,7 @@ void Object::collide(Object& obj) {
|
||||||
|
|
||||||
// vérifie plus finement s'il y a collision et récupère
|
// vérifie plus finement s'il y a collision et récupère
|
||||||
// les informations sur la collision (normale et profondeur)
|
// les informations sur la collision (normale et profondeur)
|
||||||
if (!getCollisionInfo(obj, normal, depth)) {
|
if (!Collision::dispatch[std::make_pair(getTypeId(), obj.getTypeId())](*this, obj, normal, depth)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
136
src/player.cpp
136
src/player.cpp
|
@ -9,20 +9,11 @@ Player::Player(float x, float y) : Object(x, y) {
|
||||||
sprite.setOrigin(sf::Vector2f(getRadius(), getRadius()));
|
sprite.setOrigin(sf::Vector2f(getRadius(), getRadius()));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Player::getPlayerNumber(){
|
|
||||||
return player_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::setPlayerNumber(unsigned int set_number){
|
|
||||||
player_number = set_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Vector2f Player::getForces(EngineState& state) {
|
sf::Vector2f Player::getForces(EngineState& state) {
|
||||||
sf::Vector2f forces = Object::getForces(state);
|
sf::Vector2f forces = Object::getForces(state);
|
||||||
|
|
||||||
//commandes du joueur 1
|
|
||||||
if(player_number==1){
|
|
||||||
// déplacement de la balle après appui sur les touches de direction
|
// déplacement de la balle après appui sur les touches de direction
|
||||||
|
if (getPlayerNumber() == 1) {
|
||||||
if (state.keys[sf::Keyboard::Left]) {
|
if (state.keys[sf::Keyboard::Left]) {
|
||||||
forces += sf::Vector2f(-Constants::MOVE, 0);
|
forces += sf::Vector2f(-Constants::MOVE, 0);
|
||||||
}
|
}
|
||||||
|
@ -31,12 +22,13 @@ sf::Vector2f Player::getForces(EngineState& state) {
|
||||||
forces += sf::Vector2f(Constants::MOVE, 0);
|
forces += sf::Vector2f(Constants::MOVE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
if(state.keys[sf::Keyboard::Q]){
|
if (getPlayerNumber() == 2) {
|
||||||
|
if (state.keys[sf::Keyboard::Q]) {
|
||||||
forces += sf::Vector2f(-Constants::MOVE, 0);
|
forces += sf::Vector2f(-Constants::MOVE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.keys[sf::Keyboard::D]){
|
if (state.keys[sf::Keyboard::D]) {
|
||||||
forces += sf::Vector2f(Constants::MOVE, 0);
|
forces += sf::Vector2f(Constants::MOVE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +40,7 @@ void Player::draw(sf::RenderWindow& window, ResourceManager& resources) {
|
||||||
Object::draw(window, resources);
|
Object::draw(window, resources);
|
||||||
|
|
||||||
// utilisation de la texture
|
// utilisation de la texture
|
||||||
sprite.setTexture(resources.getTexture("ball.bmp"));
|
sprite.setTexture(resources.getTexture("ball.png"));
|
||||||
|
|
||||||
// déplacement du sprite à la position de la balle
|
// déplacement du sprite à la position de la balle
|
||||||
sprite.rotate(getVelocity().x * .1f);
|
sprite.rotate(getVelocity().x * .1f);
|
||||||
|
@ -64,114 +56,18 @@ std::unique_ptr<sf::FloatRect> Player::getAABB() {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth) {
|
unsigned int Player::getTypeId() {
|
||||||
return obj.getCollisionInfo(*this, normal, depth);
|
return Player::TYPE_ID;
|
||||||
}
|
|
||||||
|
|
||||||
bool Player::getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth) {
|
|
||||||
sf::Vector2f dir = getPosition() - obj.getPosition();
|
|
||||||
float squaredLength = dir.x * dir.x + dir.y * dir.y;
|
|
||||||
float totalRadius = getRadius() + obj.getRadius();
|
|
||||||
|
|
||||||
// si les deux balles sont à une distance supérieure
|
|
||||||
// à la somme de leurs deux rayons, il n'y a pas eu collision
|
|
||||||
if (squaredLength > totalRadius * totalRadius) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float length = std::sqrt(squaredLength);
|
|
||||||
|
|
||||||
// les balles sont sur la même position.
|
|
||||||
// Renvoie une normale apte à séparer les deux balles
|
|
||||||
if (length == 0) {
|
|
||||||
depth = totalRadius;
|
|
||||||
normal.x = 0;
|
|
||||||
normal.y = -1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// il y a eu collision
|
|
||||||
depth = totalRadius - length;
|
|
||||||
normal = dir / length;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Player::getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth) {
|
|
||||||
// recherche du point le plus proche du centre de la
|
|
||||||
// balle sur le bloc. On regarde la position relative
|
|
||||||
// du cercle par rapport au bloc
|
|
||||||
std::unique_ptr<sf::FloatRect> aabb = obj.getAABB();
|
|
||||||
sf::Vector2f relpos = getPosition() - obj.getPosition();
|
|
||||||
sf::Vector2f closest = relpos;
|
|
||||||
|
|
||||||
// on restreint la position relative pour rester
|
|
||||||
// à l'intérieur du bloc
|
|
||||||
if (closest.x < -aabb->width / 2) {
|
|
||||||
closest.x = -aabb->width / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closest.x > aabb->width / 2) {
|
|
||||||
closest.x = aabb->width / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closest.y < -aabb->height / 2) {
|
|
||||||
closest.y = -aabb->height / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closest.y > aabb->height / 2) {
|
|
||||||
closest.y = aabb->height / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// si la position n'a pas été changée, elle
|
|
||||||
// était déjà à l'intérieur du cercle : le cercle
|
|
||||||
// est dans le bloc
|
|
||||||
float isInside = false;
|
|
||||||
|
|
||||||
if (relpos == closest) {
|
|
||||||
isInside = true;
|
|
||||||
|
|
||||||
// on se colle au bord le plus proche du bloc
|
|
||||||
if (std::abs(relpos.x) > std::abs(relpos.y)) {
|
|
||||||
if (closest.x > 0) {
|
|
||||||
closest.x = aabb->width / 2;
|
|
||||||
} else {
|
|
||||||
closest.x = -aabb->width / 2;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (closest.y > 0) {
|
|
||||||
closest.y = aabb->height / 2;
|
|
||||||
} else {
|
|
||||||
closest.y = -aabb->height / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// la normale est portée par la direction
|
|
||||||
// du point le plus proche au centre de la balle
|
|
||||||
sf::Vector2f prenormal = relpos - closest;
|
|
||||||
float squaredLength = prenormal.x * prenormal.x + prenormal.y * prenormal.y;
|
|
||||||
|
|
||||||
// si la balle est à l'extérieur et que
|
|
||||||
// la normale est plus longue que son rayon,
|
|
||||||
// il n'y a pas collision
|
|
||||||
if (!isInside && squaredLength >= getRadius() * getRadius()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float length = std::sqrt(squaredLength);
|
|
||||||
depth = getRadius() - length;
|
|
||||||
|
|
||||||
if (length != 0) {
|
|
||||||
normal = prenormal / length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInside) {
|
|
||||||
normal *= -1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Player::getRadius() {
|
float Player::getRadius() {
|
||||||
return 10 * getMass();
|
return 10 * getMass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Player::getPlayerNumber() {
|
||||||
|
return player_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::setPlayerNumber(unsigned int set_number) {
|
||||||
|
player_number = set_number;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue