Collision carré

General

IceCrew

5 years ago

Bonjour !

cela fait des heures et des heures que je me creuse les méninges pour trouver une solution à mon problème : 

j'ai un carré (gb.display.fillRect(0, 30, gb.display.width()-25, 4); en gros c'est le carré du milieu) et j'aimerai que mon personnage (gb.display.fillRect(posX, posY, PERSO, PERSO); petit carré en bas à gauche)  ne le traverse pas (que ce soit par en haut, par en bas ou par la droite).

Quand il s'agit de ne pas traverser le carré qui se situe tout à droite, je fais :

if(gb.collideRectRect(posX, posY, PERSO, PERSO, 70, 0, 10, gb.display.height())==true) {
    posX=70-PERSO;
  }

Mais quand ils s'agit de ne pas traverser plusieurs côtés, c'est plus compliqué !

j'avais pensé à faire deux variable (posXretard et posYretard) qui prendrai la position x et y en retard par rapport à posX et posY. Comme ça si les deux carré se superposent, le posX = posXretard et posY = posYretard.

j'ai essayé de mettre un delay mais ça stoppe tout le processus et non l'affectation de la variable... Je ne sais pas quoi mettre ni comment m'y prendre, si quelqu'un veut bien m'aider !

(Et je n'ai vraiment pas envie de mettre pleins de if, à la longue on se perd, ça fait beaucoup de texte et c'est peu pratique !)


jicehel

NEW 5 years ago

Bonjour, je t'invite à lire cet échange: https://gamebuino.com/community/topic/collisions?page=1

C'est très proche de ce que tu veux faire, il me semble. De manière générale, il y a déjà beaucoup de choses sur le forum mais on a un outils super qui se cache sous la forme d'une loupe et c'est l’intérêt du forum contrairement à Discord: on garde l'historique alors quand vous avez une question assez générique, n'hésitez pas d'abord à faire une recherche avant de poser une question. Enfin c'est mon avis et il vaut ce qu'il vaut mais bon, je le donne quand même  ;)

IceCrew

5 years ago

#include <Gamebuino-Meta.h>

#define PERSO 4
#define PAS 4
/* 80 en X et 64 en Y*/

int posXrecent = 0;
int posYrecent = 0;
int jumpSpeed = 0;
int jumpCounter = 0;
int murCounter = 0;
int nbJump = 0;
int pos = 0;
bool jump = false;

  /*----------RECTANGLES----------*/

struct rect {
  int x;
  int y;
  int widthrect;
  int heightrect;
};

  /*----------PERSONNAGE----------*/

rect rectP = {0, 50-PERSO, PERSO, PERSO};

  /*----------PLATEFORMES---------*/

rect rectangles[2] = {
  {0, 50, gb.display.width(), 14},
  {70, 0, 10, gb.display.height()},
  /*{0, 30, gb.display.width()-25, 4}*/
};

void setup() 
{
  gb.begin();
}

boolean testcollision( int xr1p1, int yr1p1, int xr1p2, int yr1p2, int xr2p1, int yr2p1, int xr2p2, int yr2p2 ) {
  boolean test = false;
  if (xr1p1 < xr2p2 && xr1p2 > xr2p1 && yr1p1 < yr2p2 && yr1p2 > yr2p1)  {
    test = true;
  }
  return test;
}


