Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Gestion des collisions  (Lu 4003 fois)

0 Membres et 1 Invité sur ce sujet

Que20

  • Newbie
  • *
  • Messages: 2
    • Voir le profil
Gestion des collisions
« le: Janvier 30, 2016, 08:07:30 pm »
Bonjour !

J'ai décide la semaine passée d'aborder le développement de jeu vidéo 2D et me suis rapidement tourné vers SFML.

Je suis parti sur un Zelda-like.

J'ai réussi à afficher mon personnage, à le faire bouger et également à afficher une map. L'étape suivante est la gestion des collisions. Cela s'avère plus difficile que prévu et je ne sais pas trop comment arriver à gérer ça proprement.

Au début, j'étais parti sur la logique de « si il y n'y a pas de collision, alors on peut bouger » : le gros souci, c'est que mon perso se retrouvait figé dès qu'il entrait en collision avec un autre objet (ce qui était « logique » ^^).

J'ai alors rajouté une condition en plus qui dit que si il y a collision, on fait en sorte que le perso ne puisse avancer que si il n'avance pas dans la direction vers laquelle il est entré en collision (exemple, si mon perso est bas, avance vers le haut et touche un mur, il peut avancer vers la gauche, droite ou le bas mais pas vers le haut).

Voici le code que j'ai actuellement pour les 4 directions de base (je gère aussi les déplacements en diagonales mais je n'ai pas encore ajouté les  détections de collision pour ces déplacements là).

                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                {
                    if(!collision.isInCollision(player.getSprite(), player2.getSprite()))
                    {
                        player.move(0, -4);
                        player.setDirection(UP);
                    }
                    else
                    {
                        if(input.getStateKey(sf::Keyboard::Up) == false)
                        {
                            player.move(0, -4);
                            player.setDirection(UP);                          
                        }
                    }
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                {
                    if(!collision.isInCollision(player.getSprite(), player2.getSprite()))
                    {              
                        player.move(-4, 0);
                        player.setDirection(LEFT);
                    }
                    else
                    {
                        if(input.getStateKey(sf::Keyboard::Left) == false)
                        {
                            player.move(-4, 0);
                            player.setDirection(LEFT);                          
                        }
                    }
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                {
                    if(!collision.isInCollision(player.getSprite(), player2.getSprite()))
                    {  
                        player.move(0, 4);
                        player.setDirection(DOWN);
                    }
                    else
                    {
                        if(input.getStateKey(sf::Keyboard::Down) == false)
                        {
                            player.move(0, 4);
                            player.setDirection(DOWN);                          
                        }
                    }
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                    if(!collision.isInCollision(player.getSprite(), player2.getSprite()))
                    {
                        player.move(4, 0);
                        player.setDirection(RIGHT);
                    }
                    else
                    {
                        if(input.getStateKey(sf::Keyboard::Right) == false)
                        {
                            player.move(4, 0);
                            player.setDirection(RIGHT);                        
                        }
                    }
                }
 

Et ma classe Collision se résume, pour le moment, à ceci :

#ifndef COLLISION_H
#define COLLISION_H

#include <SFML/Graphics.hpp>

class Collision
{
    private:
        sf::FloatRect boundingBox;
        sf::FloatRect otherBox;

    public:
        bool isInCollision(sf::Sprite &sprite1, sf::Sprite &sprite2);
};

#endif

 

Ce n'est pas particulièrement gérable et je me vois mal faire des conditions pour chaque élément avec lequel je peux entrer en collision.

Donc voilà, y a t-il un moyen « simple » (et efficace) de gérer une collision ? Dois je préciser tous les sprites avec lequel mon perso peut rentrer en collision ou peut on « automatiser » cela ?

Merci d'avance. ;-)

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Gestion des collisions
« Réponse #1 le: Janvier 31, 2016, 02:53:04 am »
Il faut que tu teste les intersections , dès lors qu'il y a une intersection , il faut que tu replaces le personnage avant l'intersection & il n'y aura plus d'intersection & tu pourras bougé ton perso :

Lien a voir :

https://openclassrooms.com/courses/theorie-des-collisions
http://loka.developpez.com/tutoriel/sdl/collision/

recherche google : "collision axe séparateur"

Que20

  • Newbie
  • *
  • Messages: 2
    • Voir le profil
Re : Gestion des collisions
« Réponse #2 le: Janvier 31, 2016, 04:33:53 pm »
C'est une possibilité et elle fonctionne mais le seul truc qui me gêne avec cette manière de faire, c'est que le perso « tremble » si on continue dans la même direction (tremblement causé justement par le fait qu'il soit repositionné un pixel avant).

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Gestion des collisions
« Réponse #3 le: Janvier 31, 2016, 08:33:52 pm »
si il tremble, c'est que ton implémentation est foireuse. Pour testé les collision , il faut prendre en compte la vitesse. il ne faut pas testé la position à l'instant T de ton perso, mais la position plus sa vélocité à l'instant T
exemple en 1D : si ton perso est à 15 et que sa vélocité est de 5 , sa position est de 20, si l'obstacle est à 18 , la position est à 18, il y a eu collision.
le mieux est d'implémenté la collision par axe séparateur. le net regorge d'articles divers a se sujet.



Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Gestion des collisions
« Réponse #4 le: Janvier 31, 2016, 10:33:11 pm »
Autre chose que je viens de penser, ta vélocitée ne dois pas être supérieur a l’épaisseur de l'objet qui produit une collision, sinon , mathématiquement, tu passes à travers. la solution, le lancer de rayon & le quadtree, mais on sort du sujet qui sort déjà lui même du forum de part sa question ;)