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

Auteur Sujet: Colision TileMap : personnage coincé  (Lu 8790 fois)

0 Membres et 4 Invités sur ce sujet

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Colision TileMap : personnage coincé
« le: Juin 24, 2014, 06:10:52 am »
Bonjour,
j'ai appliqué les astuces trouvées dans le forum pour gérer la collision entre mon personnage et un bloc de mon tileset (merci au passage) grâce au masque, mais j'ai un problème assez hargneux. En effet, quand il y a une collision mon personnage reste coincé sur place, je ne peux plus le déplacer. J'ai beau cherché, je ne vois pas l'erreur (de logique, ça compile bien). Si quelqu'un pouvait m'aider... je lui serais reconnaissant. Merci  :)

Mon code, simplifié au possible :


#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include "TileMap.cpp"

sf::RenderWindow window;
int speed=2;
sf::Texture perso;
sf::Sprite sprite_perso;
enum Dir{Down,Left,Right,Up};
sf::Vector2i anim(1, Down);
bool updateFPS = false;
int blockSize = 32;
sf::View view;
int screenW = 800;
int screenH = 600;
sf::Music music;
int LARGEUR_TILE = 40;
int HAUTEUR_TILE = 40;
bool colisionTile;

void gestionClavier();

bool collision(bool masque[], int x, int y, int tailleCase)
{
      if( masque[ int(x/tailleCase) + 8*int(y/tailleCase) ] == 1)
             return true;
      return false;
 }


int main()
{
    // On crée la fenêtre et ses paramètres
    window.create(sf::VideoMode(screenW,screenH), "Jeu v. 0.000001a");
    window.setPosition(sf::Vector2i(192,200));
    window.setFramerateLimit(60);

    sf::Texture myTexture;
    if (!myTexture.loadFromFile("tileset.png"))
        std::cout << "ERREUR : load tileset" << std::endl;
    else
        std::cout << "tileset : Done" << std::endl;
    sf::Sprite mySprite(myTexture);

    // On définit le niveau
    const int level[] =
    {
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 1, 1, 1, 1, 9, 9,
        0, 0, 0, 0, 0, 1, 1, 1, 9, 1, 1, 0, 0, 1, 1, 1,
        0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0,
        0, 8, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
    };

 bool masque[] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };

 TileMap map;
    if (!map.load("tileset.png", sf::Vector2u(40, 40), level, 16, 8))
        return -1;

    // Horloge
    sf::Clock time;

    // On vérifie que la sprite joueur est bien chargée
    if(!perso.loadFromFile("player.png"))
    {
        std::cout << "Erreur: player.png non charge" << std::endl;
    }
    perso.setSmooth(true); // pour lisser la texture

    // On applique les textures au sprite joueur
    sprite_perso.setTexture(perso);

    // Tant que la fenêtre est ouverte
    while(window.isOpen())
    {
        sf::Event event;

        // Test des évènements
        while(window.pollEvent(event))
        {
            // Si on clique sur fermer
            if (event.type == sf::Event::Closed)
                window.close();

            // Gestion des FPS
            if(event.type == sf::Event::KeyPressed)
                updateFPS = true;
            else
                updateFPS = false;
        }



        if (updateFPS == true)
        {
            if (time.getElapsedTime().asMilliseconds() >= 50)
            {
                anim.x--;
                if (anim.x * blockSize >= perso.getSize().x)
                    anim.x = 2;
                time.restart();
            }
        }

        // Gestion texture
        sprite_perso.setTextureRect(sf::IntRect(anim.x * blockSize, anim.y * blockSize, blockSize, blockSize));

        colisionTile = collision(masque, sprite_perso.getPosition().x, sprite_perso.getPosition().y, 40);
        if (colisionTile == true)
        {
             std::cout << colisionTile << std::endl;
        }
        else
        {
              std::cout << "pas de colision :"<< colisionTile <<std::endl;
              gestionClavier();
        }
        colisionTile = false;


        /* vue */
        view.reset(sf::FloatRect(0,0, screenW, screenH));
        sf::Vector2f position(screenW / 2, screenH / 2);
        position.x = sprite_perso.getPosition().x + (blockSize / 2) - (screenW / 2);
        position.y = sprite_perso.getPosition().y + (blockSize / 2) - (screenH / 2);
        if(position.x <0)
            position.x = 0;
        if(position.y <0)
            position.y = 0;
        view.reset(sf::FloatRect(position.x, position.y, screenW, screenH));

        window.setView(view);

        // On dessine

         window.draw(map);
         window.draw(sprite_perso);
         window.display();
         window.clear();
    }

    return 0;
}