void loop() 
{
  while(!gb.update());
  gb.display.clear();

  posXrecent = rectP.x;
  posYrecent = rectP.y;

  /*-----------CONTROLES----------*/

           /*--------DIRECTION--------*/

  if(gb.buttons.repeat(BUTTON_RIGHT,0)&& (rectP.x + rectP.widthrect) < 80) {
    posXrecent+=PAS;
  }

  if(gb.buttons.repeat(BUTTON_LEFT,0) && rectP.x > 0) {
    posXrecent-=PAS;
  }

            /*-----------JUMP----------*/

  if((gb.buttons.pressed(BUTTON_B)) && (nbJump < 2)) {
    jump = true;
    jumpSpeed = -5;
    nbJump += 1;
    if((gb.buttons.released(BUTTON_B)) && (jumpSpeed < 0)) {
      jumpSpeed /= 2;
    }
  }

  boolean deplacement = true;

  /*-------------ACTION------------*/

              /*-----------JUMP----------*/

  if(jump == true) {
    posYrecent += jumpSpeed;
    jumpCounter += 1;
    if((jumpCounter % 2) == 0) {
      jumpSpeed += 2;
    }
  }       

  /*-----------COLLISIONS----------*/

              /*------------MUR----------*/

  for (int i = 0; i < 2; i++) {
    if (testcollision(posXrecent, posYrecent, posXrecent + rectP.widthrect, posYrecent + rectP.heightrect, rectangles[i].x, rectangles[i].y, rectangles[i].x + rectangles[i].widthrect, rectangles[i].y + rectangles[i].heightrect)) {
      deplacement = false;

             /* -----------JUMP----------*/

      nbJump = 0;             
      if(jump == true){
        jump = false;
        jumpCounter = 0;
      }
    } 
  }

  if (deplacement) {
    rectP.x = posXrecent;
    rectP.y = posYrecent;
  }


  /*------------AFFICHAGE----------*/

              /*----------PERSO---------*/

  gb.display.fillRect(rectP.x, rectP.y, rectP.widthrect, rectP.heightrect);

              /*-----------MUR----------*/

  for (int i = 0; i < 2; i++) {
    gb.display.fillRect(rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect);
  }

  gb.display.print(posXrecent);
  gb.display.print(posYrecent);
}

Voila mon code ! j'ai essayé de comprendre ce que tu avais fais et l'ai intégré à mon programme. Cependant, mon perso s'arrête à 6 pixels du mur de droite et quand je saute, il se peut que le perso se bloque dans l'air. J'ai commenté le jump pour vois si c'était à cause de ça mais le perso se bloque toujours avant le mur de droite et je ne comprend pas pourquoi... J'ai vérifié le test de collision mais il n'y a pas d'erreurs...

IceCrew

NEW 5 years ago

Désolé pour le doublon :/ 

J'ai justement utilisé la loupe pour cette recherche (https://gamebuino.com/community/topic/how-to-detect-collisions#c1299 j'avais trouvé ce sujet mais le programme était vachement plus compliqué que celui du lien que tu m'as envoyé haha)

J'ai mal cherché ! en tout cas merci pour le lien, j'y trouve mon bonheur !

IceCrew

NEW 5 years ago

jicehel jicehel

#include <Gamebuino-Meta.h>

#define PERSO 4
#define PAS 4
/* 80 en X et 64 en Y*/

int posXrecent = 0;
int posYrecent = 0;
int jumpSpeed = 0;
int jumpCounter = 0;
int murCounter = 0;
int nbJump = 0;
int pos = 0;
bool jump = false;

  /*----------RECTANGLES----------*/

struct rect {
  int x;
  int y;
  int widthrect;
  int heightrect;
};

  /*----------PERSONNAGE----------*/

rect rectP = {0, 50-PERSO, PERSO, PERSO};

  /*----------PLATEFORMES---------*/

rect rectangles[2] = {
  {0, 50, gb.display.width(), 14},
  {70, 0, 10, gb.display.height()},
  /*{0, 30, gb.display.width()-25, 4}*/
};

void setup() 
{
  gb.begin();
}

boolean testcollision( int xr1p1, int yr1p1, int xr1p2, int yr1p2, int xr2p1, int yr2p1, int xr2p2, int yr2p2 ) {
  boolean test = false;
  if (xr1p1 < xr2p2 && xr1p2 > xr2p1 && yr1p1 < yr2p2 && yr1p2 > yr2p1)  {
    test = true;
  }
  return test;
}


