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__ | ||||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include <iostream> | ||||
| #include "object.hpp" | ||||
| #include "engine_state.hpp" | ||||
| 
 | ||||
|  | @ -24,13 +23,10 @@ public: | |||
|     std::unique_ptr<sf::FloatRect> getAABB(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Calcule les informations sur une éventuelle collision de | ||||
|      * cet objet avec un autre : la normale et la profondeur | ||||
|      * Récupère l'identifiant de type de cet objet | ||||
|      */ | ||||
|     virtual bool getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth); | ||||
|     virtual bool getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth); | ||||
|     virtual bool getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth); | ||||
|     static constexpr unsigned int TYPE_ID = 1; | ||||
|     unsigned int getTypeId(); | ||||
| }; | ||||
| 
 | ||||
| #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; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Calcule les informations sur une éventuelle collision de | ||||
|      * cet objet avec un autre : la normale et la profondeur | ||||
|      * Récupère l'identifiant de type de cet objet | ||||
|      */ | ||||
|     virtual bool getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth); | ||||
|     virtual bool getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth) = 0; | ||||
|     virtual bool getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth) = 0; | ||||
|     virtual unsigned int getTypeId() = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Détecte s'il y a collision entre cet objet | ||||
|  | @ -169,4 +166,3 @@ struct ObjectCompare { | |||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,18 +31,16 @@ public: | |||
|     std::unique_ptr<sf::FloatRect> getAABB(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Calcule les informations sur une éventuelle collision de | ||||
|      * cet objet avec un autre : la normale et la profondeur | ||||
|      * Récupère l'identifiant de type de cet objet | ||||
|      */ | ||||
|     virtual bool getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth); | ||||
|     virtual bool getCollisionInfo(Player& obj, sf::Vector2f& normal, float& depth); | ||||
|     virtual bool getCollisionInfo(Block& obj, sf::Vector2f& normal, float& depth); | ||||
|     static constexpr unsigned int TYPE_ID = 0; | ||||
|     unsigned int getTypeId(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie le rayon de la balle | ||||
|      */ | ||||
|     float getRadius(); | ||||
|      | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie le numéro du joueur | ||||
|      */ | ||||
|  | @ -50,7 +48,6 @@ public: | |||
| 
 | ||||
|     /**
 | ||||
|      * Modifie le numéro du joueur | ||||
|      * | ||||
|      */ | ||||
|     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) { | ||||
|     return obj.getCollisionInfo(*this, normal, depth); | ||||
| unsigned int Block::getTypeId() { | ||||
|     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,12 +43,13 @@ void Engine::start() { | |||
|             if (event.type == sf::Event::KeyReleased) { | ||||
|                 state.keys[event.key.code] = false; | ||||
|             } | ||||
| 			// lorsque la fenêtre est redimensionnée par l'utilisateur
 | ||||
|     		if (event.type == sf::Event::Resized){ | ||||
|        			 // mise à jour de la caméra en fonction de la taille de la fenêtre
 | ||||
|        			 sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); | ||||
|        			 window.setView(sf::View(visibleArea)); | ||||
|   		  	} | ||||
| 
 | ||||
| 			// 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
 | ||||
|     		if (event.type == sf::Event::Resized) { | ||||
|                 sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); | ||||
|                 window.setView(sf::View(visibleArea)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         float frame = clock.restart().asSeconds(); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| 
 | ||||
| #include "object.hpp" | ||||
| #include "constants.hpp" | ||||
| #include "collision.hpp" | ||||
| #include <iostream> | ||||
| 
 | ||||
| Object::Object(float x, float y) : | ||||
|  | @ -75,16 +75,12 @@ void Object::draw(sf::RenderWindow& window, ResourceManager& resources) { | |||
| } | ||||
| 
 | ||||
| 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
 | ||||
|     acceleration = getForces(state) * getMassInvert(); | ||||
|     velocity += acceleration * Constants::PHYSICS_TIME; | ||||
| } | ||||
| 
 | ||||
| bool Object::getCollisionInfo(Object& obj, sf::Vector2f& normal, float& depth) { | ||||
|     return obj.getCollisionInfo(*this, normal, depth); | ||||
|     // intégration de la vitesse dans la position
 | ||||
|     position += velocity * Constants::PHYSICS_TIME; | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|     // 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; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										142
									
								
								src/player.cpp
								
								
								
								
							
							
						
						
									
										142
									
								
								src/player.cpp
								
								
								
								
							|  | @ -9,20 +9,11 @@ Player::Player(float x, float y) : Object(x, y) { | |||
|     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 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]) { | ||||
|             forces += sf::Vector2f(-Constants::MOVE, 0); | ||||
|         } | ||||
|  | @ -31,12 +22,13 @@ sf::Vector2f Player::getForces(EngineState& state) { | |||
|             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); | ||||
|         } | ||||
|          | ||||
|         if(state.keys[sf::Keyboard::D]){ | ||||
| 
 | ||||
|         if (state.keys[sf::Keyboard::D]) { | ||||
|             forces += sf::Vector2f(Constants::MOVE, 0); | ||||
|         } | ||||
|     } | ||||
|  | @ -48,7 +40,7 @@ void Player::draw(sf::RenderWindow& window, ResourceManager& resources) { | |||
|     Object::draw(window, resources); | ||||
| 
 | ||||
|     // 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
 | ||||
|     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) { | ||||
|     return obj.getCollisionInfo(*this, normal, depth); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| unsigned int Player::getTypeId() { | ||||
|     return Player::TYPE_ID; | ||||
| } | ||||
| 
 | ||||
| float Player::getRadius() { | ||||
|     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