/* Autres fonctions */


void gestionClavier()
{
      if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            anim.y = Up;
            sprite_perso.move(0, -speed);
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            anim.y = Down;
            sprite_perso.move(0, speed);
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            anim.y = Left;
            sprite_perso.move(-speed, 0);
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            anim.y = Right;
            sprite_perso.move(speed, 0);
        }

        if(sprite_perso.getPosition().x <= 0)
            sprite_perso.setPosition(sf::Vector2f(0, sprite_perso.getPosition().y));
        if(sprite_perso.getPosition().y <= 0)
            sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x,0));
}


 

(le fichier TileMap.cpp est le même que celui des tutos officiel, je l'ai pas remis)

OualidH38

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
    • E-mail
Re : Colision TileMap : personnage coincé
« Réponse #1 le: Juin 24, 2014, 02:17:08 pm »
Ton problème vient de ton raisonnement au niveau de la gestion de collision,  dans ta boucle if tu test si oui ou non il y a collision. 
Ta fonction gestionClavier ( ) est la fonction permettant à ton personnage de se déplacer, si tu regarde bien dans ta boucle tu appelle cette fonction uniquement lorsqu'il n'y a pas collision, normal que ton personnage s'arrête de bouger dès qu'il entre en collision puisque tu n'appelle pas la fonction gestionClavier ( ).

Tu devrais plutôt faire en sorte que ton personnage puisse bouger vers une direction où il peut aller, car s'il est bloqué à droite il peut aller à gauche,  donc revois ton test de collision ;)

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #2 le: Juin 24, 2014, 06:21:42 pm »
Merci pour ta réponse, j'ai donc essayé de faire comme ceci :


 colisionTile = collision(masque, sprite_perso.getPosition().x, sprite_perso.getPosition().y, 40);
        if (colisionTile == true)
        {
             std::cout << colisionTile << std::endl;
        }
        else
        {
              std::cout << "pas colision"<< colisionTile <<std::endl;

        }
        colisionTile = false;

         //Gestion du clavier
           gestionClavier2();
           gestionClavier();

// avec les fonctions

void gestionClavier()
{
      if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (directionH == true))
        {
            anim.y = Up;
            sprite_perso.move(0, -speed);
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && (directionB == true))
        {
            anim.y = Down;
            sprite_perso.move(0, speed);
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (directionG == true))
        {
            anim.y = Left;
            sprite_perso.move(-speed, 0);
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && (directionD == true))
        {
            anim.y = Right;
            sprite_perso.move(speed, 0);
        }

        if(sprite_perso.getPosition().x <= 0)
            sprite_perso.setPosition(sf::Vector2f(0, sprite_perso.getPosition().y));
        if(sprite_perso.getPosition().y <= 0)
            sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x,0));
}

void gestionClavier2()
{
      if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (colisionTile == true))
        {
            directionG = true;
            directionD = true;
            directionH = false;
            directionB = true;
        }
      if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && (colisionTile == true))
        {
            directionG = true;
            directionD = true;
            directionH = true;
            directionB = false;
        }
       if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (colisionTile == true))
        {
            directionG = false;
            directionD = true;
            directionH = true;
            directionB = true;
        }
       if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && (colisionTile == true))
        {
            directionG = true;
            directionD = false;
            directionH = true;
            directionB = true;
        }
}

 

le problème est qu'une fois qu'il y a une collision elle reste en mémoire donc ce que j'ai fait ne peut pas fonctionner. Je ne sais pas comment résoudre le problème, soit mon personnage reste bloqué soit il passe complètement à travers les bloques. Qu'est-ce qui ne va pas ? (encore merci  ;D)

OualidH38

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
    • E-mail
Re : Colision TileMap : personnage coincé
« Réponse #3 le: Juin 25, 2014, 01:58:25 pm »
Je te conseil d'aller voir du côté de ce tutoriel : http://fr.openclassrooms.com/informatique/cours/theorie-des-collisions/formes-simples

En gros ce qu'il faut que tu comprenne c'est que tu dois faire en sorte de calculer la position future de ton personnage que l'on va appeler position2, tu fais ton test de collision sur position2, s'il n'y a pas collision alors tu fais un perso.setPosition(position2), s'il y a collision tu n'applique pas la nouvelle position.

Pour obtenir position2 il suffit d'ajouter à la position de ton personnage la vitesse :

sf::Vector2f position2;

position2.x = perso.getPosition().x + vitesseX;
position2.y = perso.getPosition().y + vitesseY;

//Une fois que tu as calculé position2 tu test si en position2 il y a collision