void loop() 
{
  while(!gb.update());
  gb.display.clear();

  posXrecent = rectP.x;
  posYrecent = rectP.y;

  /*-----------CONTROLES----------*/

           /*--------DIRECTION--------*/

  if(gb.buttons.repeat(BUTTON_RIGHT,0)&& (rectP.x + rectP.widthrect) < 80) {
    posXrecent+=PAS;
  }

  if(gb.buttons.repeat(BUTTON_LEFT,0) && rectP.x > 0) {
    posXrecent-=PAS;
  }

            /*-----------JUMP----------*/

  if((gb.buttons.pressed(BUTTON_B)) && (nbJump < 2)) {
    jump = true;
    jumpSpeed = -5;
    nbJump += 1;
    if((gb.buttons.released(BUTTON_B)) && (jumpSpeed < 0)) {
      jumpSpeed /= 2;
    }
  }

  boolean deplacement = true;

  /*-------------ACTION------------*/

              /*-----------JUMP----------*/

  if(jump == true) {
    posYrecent += jumpSpeed;
    jumpCounter += 1;
    if((jumpCounter % 2) == 0) {
      jumpSpeed += 2;
    }
  }       

  /*-----------COLLISIONS----------*/

              /*------------MUR----------*/

  for (int i = 0; i < 2; i++) {
    if (testcollision(posXrecent, posYrecent, posXrecent + rectP.widthrect, posYrecent + rectP.heightrect, rectangles[i].x, rectangles[i].y, rectangles[i].x + rectangles[i].widthrect, rectangles[i].y + rectangles[i].heightrect)) {
      deplacement = false;

             /* -----------JUMP----------*/

      nbJump = 0;             
      if(jump == true){
        jump = false;
        jumpCounter = 0;
      }
    } 
  }

  if (deplacement) {
    rectP.x = posXrecent;
    rectP.y = posYrecent;
  }


  /*------------AFFICHAGE----------*/

              /*----------PERSO---------*/

  gb.display.fillRect(rectP.x, rectP.y, rectP.widthrect, rectP.heightrect);

              /*-----------MUR----------*/

  for (int i = 0; i < 2; i++) {
    gb.display.fillRect(rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect);
  }

  gb.display.print(posXrecent);
  gb.display.print(posYrecent);
}

Voila mon code ! j'ai essayé de comprendre ce que tu avais fais et l'ai intégré à mon programme. Cependant, mon perso s'arrête à 6 pixels du mur de droite et quand je saute, il se peut que le perso se bloque dans l'air. J'ai commenté le jump pour vois si c'était à cause de ça mais le perso se bloque toujours avant le mur de droite et je ne comprend pas pourquoi... J'ai vérifié le test de collision mais il n'y a pas d'erreurs...

jicehel

NEW 5 years ago

Hum, c'est normal, car dans ton cas, tu ne veux pas uniquement que le déplacement n'est pas lieu, il doit avoir lieu mais de façon différente.

Ca marche bien avec les bords de l'écran mais c'est un peu de la chance car tu n'as pas de déplacements variables en taille.

Actuellement ce que tu fais c'est par exemple pour le déplacement le plus simple, celui horizontal:

J'ai une touche qui est appuyé pour aller vers la droite: si je rencontre un obstacle, je ne me déplace pas. Si ton obstacle est placé à un nombre de pas exacts, tu auras l'impression que ça marche car le personnage s’arrêtera pile devant le mur mais si la position du mur n'est pas un multiple exact de pas, il faut que tu traites ce cas et qu'en cas de collision avec le mur, il s’arrête contre le mur.

Pour le saut c'est plus complexe car tu gères la chute. Le personnage doit donc s'il saute contre un mur, continuer sont saut dans les directions où il n'est pas bloqué. Je sais que mes explications ne sont pas toujours très claires, mais j'espère que ça t'aide à comprendre le problème.

Je vais essayer de te coder ça rapidos (Enfin pour le saut je ne te garantie pas que ce soit nickel..., je regarde ça)

jicehel

NEW 5 years ago

Hum une question pour comprendre ce que tu veux faire. Est-ce que le personnage est censé pouvoir s'accrocher au mur verticaux ? (C'est pour le comportement car du coup ce ne serait pas le même que celui que je viens de décrire)

jicehel

NEW 5 years ago

Hum, désolé, j'ai un soucis pour le faire j'ai une erreur de logique quelque part avec les sauts (quand on se déplace en sautant vers la droite et en retombant). Pas le temps de chercher plus pour le moment mais quelqu'un pourra sans doute te donner l'erreur. Sinon j'y regarderais ce soir.

