Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SFML] gestion des collisions avec tilemap

    22 septembre 2017 à 20:44:37

    Bonjour,

    je réalise un projet de jeu avec sfml et j'essaye de gérer les collisions sur ma map.

    Pour cela j'utilise un vector qui contient des objets tile qui dispose chacun d'une énumération qui indique si le personnage peu marcher dessus, en dessous où pas du tous.

    Je vérifie (avant chaque mouvement) que la direction vers laquelle le perso se dirige correspond a un tile dont le type (énumération) indique que le perso peu marché dessus.

    la map est composé de 50x50 tiles de 32px.

    Cependant cela ne semble pas fonctionner :(

    Mon erreur vient elle de ma fonction pour calculer le tile sur lequel ce trouve mon perso ou d'ailleurs?

    Il y t il une meilleur solution pour gérer mes collisions ?

    Main.cpp:

    sf::Vector2f movement(0.f, 0.f);
    		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    		{
    			currentile = currentTileNbr(animatedSprite)-50;
    			if (tabTile[currentile-1].getType() != type::off)
    			{
    				currentAnimation = &walkingAnimationUp;
    				movement.y -= speed;
    				noKeyWasPressed = false;
    			}
    			
    		}
    		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    		{
    			currentile = currentTileNbr(animatedSprite) + 50;
    			if (tabTile[currentile - 1].getType() != type::off)
    			{
    				currentAnimation = &walkingAnimationDown;
    				movement.y += speed;
    				noKeyWasPressed = false;
    			}
    			
    		}
    		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    		{
    			currentile = currentTileNbr(animatedSprite) -1;
    			if (tabTile[currentile - 1].getType() != type::off)
    			{
    				currentAnimation = &walkingAnimationLeft;
    				movement.x -= speed;
    				noKeyWasPressed = false;
    			}
    		}
    		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    		{
    			currentile = currentTileNbr(animatedSprite) + 1;
    			if (tabTile[currentile - 1].getType() != type::off)
    			{
    				currentAnimation = &walkingAnimationRight;
    				movement.x += speed;
    				noKeyWasPressed = false;
    			}
    		}
    		animatedSprite.play(*currentAnimation);
    		animatedSprite.move(movement * frameTime.asSeconds());


    fonction pour connaitre le tile ou se trouve le perso:

    int currentTileNbr(AnimatedSprite animatedSprite)
    {
    	nbrCol = std::ceil((animatedSprite.getPosition().x) / 32);
    	nbrRow = std::ceil((animatedSprite.getPosition().y) / 32);
    	currentile = (((nbrRow) * 50) + (nbrCol));
    	return currentile;
    }



    -
    Edité par Tenkai188 22 septembre 2017 à 20:45:37

    • Partager sur Facebook
    • Partager sur Twitter
      27 septembre 2017 à 17:35:25

      Salut j'ai pas masse compris ton raisonnement mais perso j'ai eu un problème identique il venait du faite que comparer des float ou de double en SFML c'est pas bon du tout ^^ Perso j'ai plus fait de la CSFML (SFML pour du C) et j'ai du faire une zone de détection en gros :

      if (perso.x < tilt.x - 10 && perso.x > tilt.x + 10)
      alors avance

      Bon c'est très grossier mais je voulais te montrer l'idée 

      Si j'ai mal compris ton problème je veux bien plus de détail ^^

      -
      Edité par NutNut tu coco 27 septembre 2017 à 17:36:27

      • Partager sur Facebook
      • Partager sur Twitter
      Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
        27 septembre 2017 à 21:58:59

        En fait, j'essaye de faire un jeux vu du dessus : le perso peut donc se déplacer dans plusieurs directions (haut,bas,gauche,droite et diagonale).

        La carte sur la quel il se déplace est créé de la manière suivante:

        - J'utilise un fichier texte qui contient une suite de nombre qui correspondent chacun a un carré de texture ( du tileset) par exemple le nombre 33 correspond a un carré de rivière.

        std::ifstream monFluxMur("demoMur.txt");
        	std::vector <int> tableauMur;
        	int nombreMur;
        	while (monFluxMur >> nombreMur)
        		tableauMur.push_back(nombreMur);
        	for (int a = 0; a < tableauMur.size(); a++)
        	{
        		tabTile.push_back(Tile(tableauMur[a], tabOn, tabOff, tabBelow));
        	}

        - Je crée avec chaque nombre un objet Tile qui est composé d'un identifiant (le nombre) et une énumération indiquant si le nombre correspond a une texture sur laquel le perso peut marcher (au dessus ou dessous) ou pas. Pour cela j'ai créé 3 vector qui indique les nombres qui corresponde a chaque situation ( exemple: tabOff contient les identifiant des texture sur lequel il ne faut pas marcher)

        Tile.cpp:

        #include "Tile.h"
        Tile::Tile()
        {
        	id = 0;
        	mtype=type::on;
        }
        Tile::Tile(int ide, std::vector<int>tabOn, std::vector<int>tabOff, std::vector<int>tabBelow)
        {
        	id = ide;
        	bool findIt = false;
        
        	for (int b = 0; b < tabOn.size(); b++)
        	{
        		if ((ide == tabOn[b])&&(findIt==false))
        		{
        			mtype = type::on;
        			findIt = true;
        		}
        	}
        	for (int b = 0; b < tabOff.size(); b++)
        	{
        		if ((ide == tabOff[b]) && (findIt == false))
        		{
        			mtype = type::off;
        			findIt = true;
        		}
        	}
        	for (int b = 0; b < tabBelow.size(); b++)
        	{
        		if ((ide == tabBelow[b]) && (findIt == false))
        		{
        			mtype = type::below;
        			findIt = true;
        		}
        	}
        }
        
        Tile::~Tile()
        {
        }
        
        type Tile::getType() const
        {
        	return mtype;
        }

        - Ensuite grâce a la classe Tilemap (https://www.sfml-dev.org/tutorials/2.4/graphics-vertex-array-fr.php) que j'ai modifié pour utilisé un vector de Tile je crée ma carte.

        - Et enfin, je vérifie (avant chaque mouvement) que le carré de texture vers lequel le perso se dirige correspond a un tile dont le type (énumération) indique que le perso peu marché dessus.

        J'ai essayé d'expliquer cela clairement mais j'avoue que je m'y perd un peu moi-même :( 

        Dans tous les cas, merci de ton aide :) sa commence a faire un moment que je bloque la dessus ^^

        -
        Edité par Tenkai188 27 septembre 2017 à 22:00:06

        • Partager sur Facebook
        • Partager sur Twitter
          28 septembre 2017 à 9:56:59

          Salut,

          Si tu as un fichier txt j'imagine que tu as un tableau de pointeur pour stocker tout les nombres (tilts) ?

          exemple :

          Fichier txt :

          123

          114

          444

          dans ton code :

          map[3][3] = {{1,2,3}, {1,1,4}, {4,4,4}};

          encore une fois c'est très grossier mais c'est pour expliquer a quoi je pense ^^

          • Partager sur Facebook
          • Partager sur Twitter
          Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
            28 septembre 2017 à 17:21:54

            Non, je les stock d'abord dans un vector d'entier

            ensuite j'utilise ces nombre comme attribut d'objet Tile

            et apres je stocke ces tiles dans un vector de type tile. :(

            • Partager sur Facebook
            • Partager sur Twitter
              29 septembre 2017 à 9:52:05

              Mais du coup comment check tu que ton personnage est sur un tilt ou l'on peut marcher ? avec les coordonnée en X et Y ? du personnage et de la tilt ?
              • Partager sur Facebook
              • Partager sur Twitter
              Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
                29 septembre 2017 à 13:54:01

                J'utilise une fonction qui calcule l'emplacement dans le vector de Tile grace a la position x et y du sprite:

                int currentTileNbr(AnimatedSprite animatedSprite)
                
                {
                
                    nbrCol = std::ceil((animatedSprite.getPosition().x) / 32); //je divise la position x du sprite par la taille du tile pour savoir dans quel colone il se trouve
                
                    nbrRow = std::ceil((animatedSprite.getPosition().y) / 32);//je fais la même chose avec la position y pour savoir la ligne dans laquel il se trouve
                
                    currentile = (((nbrRow) * 50) + (nbrCol)); // je calcul ensuite son emplacement dans le tableau grace au nombre de tile
                
                    return currentile;
                
                }

                ensuite j'utilise le resultat obtenu pour connaitre le type du prochain tile 

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                        {
                            currentile = currentTileNbr(animatedSprite)-50;//si je monte je vais vers le la ligne précédente du tableau
                            if (tabTile[currentile-1].getType() != type::off)
                            {
                                currentAnimation = &walkingAnimationUp;
                                movement.y -= speed;
                                noKeyWasPressed = false;
                            }
                             
                        }




                -
                Edité par Tenkai188 29 septembre 2017 à 14:07:41

                • Partager sur Facebook
                • Partager sur Twitter
                  29 septembre 2017 à 17:27:31

                  Ok je comprend mieux ! mais du coup ça ne marche pas ce que tu fais ? il avance sur des cases ou il ne devrait pas avancer ?
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
                    1 octobre 2017 à 13:16:51

                    non car cet boucle if n’exécute le code qui permet d'avancer que si le tile suivant est du bon type

                    if (tabTile[currentile-1].getType() != type::off)
                                {
                                    currentAnimation = &walkingAnimationUp;
                                    movement.y -= speed;
                                    noKeyWasPressed = false;
                                }



                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 octobre 2017 à 9:44:17

                      Non ^^ mais ok ça j'ai compris mais du coup qu'es ce qui marche pas ?
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
                        2 octobre 2017 à 13:38:05

                        Les déplacements vers la gauche et le bas :(
                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 octobre 2017 à 14:21:10

                          ça marche pour le haut et la droite tout le temps ? et ça ne marche pas pour le bas et le gauche tout le temps ?

                          Pour quoi tu fais currentile - 1 ?

                          if (tabTile[currentile-1].getType() != type::off)



                          -
                          Edité par NutNut tu coco 2 octobre 2017 à 14:25:01

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
                            2 octobre 2017 à 16:44:29

                            ça a l'air de fonctionner quand je monte ou quand je vais à droite :(

                            Concernant le "currentTile-1" : je fais ainsi car il me semble que les vector (ici celui de Tile) comme les tableau commence à zero.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              3 octobre 2017 à 9:45:37

                              Ba je t'avoue j'ai relu ton code et je vois pas trop en vrai si tu veux je peux le regarder en entier tu me le met dans un zip ou un tar et je regard ça sur mon pc pour le compiler après vu que c'est ton code je comprend que tu ne veuilles pas ;)
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
                                3 octobre 2017 à 12:48:29

                                Salut,

                                Ce que je trouve bizarre, est que quelque soit la direction de ton perso, tu verifies "currentTile-1".
                                Bien souvent, c'est la tuile qui se trouve à gauche du perso, donc quand tu veux aller en bas par exemple, verifier la tuile de gauche n'a aucun sens.

                                Tu t'es fais une fonction qui retourne une tuile en fonction de ton perso.
                                Généralise la en une fonction qui retourne une tuile en fonction de coordonnées (x, y), ca rendra ton code plus claire:
                                currentTileNbr(x, y) ==> tuile courrante.
                                currentTileNbr(x+1, y) ==> tuile de droite.
                                currentTileNbr(x-1, y) ==> tuile de gauche.
                                currentTileNbr(x, y-1) ==> tuile du haut.
                                currentTileNbr(x, y+1) ==> tuile du bas.

                                PS: Attention aux limites mini et maxi, retourner la tuile de gauche quand x vaut zero par exemple, n'a aucun sens.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  3 octobre 2017 à 15:59:48

                                  Voila mon projet:

                                  https://1fichier.com/?mqhbpqffwz

                                  Je préfère prévenir: je débute donc mon code est mal organiser et assez désagréable a regarder :(

                                  Ne fait pas attention au rectangle bleu, j'essaye de créé des fenêtres de texte pour les dialogues. 

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    3 octobre 2017 à 17:01:22

                                    Alors j'ai pas encore regardé ton code mais juste au niveau de l'architecture c'est un conseil aucunement une critique !! 

                                    -Les .h en c++ tu peux mettre remplacer .hpp pour les (.h class pour différencier)

                                    -Les .h (ou .hpp) dans un dossier include

                                    -Les .cpp dans un dossier source ou (src) (après en fonction tu peux regrouper les .cpp dans d'autre sous dossier)

                                    -Les images vidéos fonte dans un dossier assets (après des sous dossier movies, pictures, fonts, ...)

                                    Rien ne t'oblige à le faire mais par exemple pour le coup j'arrive sur ton projet et c'est un peu plus galère :)

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Quand tu regardes l'abîme, l'abîme regarde aussi en toi.
                                      3 octobre 2017 à 21:25:01

                                      Merci pour les conseils, n'hésite pas à le dire si tu vois d'autres erreurs :)
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      [SFML] gestion des collisions avec tilemap

                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                      • Editeur
                                      • Markdown