if(PAS COLLISION)
{
         perso.setPosition(position2);
}
else
        std::cout<<"Collision !"<<std::endl;
 

vitesseX et vitesseY sont seulement des variables dont la valeur dépend des touches sur lesquels tu appuies.


Voilà j'espère t'avoir aidé  ;)

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #4 le: Juin 26, 2014, 01:16:10 am »
Ok merci même si j'ai mis plusieurs longues heures pour essayer de comprendre et d'adapter ce que tu m'as dis à mon programme. J'ai donc procédé à quelques petits changements :

         // dans le main
 
        gestionClavier();

        position2.x = sprite_perso.getPosition().x + vitesseX;
        position2.y = sprite_perso.getPosition().y + vitesseY;

        colisionTile = collision(masque, position2.x, position2.y, 40);

        if(colisionTile == false)
        {
            sprite_perso.setPosition(position2);
            std::cout<<" pas Collision !"<<std::endl;
        }
        else
            std::cout<<"Collision !"<<std::endl;

// et dans la fonction

void gestionClavier()
{
      if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            anim.y = Up;
            vitesseY = -speed;
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            anim.y = Down;
            vitesseY = +speed;
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            anim.y = Left;
            vitesseX = -speed;
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            anim.y = Right;
            vitesseX = +speed;
        }

        if(sprite_perso.getPosition().x <= 0)
            sprite_perso.setPosition(sf::Vector2f(0, sprite_perso.getPosition().y));
        if(sprite_perso.getPosition().y <= 0)
            sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x,0));
}
 

Cependant mon personnage glisse continuellement avec cette méthode, même quand j'arrête d'appuyer. Une idée ?  :)

Merci
« Modifié: Juin 26, 2014, 02:31:23 am par pompot »

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #5 le: Juin 26, 2014, 02:21:12 pm »
Vu que la seule fois où tu affectes une valeur à vitesseX et vitesseY c'est quand tu appuies sur une touche donc ils gardent cette valeur même quand tu n'appuies plus.
Mets vitesseX et vitesseY à 0 avant gestionClavier.

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #6 le: Juin 26, 2014, 05:26:54 pm »
Exact merci !  ;)
J'avais trouvé une autre solution sûrement moins adéquate en faisant :
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
    position2.y = sprite_perso.getPosition().y + vitesseY;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
    position2.x = sprite_perso.getPosition().x + vitesseX;
}
 

Par contre, une dernière petite chose. ;D Je croyais que l'endroit des collisions correspond à mon masque mais ce n'est pas le cas, les collisions se font à des endroits inattendus. (le code de la fonction collision et son masque est dans mon premier message). Savez-vous pourquoi ?
« Modifié: Juin 26, 2014, 05:33:47 pm par pompot »

PtichapronRouge

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
    • E-mail
Re : Colision TileMap : personnage coincé
« Réponse #7 le: Juin 26, 2014, 08:17:51 pm »
Il me semble que le problème vient de cette ligne :
Citer
if( masque[ int(x/tailleCase) + 8*int(y/tailleCase) ] == 1)
Ton masque fait 8 lignes pour 16 colonnes, donc ce n'est pas 8*int... Que tu dois écrire mais 16*int...
Remplace le 8 par un 16 et ça devrait aller mieux je pense :)
Un coca, un ordinateur, et un livre SFML Game Development. Elle est pas belle la vie ?

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #8 le: Juin 26, 2014, 10:08:12 pm »
Je pensais que les colonnes se situaient sur l'axe des Y plutôt d'où le 8*int. Mais même en le passant à 16 les obstacles ont l'air un peu mieux placés mais ils ne correspondent pas exactement au masque. ( je peux rentrer dans des grosses zones où cela ne devrait pas être possible). Ce n'est pas que ça... :/

OualidH38

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
    • E-mail
Re : Colision TileMap : personnage coincé
« Réponse #9 le: Juin 28, 2014, 11:28:55 am »
Regarde ce tuto il est en C mais la logique est la même : http://fr.openclassrooms.com/informatique/cours/tile-mapping/simple-personnage

J'espère que ça t'aidera à comprendre pourquoi ton personnage passe parfois à travers les tiles de ta map  ;)

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #10 le: Juin 28, 2014, 04:52:31 pm »
Merci je l'ai lu c'était instructif mais mon problème n'est pas que mon personnage passe à travers certaines tiles en raison d'un bug. En faite, ce sont des zones entières de collision qui sont au mauvais endroit (il y a collision ou il ne devrait pas et vise versa).

OualidH38

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
    • E-mail
Re : Colision TileMap : personnage coincé
« Réponse #11 le: Juin 28, 2014, 06:29:02 pm »
Ah excuse moi j'avais mal compris  ;D