En tous cas le code devrait te donner une idée de quoi faire (j'ai rajout ta 3ème plateforme pour que tu puisses tester le comportement que tu souhaites mais il y a plein de cas à prévoir comme par exemple si tu dois pouvoir passer à travers une plateforme ou passer par un trou etc...

Bon je te donne le code même s'il ne marche pas comme je voudrais (désolé, dans ma logique, il devrait mais j'ai dû faire une boulette quelque part)

#include <Gamebuino-Meta.h>

#define PERSO 4   // taille du personnage (carré de 4x4)
#define PAS 4     // taille d'un déplacement
#define STOP   0
#define DROITE 1
#define GAUCHE -1
#define HAUT   -1
#define BAS    1

#define NbSautsMax 2

#define Nb_rectangles 3

/* 80 en X et 64 en Y*/

// initialisation des variables
byte posXrecent = 0;  // Mémorise la position en X actuelle du joueur avant déplacement
byte posYrecent = 0;  // Mémorise la position en Y actuelle du joueur avant déplacement
byte jumpSpeed = 0;   // Déplacement vertical (pas) effectu lors d'un saut
byte jumpCounter = 0; // Permet de gérer la courbe du saut (passage du temps du saut)
byte nbJump = 0;      // Nombre d'appui sur B pour sauter qui doit être plus petit que le nombre de sauts autorisés
bool jump = false;    // Variable indiquant si on est en train de sauter

  /*----------RECTANGLES----------*/

struct rect {
  byte x;          // Position en X du rectangle
  byte y;          // Position en Y du rectangle
  byte widthrect;  // Largeur du rectangle
  byte heightrect; // Hauteur du rectangle
};

  /*----------PERSONNAGE----------*/

byte directionH = STOP;
byte directionV = STOP;
rect rectP = {0, 50-PERSO, PERSO, PERSO};

  /*----------PLATEFORMES---------*/

rect rectangles[Nb_rectangles] = {
  {0, 50, gb.display.width(), 14},
  {70, 0, 10, gb.display.height()},
  {0, 30, gb.display.width()-25, 4},
};

void setup() 
{
  gb.begin();
}

// On ne l'utilise pas dans ton cas mais je la garde pour le cas de plate forme et non pas de mur
boolean testcollision( byte xr1p1, byte yr1p1, byte xr1p2, byte yr1p2, byte xr2p1, byte yr2p1, byte xr2p2, byte yr2p2 ) {
  boolean test = false;
  if (xr1p1 < xr2p2 && xr1p2 > xr2p1 && yr1p1 < yr2p2 && yr1p2 > yr2p1)  {
    test = true;
  }
  return test;
}

// S'il y a eu collision on test si il a eu lieu horizotalement en fonction de la direction
boolean testcollisionH( byte xr1p1, byte xr1p2, byte xr2p1,  byte xr2p2, byte dirH ) {
  boolean test = false;
  if (dirH == DROITE && xr1p2 > xr2p1)  {
    test = true;
  }
  if (dirH == GAUCHE && xr1p1 < xr2p2)  {
    test = true;
  }
  return test;
}

// En cas de collision on vérifie s'il a eu lieu verticalement en fonction de la direction
boolean testcollisionV( int yr1p1, int yr1p2, int yr2p1,  int yr2p2, byte dirV ) {
  boolean test = false;
  if (dirV == BAS && yr1p2 > yr2p1)  {
    test = true;
  }
  if (dirV == HAUT && yr1p1 < yr2p2)  {
    test = true;
  }
  return test;
}

void loop() 
{
  while(!gb.update());
  gb.display.clear();

  posXrecent = rectP.x;
  posYrecent = rectP.y;

  /*-----------CONTROLES----------*/

           /*--------DIRECTION--------*/

  if(gb.buttons.repeat(BUTTON_RIGHT,0) && (rectP.x + rectP.widthrect) < gb.display.width() ) {
    directionH = DROITE;
    posXrecent+=PAS;
  } 

  if(gb.buttons.repeat(BUTTON_LEFT,0) && ( rectP.x) > 0) {
    posXrecent-=PAS;
    directionH = GAUCHE;
  } 

          /*-----------JUMP----------*/

  if((gb.buttons.pressed(BUTTON_B)) && (nbJump < NbSautsMax)) {
    jump = true;
    jumpSpeed = -5;
    nbJump += 1;
    if((gb.buttons.released(BUTTON_B)) && (jumpSpeed < 0)) {
      jumpSpeed /= 2;
    }
    directionV = HAUT;
  }

  /*-------------ACTIONS------------*/

              /*-----------JUMP----------*/

  if(jump == true) {
    if (jumpSpeed < 0) directionV = HAUT; else directionV = BAS;
    posYrecent += jumpSpeed;
    jumpCounter += 1;
    if((jumpCounter % 2) == 0) {
      jumpSpeed += 2;
    }

  }       

  /*-----------COLLISIONS----------*/

              /*------------MUR----------*/

  for (int i = 0; i < Nb_rectangles; i++) {
    if (testcollision(posXrecent, posYrecent, posXrecent + rectP.widthrect, posYrecent + rectP.heightrect, rectangles[i].x, rectangles[i].y, rectangles[i].x + rectangles[i].widthrect, rectangles[i].y + rectangles[i].heightrect)) {

       if (testcollisionH(posXrecent, posXrecent + rectP.widthrect, rectangles[i].x, rectangles[i].x + rectangles[i].widthrect,directionH)) {
          if (directionH == DROITE) posXrecent = rectangles[i].x - rectP.widthrect;
          if (directionH == GAUCHE) posXrecent = rectangles[i].x + rectangles[i].widthrect;
          directionH = STOP;
       }

       if (testcollisionV(posYrecent, posYrecent + rectP.heightrect, rectangles[i].y, rectangles[i].y + rectangles[i].heightrect,directionV)) {
          if (directionV == HAUT)   {
            posYrecent = rectangles[i].y + rectangles[i].heightrect;
            if (jumpSpeed < 0) jumpSpeed = 1;
            directionV= BAS;
          } else { 
              posYrecent = rectangles[i].y - rectP.heightrect;
              directionV= STOP;
              jump = false;
              nbJump = 0;
              jumpCounter = 0;
              jumpSpeed  = 0;
          }

       }
             /* -----------JUMP----------*/
    } 
  }

  // Sécurité de sortie d'écran
  if((posXrecent + rectP.widthrect) >= gb.display.width()) {
    posXrecent = gb.display.width() - rectP.widthrect;
    directionH = STOP;
  } 
  if((posXrecent) <= 0) {
    posXrecent = 0;
    directionH = STOP;
  } 
  if((posYrecent + rectP.heightrect) >= gb.display.height()) {
    posXrecent = gb.display.height() - rectP.heightrect;
    directionV = STOP;
    jump = false;
  } 
  if((posYrecent) <= 0) {
    posYrecent = 0;
    nbJump = 0;
    jumpCounter = 0;
    directionV = STOP;
  } 
  rectP.x = posXrecent;
  rectP.y = posYrecent;



  /*------------AFFICHAGE----------*/

              /*----------PERSO---------*/

  gb.display.fillRect(rectP.x, rectP.y, rectP.widthrect, rectP.heightrect);

              /*-----------MUR----------*/

  for (int i = 0; i < Nb_rectangles; i++) {
    gb.display.fillRect(rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect);
  }

  gb.display.print("X: ");   gb.display.print(posXrecent);
  gb.display.print(" ; Y: "); gb.display.print(posYrecent);
  gb.display.print("       ");
}





IceCrew

5 years ago

j'avais prévu que mon sprite puisse se fixer aux murs et rebondir.

Mais en tout cas merci sincèrement,pour la rapidité des réponses et le code ! je vais l'essayer et essayer de trouver le problème :p

[EDIT] : il y a aussi un problème de double saut, le sprite disparaît et ne peux plus bouger

IceCrew

NEW 5 years ago

jicehel jicehel

j'avais prévu que mon sprite puisse se fixer aux murs et rebondir.

Mais en tout cas merci sincèrement,pour la rapidité des réponses et le code ! je vais l'essayer et essayer de trouver le problème :p