Par contre je ne vois pas pourquoi les zones de collision ne correspondent pas au masque, as tu pensé à gérer les collisions directement avec ton tableau "level" sans passer par un masque?

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #12 le: Juin 29, 2014, 04:15:39 pm »
Je ne vois pas comment je pourrais faire sans le masque vu qu'il me sert justement à savoir s'il y a une collision sur une case correspondant à mon tableau level. Ce que je peux peut-être faire c'est donner mon code entier avec mon personnage et mon tileset pour que quelqu'un de plus expérimenté l'essaie et comprenne pourquoi.

main.cpp
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include "TileMap.cpp"

sf::RenderWindow window; // Fenêtre
sf::RectangleShape rectangle; // un objet rectangle
int speed=2; // vitesse du personnage
sf::Texture perso; // Texture du perso
sf::Sprite sprite_perso; // Pour récupérer son sprite
enum Dir{Down,Left,Right,Up}; // Pour le déplacement
sf::Vector2i anim(1, Down); // Animation du personnage
bool updateFPS = false; // Fps
int blockSize = 32; // Taille du personnage
sf::View view; // Vue
int screenW = 800; // Largeur fenêtre
int screenH = 600; // Hauteur fenêtre
int LARGEUR_TILE = 40; // largeur d'une tuile du décor
int HAUTEUR_TILE = 40; // hauteur d'une tuile du décor
bool colisionTile; // Vraie si collision, faux si pas collision
sf::Vector2f position2; // Position du personnage calculée
int vitesseX = 0; // Vitesse du personnage
int vitesseY = 0; // Vitesse du personnage

// Déclaration des fonctions (comme elles ne sont pas dans un header...)
void gestionClavier();
void gestionSouris();
void playMusic();
void gestionClavier2();
bool collision(bool[], int, int, int);

// Fonction principale
int main()
{
    // On crée la fenêtre et ses paramètres
    window.create(sf::VideoMode(screenW,screenH), "Jeu");
    window.setPosition(sf::Vector2i(192,200));
    window.setFramerateLimit(60);
    //window.setKeyRepeatEnabled(false);

    sf::Texture myTexture;
   
    if (!myTexture.loadFromFile("tileset.png"))
        std::cout << "ERREUR : load tileset" << std::endl;
    else
        std::cout << "tileset : Done" << std::endl;
       
    sf::Sprite mySprite(myTexture);

    // On définit le niveau
    const int level[] =
    {
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 1, 1, 1, 1, 9, 9,
        0, 0, 0, 0, 0, 1, 1, 1, 9, 1, 1, 0, 0, 1, 1, 1,
        0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0,
        0, 8, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
    };

    // Le masque du niveau (0 : pas collision, 1 : collision)
    bool masque[] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
        0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };

 TileMap map;
    if (!map.load("tileset.png", sf::Vector2u(40, 40), level, 16, 8))
        return -1;

    // Horloge
    sf::Clock time;

    // On vérifie que la sprite joueur est bien chargée
    if(!perso.loadFromFile("player.png"))
    {
        std::cout << "Erreur: player.png non charge" << std::endl;
    }
    perso.setSmooth(true); // pour lisser la texture

    // On applique les textures au sprite joueur
    sprite_perso.setTexture(perso);

    // Tant que la fenêtre est ouverte
    while(window.isOpen())
    {
        sf::Event event;

        // Test des évènements
        while(window.pollEvent(event))
        {
            // Si on clique sur fermer
            if (event.type == sf::Event::Closed)
                window.close();

            // Gestion des FPS
            if(event.type == sf::Event::KeyPressed)
            {
                updateFPS = true;
            }
            else
            {
                 updateFPS = false;
            }
        }

        if (updateFPS == true)
        {
            if (time.getElapsedTime().asMilliseconds() >= 50)
            {
                anim.x--;
                if (anim.x * blockSize >= perso.getSize().x)
                    anim.x = 2;
                time.restart();
            }
        }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Gestion texture
        sprite_perso.setTextureRect(sf::IntRect(anim.x * blockSize, anim.y * blockSize, blockSize, blockSize));

        vitesseX = 0;
        vitesseY = 0;
        gestionClavier();

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            position2.y = sprite_perso.getPosition().y + vitesseY;
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            position2.x = sprite_perso.getPosition().x + vitesseX;
        }

        colisionTile = collision(masque, position2.x, position2.y, 40);

        if(colisionTile == false)
        {
            sprite_perso.setPosition(position2);
            std::cout<<" pas Collision !"<<std::endl;
        }
        else
        {
            std::cout<<"Collision !"<<std::endl;
        }

        /* vue */
        view.reset(sf::FloatRect(0,0, screenW, screenH));
        sf::Vector2f position(screenW / 2, screenH / 2);
        position.x = sprite_perso.getPosition().x + (blockSize / 2) - (screenW / 2);
        position.y = sprite_perso.getPosition().y + (blockSize / 2) - (screenH / 2);
        if(position.x <0)
            position.x = 0;
        if(position.y <0)
            position.y = 0;
        view.reset(sf::FloatRect(position.x, position.y, screenW, screenH));

        window.setView(view);

        // On dessine
         window.draw(map);
         window.draw(sprite_perso);
         window.display();
         window.clear();
    }

    return 0;
}