[EDIT] : il y a aussi un problème de double saut, le sprite disparaît et ne peux plus bouger

jicehel

NEW 5 years ago

Au fait, j'avais encore oubli mais tu as la fonction: gb.collideRectRect(player.x, player.y, player.w, player.h, rect.x, rect.y, rect.w, rect.h)

Ca simplifie le code  ;)

Bon, je pense que ce n'est pas comme ça qu'il faudait faire mais pour terminer sur mon code d'avant, ça donnerait ça:

#include <Gamebuino-Meta.h>

#define PERSO 4   // taille du personnage (carré de 4x4)
#define PAS 4     // taille d'un déplacement
#define STOP   0
#define DROITE 1
#define GAUCHE -1
#define HAUT   -1
#define BAS    1

#define NbSautsMax 2

#define Nb_rectangles 4

/* 80 en X et 64 en Y*/

// initialisation des variables
int posXrecent = 0;  // Mémorise la position en X actuelle du joueur avant déplacement
int posYrecent = 0;  // Mémorise la position en Y actuelle du joueur avant déplacement
int jumpSpeed = 0;   // Déplacement vertical (pas) effectué lors d'un saut
int jumpCounter = 0; // Permet de gérer la courbe du saut (passage du temps du saut)
int nbJump = 0;      // Nombre d'appui sur B pour sauter qui doit être plus petit que le nombre de sauts autorisés
bool jump = false;    // Variable indiquant si on est en train de sauter

/*----------RECTANGLES----------*/

struct rect {
  int x;          // Position en X du rectangle
  int y;          // Position en Y du rectangle
  int widthrect;  // Largeur du rectangle
  int heightrect; // Hauteur du rectangle
};

/*----------PERSONNAGE----------*/

int directionH = STOP;
int directionV = STOP;
rect rectP = {0, 50 - PERSO, PERSO, PERSO};

/*----------PLATEFORMES---------*/

rect rectangles[Nb_rectangles] = {
  {-20, 50, 90, 14},
  {70, -20, 20, 70},
  {70, 50, 10, 14},
  {0, 30, gb.display.width() - 25, 4},
};

void setup()
{
  gb.begin();
}


// S'il y a eu collision on test si il a eu lieu horizotalement en fonction de la direction
boolean testcollisionH( int xr1p1, int xr1p2, int xr2p1,  int xr2p2, int dirH ) {
  int test = 0;
  if (xr1p1 > xr2p1 && xr1p2 < xr2p2) 
    test = 2;
  else {
    if (dirH == DROITE && xr1p2 > xr2p1)  {
      test = 1;
    }
    if (dirH == GAUCHE && xr1p1 < xr2p2)  {
      test = 1;
    }
  }
  return test;
}

// En cas de collision on vérifie s'il a eu lieu verticalement en fonction de la direction
boolean testcollisionV( int yr1p1, int yr1p2, int yr2p1,  int yr2p2, int dirV ) {
  int test = 0;
  if (yr1p1 > yr2p1 && yr1p2 < yr2p2) 
    test = 2;
  else {
    if (dirV == BAS && yr1p2 > yr2p1)  {
      test = 1;
    }
    if (dirV == HAUT && yr1p1 < yr2p2)  {
      test = 1;
    }
  }
  return test;
}

void loop()
{
  while (!gb.update());
  gb.display.clear();

  posXrecent = rectP.x;
  posYrecent = rectP.y;

  /*-----------CONTROLES----------*/

  /*--------DIRECTION--------*/

  if (gb.buttons.repeat(BUTTON_RIGHT, 0) && (rectP.x + rectP.widthrect) < gb.display.width() ) {
    directionH = DROITE;
    posXrecent += PAS;
  }

  if (gb.buttons.repeat(BUTTON_LEFT, 0) && ( rectP.x) > 0) {
    posXrecent -= PAS;
    directionH = GAUCHE;
  }

  /*-----------JUMP----------*/

  if ((gb.buttons.pressed(BUTTON_B)) && (nbJump < NbSautsMax)) {
    jump = true;
    jumpSpeed = -5;
    nbJump += 1;
    if ((gb.buttons.released(BUTTON_B)) && (jumpSpeed < 0)) {
      jumpSpeed /= 2;
    }
    directionV = HAUT;
  }

  /*-------------ACTIONS------------*/

  /*-----------JUMP----------*/

  if (jump == true) {
    if (jumpSpeed < 0) directionV = HAUT; else directionV = BAS;
    posYrecent += jumpSpeed;
    jumpCounter += 1;
    if ((jumpCounter % 2) == 0) {
      jumpSpeed += 2;
    }

  }

  /*-----------COLLISIONS----------*/

  /*------------MUR----------*/

  for (int i = 0; i < Nb_rectangles; i++) {
    if (gb.collideRectRect(posXrecent, posYrecent, rectP.widthrect, rectP.heightrect, rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect)) {
      int res;
      res = testcollisionV(posYrecent, posYrecent + rectP.heightrect, rectangles[i].y, rectangles[i].y + rectangles[i].heightrect, directionV); 
      if (res > 0) {
        if (res < 2 && directionV == HAUT)   {
          posYrecent = rectangles[i].y + rectangles[i].heightrect;
          if (jumpSpeed < 0) jumpSpeed = 1;
          directionV = BAS;
        } else {
          if (res < 2) {
          posYrecent = rectangles[i].y - rectP.heightrect;
          directionV = STOP;
          jump = false;
          nbJump = 0;
          jumpCounter = 0;
          jumpSpeed  = 0;
          }
        }
      } else if (testcollisionH(posXrecent, posXrecent + rectP.widthrect, rectangles[i].x, rectangles[i].x + rectangles[i].widthrect, directionH)< 2) {
        if (directionH == DROITE) posXrecent = rectangles[i].x - rectP.widthrect;
        if (directionH == GAUCHE) posXrecent = rectangles[i].x + rectangles[i].widthrect;
        directionH = STOP;
        i = Nb_rectangles;
      }
    }
  }

  // Sécurité de sortie d'écran
  if ((posXrecent + rectP.widthrect) >= gb.display.width()) {
    posXrecent = gb.display.width() - rectP.widthrect;
    directionH = STOP;
  }
  if ((posXrecent) <= 0) {
    posXrecent = 0;
    directionH = STOP;
  }
  if ((posYrecent + rectP.heightrect) >= gb.display.height()) {
    posXrecent = gb.display.height() - rectP.heightrect;
    directionV = STOP;
    jump = false;
  }
  if ((posYrecent) <= 0) {
    posYrecent = 0;
  }
  rectP.x = posXrecent;
  rectP.y = posYrecent;
  directionH = STOP;
  directionV = STOP;



  /*------------AFFICHAGE----------*/

  /*----------PERSO---------*/

  gb.display.fillRect(rectP.x, rectP.y, rectP.widthrect, rectP.heightrect);

  /*-----------MUR----------*/

  for (int i = 0; i < Nb_rectangles; i++) {
    gb.display.fillRect(rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect);
  }

  gb.display.print("X:");   gb.display.print(posXrecent);
  gb.display.print(";Y: "); gb.display.println(posYrecent);
  gb.display.print("DirH:"); gb.display.print(directionH);
  gb.display.print(";DirV:"); gb.display.print(directionV);

}


C'est vite fait, mais je pense que l'approche n'est pas bonne est il y a des cas particulier.

Maintenant je pense avoir compris ce que tu voulais faire mais je pense que tu devrais regarder plutôt le code de dn ou d'oubliettes pour avoir une approche plus pratique dans les faits. Pareil pour les bordures extérieures, je suis resté sur ton système de blocs mais si tu veux en fait délimiter une zone de jeu, fixer la valeur maxX et maxY serait, je pense plus efficace (si j'ai bien compris ce que tu voulais faire). Le système d'§Oubliettes de geed est un peu différent mais adaptable. Tu as SuperCrateMeta aussi d'Aurélien mais pour DN et SuperCrateMeta, il te faut quand même bien analyser le code car il est assez grand et c'est encore pire pour dn, très bien programmé mais sans doute un peu complexe à analyser pour tout comprendre, mais bon globalement, tu peux gérer tes déplacements dans une grille où tu représente tes niveaux