/* Fonctions */

// Deplacement personnage
void gestionClavier()
{
    if(sf::Event::KeyPressed)
    {
          if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            anim.y = Up;
            vitesseY = -speed;
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            anim.y = Down;
            vitesseY = speed;
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            anim.y = Left;
            vitesseX = -speed;
        }
         else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            anim.y = Right;
            vitesseX = speed;
        }
    }
    else
    {
        vitesseX=0;
        vitesseY=0;
    }

    // collision avec les bords gauche et haut
        if(sprite_perso.getPosition().x <= 0)
            sprite_perso.setPosition(sf::Vector2f(0, sprite_perso.getPosition().y));
        if(sprite_perso.getPosition().y <= 0)
            sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x,0));
}

// Fonction qui teste la collision entre le masque et le personnage
bool collision(bool masque[], int x, int y, int tailleCase)
{
      if( masque[ int(x/tailleCase) + 16*int(y/tailleCase) ] == 1)
             return true;
      return false;
}
 

TileMap.cpp (celui de la doc)
class TileMap : public sf::Drawable, public sf::Transformable
{
public:

    bool load(const std::string& tileset, sf::Vector2u tileSize, const int* tiles, unsigned int width, unsigned int height)
    {
        // on charge la texture du tileset
        if (!m_tileset.loadFromFile(tileset))
            return false;

        // on redimensionne le tableau de vertex pour qu'il puisse contenir tout le niveau
        m_vertices.setPrimitiveType(sf::Quads);
        m_vertices.resize(width * height * 4);

        // on remplit le tableau de vertex, avec un quad par tuile
        for (unsigned int i = 0; i < width; ++i)
            for (unsigned int j = 0; j < height; ++j)
            {
                // on récupère le numéro de tuile courant
                int tileNumber = tiles[i + j * width];

                // on en déduit sa position dans la texture du tileset
                int tu = tileNumber % (m_tileset.getSize().x / tileSize.x);
                int tv = tileNumber / (m_tileset.getSize().x / tileSize.x);

                // on récupère un pointeur vers le quad à définir dans le tableau de vertex
                sf::Vertex* quad = &m_vertices[(i + j * width) * 4];

                // on définit ses quatre coins
                quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
                quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
                quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
                quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);

                // on définit ses quatre coordonnées de texture
                quad[0].texCoords = sf::Vector2f(tu * tileSize.x, tv * tileSize.y);
                quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
                quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
                quad[3].texCoords = sf::Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
            }

        return true;
    }

private:

    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        // on applique la transformation
        states.transform *= getTransform();

        // on applique la texture du tileset
        states.texture = &m_tileset;

        // et on dessine enfin le tableau de vertex
        target.draw(m_vertices, states);
    }

    sf::VertexArray m_vertices;
    sf::Texture m_tileset;
};
 
« Modifié: Juin 29, 2014, 04:18:12 pm par pompot »

OualidH38

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
    • E-mail
Re : Colision TileMap : personnage coincé
« Réponse #13 le: Juin 30, 2014, 01:08:42 pm »
Tu peux très bien te passer d'un masque, c'est ce que je fais et ça marche très bien.
Tu peux faire comme ça par exemple :
//Imaginons que le personnage entre en collision avec les tiles 5 et 9:

bool collision(int level[], int x, int y, int tailleCase)
{
      if( level[ int(x/tailleCase) + 16*int(y/tailleCase) ] == 5 || level[ int(x/tailleCase) + 16*int(y/tailleCase) ] == 9)
             return true;
      else
      return false;
}
 

J'espère que ça t'aidera  :)

pompot

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Colision TileMap : personnage coincé
« Réponse #14 le: Juin 30, 2014, 03:25:21 pm »
J'ai donc essayé en faisant la collision directement avec le level mais il y a toujours le même problème, les zone de collision ne correspondent pas comme il faut.  :(