Un niveau ressemblerait à une position que peut prendre le personnage

       1   2   3    4   5   6    7   8   9   10   11   12

1 |  2   0   0    0   0    0   0   0  0     0    0      2

2 |  2  0    0    0   0    0   0   0  0     0    0      2

3 |  2  1    1   1   0    0   1    1  1    1     1      2

4 |  2  0   0   0    0    0   0    0   0   0     0      2

5 |  2  1   1   1    1    1   1    1  1    1     1      2


Les 2 représentent des mur verticaux infranchissables et les 1 des passerelles 

Si le personnage est sur une passerelle il ne tombe pas, sinon il tombe

Le personnage peut sauter il est bloqué verticalement si une passerelle se trouve au dessus de lui mais peut sauter horizontalement (B + dir) 

Le personnage est bloqué horizontalement s'il y a un mur dans la direction où il va


Voilà, ça te permet de gérer les déplacements sans avoir à gérer les collisions mais bon, le système des collisions peut fonctionner aussi. Dans le programme que je t'ai mis, il fonctionne à peu près mais les conditions sont à améliorer car le système que je t'ai mis n'est pas robuste et peut facilement bugguer et bloquer le personnage.


Dans mon précédent programme, il y avait plusieurs problème dont une grosse bêtise: le passage des int en byte car j'avais oublié que les bytes n'étaient pas signés et du coup vu comment je les utilisais -1 devenait 255... Pas terrible dans ce cas...  ;)

IceCrew

5 years ago

Salut, 

merci pour la réponse et le programme !

Je vais essayer de faire par un système de map(comme par exemple pour le programme Blockdude). Il faut juste que j'essaye de comprendre les bytes car je ne les ais jamais utilisés avec du c dans un programme...

Mais encore merci pour tout tes conseils !

IceCrew

NEW 5 years ago

jicehel jicehel

Salut, 

merci pour la réponse et le programme !

Je vais essayer de faire par un système de map(comme par exemple pour le programme Blockdude). Il faut juste que j'essaye de comprendre les bytes car je ne les ais jamais utilisés avec du c dans un programme...

Mais encore merci pour tout tes conseils !

jicehel

NEW 5 years ago

Mince je m'aperçois que je n'ai pas dû valider ma dernière réponse.. Bon je ne remets pas tout ce que je t'avais mis car le plus important c'était que je te conseillais de regardais un code à adapter légèrement: https://openclassrooms.com/forum/sujet/gestion-collision-et-deplacement-de-mario et lire des tutos super bien fait. Il y en a un que je ne retrouve plus mais l'autre est suffisant je pense: https://jeux.developpez.com/tutoriels/tile-mapping-construction-niveau/simple-personnage/

C'est le type de méthode utilisée dans Oubliettes par exemple et je pense que c'est la meilleure.

Si tu arrives à la mettre en oeuvre, n'hésites pas à faire un tuto sur la construction d'un jeu de plateforme. Pour le moment, il n'y en a pas. S'il y a des imperfections dans ton tutos, on pourra t'aider à le corriger et ça servira aux autres qui débutent et voudraient également en faire un et vont avoir exactement les même problèmes. 

IceCrew

NEW 5 years ago

@jicehel

Je te remercie pour les liens, ils sont très utiles et complets :) (cependant ils utilisent la librairie sdl qui n'est pas disponible sur arduino donc je continue à chercher haha)

Cependant j'aurai une question : les sous programmes avec arduino c'est comme en c ? (un fichier c avec le main, un autre .c avec la description des variables (void ...) et un header ?)

ou il faut tous les mettre en .ino ?

ou il faut mettre un en .ino et les deux autres en .h et .c ?

jicehel

NEW 5 years ago

tu as les .ino et les .h  En fait tu dois surtout avoir ton .ino avec le même nom que ton répertoire. Après il ouvrira les autres .ino et .h qu'il trouve et même les .c si je ne m'abuse. Perso, je mets les .ino et les .h dedans mais tu peux les créer directement dans l'IDE Arduino.