collisions

Général

jicehel

NEW il y a 5 ans

Bon, je te donne la solution: Tu sort la procédure de test de collision et tu rajoutes le test de la position où serait le rectangle si le déplacement avait lieu avant de le faire. S'il y a collision, tu refuses le déplacement. Bon, il faut sans doute ajuster les limites pour ne pas autoriser le collision de la bordure, mais ça je te laisse regarder, c'est assez simple à mettre en place, je pense. A toi de voir, testes, farfouilles et dis moi si tu as des problèmes.

#include <Gamebuino-Meta.h>

// Définition de la structure s_rect avec les composants d'un rectangle
// Le point supérieur gauche avec ses coordonnées x,y
// Sa largeur et sa hauteur en points
// Je rajoute une composante qui va être la couleur du rectangle
struct s_rect {
  int x;
  int y;
  int widthrect;
  int heightrect;
  int couleur;
};

// Définition des 2 rectangles de type s_rect
s_rect rect1 = {5, 5, 15, 15, 1};
s_rect rect2 = {50, 10, 10, 10, 2};


// Procédure de setup où pour le moment, on initialise juste la META
void setup() {
  gb.begin();
}


// Fonction retournant vrai en cas de collision
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)  { // collision détectée !
    test = true;
  }
  return test;
}



// Boucle principale, dans laquelle on va déplacer rect1 avec les touches et vérifier s'il rentre en collision avec rect
void loop() {
  while (!gb.update());
  gb.display.clear();

  // Contrôles du déplacement de rect1 avec les touches
  if (gb.buttons.repeat(BUTTON_LEFT, 0) && rect1.x > 0)
    if (!testcollision(rect1.x - 1, rect1.y, rect1.x + rect1.widthrect - 1, rect1.y + rect1.heightrect, rect2.x, rect2.y, rect2.x + rect2.widthrect, rect2.y + rect2.heightrect)) rect1.x--;
  if (gb.buttons.repeat(BUTTON_RIGHT, 0) && (rect1.x + rect1.widthrect) < 80)
    if (!testcollision(rect1.x + 1, rect1.y, rect1.x + rect1.widthrect + 1, rect1.y + rect1.heightrect, rect2.x, rect2.y, rect2.x + rect2.widthrect, rect2.y + rect2.heightrect)) rect1.x++;
  if (gb.buttons.repeat(BUTTON_UP, 0) && rect1.y > 0)
    if (!testcollision(rect1.x, rect1.y - 1, rect1.x + rect1.widthrect, rect1.y + rect1.heightrect - 1, rect2.x, rect2.y, rect2.x + rect2.widthrect, rect2.y + rect2.heightrect)) rect1.y--;
  if (gb.buttons.repeat(BUTTON_DOWN, 0) && (rect1.y + rect1.heightrect) < 64)
    if (!testcollision(rect1.x, rect1.y + 1, rect1.x + rect1.widthrect, rect1.y + rect1.heightrect + 1, rect2.x, rect2.y, rect2.x + rect2.widthrect, rect2.y + rect2.heightrect)) rect1.y++;

  // On dessine rect1
  gb.display.setColor(rect1.couleur);
  gb.display.fillRect(rect1.x, rect1.y, rect1.widthrect, rect1.heightrect);
  // On dessine rect2
  gb.display.setColor(rect2.couleur);
  gb.display.fillRect(rect2.x, rect2.y, rect2.widthrect, rect2.heightrect);
}

BlatteNote

NEW il y a 5 ans

Le code marche a la perfection ! Dommage que je n'arrive pas a appliquer les collisions a un 2ème block voir a d'autres n-èmes block.

On dirait que vous avez écrit les collisions dans les if de déplacement. mais Y a t'il une façon sans tester de valeur booléenne ? une fonction qui permet d'ajuster les collisions a d'autres blocks de façon plus rapide ?

Merci pour votre aide.


jicehel

NEW il y a 5 ans

OK, dans ce cas prends y toi autrement. Je te donne le principe de la solution mais je ne t'envois pas le code ce soir (il est emps que j'aille me coucher et je pense que tu dois pouvoir trouver.

Solution: dans ton test des touches, tu ne mets pas à jour les informations de rect1 (x et y) mais 2 variable comme par exemple tempX et tempY que tu met à jour avec la valeur de la position qu'aurait le rectangle sil se déplaçait

Tu fais ensuite une boucle qui va tester pour chacun de tes obstacle s'il y a collision. Si non, tu mets à jour rect1.x avec la valeur   de tempX et rect1.y avec TempY sinon, tu ne fais rien.

Astuce pour tester la collision avec un ensemble de rectangles, stock les dans un tableau.


jicehel

NEW il y a 5 ans

J'espère que tu as pu regarder. Avant de me remettre dans les cartons, je te donne la solution si tu sèches.

Tu peux procéder comme ça par exemple:

#include <Gamebuino-Meta.h>

// Définition de la structure s_rect avec les composants d'un rectangle
// Le point supérieur gauche avec ses coordonnées x,y
// Sa largeur et sa hauteur en points
// Je rajoute une composante qui va être la couleur du rectangle
struct s_rect {
  int x;
  int y;
  int widthrect;
  int heightrect;
  int couleur;
};

// Définition des 2 rectangles de type s_rect
s_rect rect1 = {5, 5, 10, 10, 1};
s_rect rectangles[5] = {{50, 10, 3, 3, 2},
  {10, 50, 3, 3, 3},
  {50, 40, 3, 3, 4},
  {70, 30, 3, 3, 5},
  {40, 40, 3, 3, 6}
};


// Procédure de setup où pour le moment, on initialise juste la META
void setup() {
  gb.begin();
}


// Fonction retournant vrai en cas de collision
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)  { // collision détectée !
    test = true;
  }
  return test;
}



// Boucle principale, dans laquelle on va déplacer rect1 avec les touches et vérifier s'il rentre en collision avec rect
void loop() {
  int X_actuel;
  int Y_actuel;
  while (!gb.update());
  gb.display.clear();
  X_actuel = rect1.x;
  Y_actuel = rect1.y;
  // Contrôles du déplacement de rect1 avec les touches
  if (gb.buttons.repeat(BUTTON_LEFT, 0) && rect1.x > 0)  X_actuel--;
  if (gb.buttons.repeat(BUTTON_RIGHT, 0) && (rect1.x + rect1.widthrect) < 80)  X_actuel++;
  if (gb.buttons.repeat(BUTTON_UP, 0) && rect1.y > 0)Y_actuel--;
  if (gb.buttons.repeat(BUTTON_DOWN, 0) && (rect1.y + rect1.heightrect) < 64) Y_actuel++;
  boolean deplacement_ok = true;
  for (int i = 0; i < 5; i++)
    if (testcollision(X_actuel, Y_actuel, X_actuel + rect1.widthrect, Y_actuel + rect1.heightrect, rectangles[i].x, rectangles[i].y, rectangles[i].x + rectangles[i].widthrect, rectangles[i].y + rectangles[i].heightrect)) {
      deplacement_ok = false;
    }
  if (deplacement_ok) {
    rect1.x = X_actuel;
    rect1.y = Y_actuel;
  }
  // On dessine rect1
  gb.display.setColor(rect1.couleur);
  gb.display.fillRect(rect1.x, rect1.y, rect1.widthrect, rect1.heightrect);
  // On dessine les autres rectangles
  for (int i = 0; i < 5; i++) {
    gb.display.setColor(rectangles[i].couleur);
    gb.display.fillRect(rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect);
  }
}

BlatteNote

NEW il y a 5 ans

Merci. je regarderai tout ça demain.

PS: Au fait ... ce langage Informatique Gamebuino, ce serai plutôt du C ou du C++ ?

Bon courage pour les cartons ;-)

jicehel

NEW il y a 5 ans

Si si bien sûr, ça en est mais avec des commandes en plus ajoutées par la librairie gb pour commander plus facilement le matériel.

Tiens moi au courant et au début, essayes sans regarder la solution pour  chercher et essayer de trouver ta solution. Après regardes la solution si tu galères.

BlatteNote

il y a 5 ans

Je me demande si il y a une possibilité d'appliquer un "visible" ou "invisible" sur un élément ? avec un boolean ?

comme par exemple rendre un rectangle invisible (donc le faire disparaître) quand on le touche avec le rect1 ? ou même le faire devenir invisible et le remettre autre part (comme derrière le rect1 et faire en sorte qu'il le suive ?)

BlatteNote

NEW il y a 5 ans

jicehel jicehel

Je me demande si il y a une possibilité d'appliquer un "visible" ou "invisible" sur un élément ? avec un boolean ?

comme par exemple rendre un rectangle invisible (donc le faire disparaître) quand on le touche avec le rect1 ? ou même le faire devenir invisible et le remettre autre part (comme derrière le rect1 et faire en sorte qu'il le suive ?)

jicehel

NEW il y a 5 ans

Bien sûr tu peux, tu peux ajouter une propriété "visible" dans ta structure rectangle et faire que s'il y a collision, tu passes le rectangle à "visible" = false. Tu n'affiches les rectangles que quand visible = true. Pour que ce soit plus logique, ne faire un test de collision que si visible ="true" aussi.

Je n'ai pas bien compris ta dernière proposition le rectangle invisible qui suit rect1. S'il le suit, ça n'a d’intérêt que s'il est visible selon moi. Après pour qu'il le suive, c'est faisable si tu veux, je te ferais un code pour ça si tu n'y arrive pas. C'est un peu plus complexe déjà mais rien d'insurmontable mais si tu veux que ce soit propre, il y a plus de cas particuliers à prévoir et tous cas, le truc c'est de changer les propriétés du rectangle quand il y a collision puis que le rectangle ait un autre comportement quand il a été touché une fois.

Je te mets le premier code celui ou les rectangles disparaissent s'ils sont touchés. Je te laisse chercher pour ta dernière proposition, il y a plus de boulot, je  n'ai pas vraiment le temps ni l'envie ce soir mais si tu essayes et que tu galères, expliques ton problème et je t'aiderais.


#include <Gamebuino-Meta.h>

#define visible   true
#define invisible false

// Définition de la structure s_rect avec les composants d'un rectangle
// Le point supérieur gauche avec ses coordonnées x,y
// Sa largeur et sa hauteur en points
// Je rajoute une composante qui va être la couleur du rectangle
struct s_rect {
  int x;
  int y;
  int widthrect;
  int heightrect;
  int couleur;
  boolean affiche;
};

// Définition des 2 rectangles de type s_rect
s_rect rect1 = {5, 5, 10, 10, 1, visible};
s_rect rectangles[5] = {{50, 10, 3, 3, 2, visible},
  {10, 50, 3, 3, 3, visible},
  {50, 40, 3, 3, 4, visible},
  {70, 30, 3, 3, 5, visible},
  {40, 40, 3, 3, 6, visible}
};


// Procédure de setup où pour le moment, on initialise juste la META
void setup() {
  gb.begin();
}


// Fonction retournant vrai en cas de collision
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)  { // collision détectée !
    test = true;
  }
  return test;
}



// Boucle principale, dans laquelle on va déplacer rect1 avec les touches et vérifier s'il rentre en collision avec rect
void loop() {
  int X_actuel;
  int Y_actuel;
  while (!gb.update());
  gb.display.clear();
  X_actuel = rect1.x;
  Y_actuel = rect1.y;
  // Contrôles du déplacement de rect1 avec les touches
  if (gb.buttons.repeat(BUTTON_LEFT, 0) && rect1.x > 0)  X_actuel--;
  if (gb.buttons.repeat(BUTTON_RIGHT, 0) && (rect1.x + rect1.widthrect) < 80)  X_actuel++;
  if (gb.buttons.repeat(BUTTON_UP, 0) && rect1.y > 0)Y_actuel--;
  if (gb.buttons.repeat(BUTTON_DOWN, 0) && (rect1.y + rect1.heightrect) < 64) Y_actuel++;
  boolean deplacement_ok = true;
  for (int i = 0; i < 5; i++)
    if (rectangles[i].affiche) {
      if (testcollision(X_actuel, Y_actuel, X_actuel + rect1.widthrect, Y_actuel + rect1.heightrect, rectangles[i].x, rectangles[i].y, rectangles[i].x + rectangles[i].widthrect, rectangles[i].y + rectangles[i].heightrect)) {
        deplacement_ok = false;
        rectangles[i].affiche = false;
      }
    }
  if (deplacement_ok) {
    rect1.x = X_actuel;
    rect1.y = Y_actuel;
  }
  // On dessine rect1
  gb.display.setColor(rect1.couleur);
  gb.display.fillRect(rect1.x, rect1.y, rect1.widthrect, rect1.heightrect);
  // On dessine les autres rectangles
  for (int i = 0; i < 5; i++) {
    if (rectangles[i].affiche) {
      gb.display.setColor(rectangles[i].couleur);
      gb.display.fillRect(rectangles[i].x, rectangles[i].y, rectangles[i].widthrect, rectangles[i].heightrect);
    }
  }
}



BlatteNote

il y a 5 ans

je vais essayer demain de faire deux tableaux, un pour les collisions "dur" et l'autre pour les collisions "visible/invisible".

Et pour l'autre partie, c’était bien le fait que le block touché suive le rect1 de façon "visible" ? (le block touché deviens invisible et redeviens visible et suis le rect1 tout en étant visible).

Je me pose la question de savoir si on peu comme dans certains logiciels d'animation de dessins, faire en sorte qu'un block suive un path prédéfini ? d'ou pourrai être l’intérêt du "invisible" ?

BlatteNote

NEW il y a 5 ans

jicehel jicehel

je vais essayer demain de faire deux tableaux, un pour les collisions "dur" et l'autre pour les collisions "visible/invisible".

Et pour l'autre partie, c’était bien le fait que le block touché suive le rect1 de façon "visible" ? (le block touché deviens invisible et redeviens visible et suis le rect1 tout en étant visible).

Je me pose la question de savoir si on peu comme dans certains logiciels d'animation de dessins, faire en sorte qu'un block suive un path prédéfini ? d'ou pourrai être l’intérêt du "invisible" ?

jicehel

NEW il y a 5 ans

Oui tu peux suivre un chemin défini. Pour cela tu stocke les coordonnées du chemin à suivre dans un tableau soit à 2 dimensions (X et Y), soit dans un tableau de structures (Avec X et Y aussi mais d'autres informations si besoin). Après tu as des solutions plus complexes comme d'utiliser une liste chaînée mais ça me parait inutile et trop complexe pour que tu commences par ça. (Ce n'est utilisé que dans de rare cas, ça peut réponde à ton besoin mais selon moi c'est superflu comme tu as d'autres solutions beaucoup plus simples).

BlatteNote

NEW il y a 5 ans

Et si le chemin est un cercle suivi par un pixel et que ce chemin soit aussi a tourner autour d'un block? pour ses coordonnées je dois mettre que certaines valeurs dans le tableau ? ou récupérer toutes les coordonnée du cercle ? (peut être en fonction de la qualité du rendu animé et de la ram machine ?

Je veux pas aller trop vite, il faut déjà que j'essaye de coder la collision qui ferait que le block touché devienne invisible et redevienne visible et suive le rect1 tout en étant visible.

jicehel

NEW il y a 5 ans

oui fait simple mais sinon pour ta rotation, tu peux la calculer par rapport à la position de ton rectangle et par rapport au rectangle autour duquel il tourne, le déplacement dans l'espace sera suivi dans le tableau de coordonnées du rectangle qui suivra un chemin défini. Mais tu te compliques un peu la vie à moins que tu saches déjà ce que tu veux faire. Réfléchis bien à ce que tu veux faire et écrit le. Par exemple le rect 1 va de la position 10,10 à 70,40 en suivant un courbe et les rectangles 3, 4 et 5 tournent autour de lui à des vitesses différentes. Tu vois, j'écris les caractéristiques de ce que je veux obtenir. Il faut encore enrichir la description avec tous les éléments voulus. Tu détailles bien tout ce que tu veux et tu réfléchis à comment est-ce que tu va procéder puis tu commences à l'implémenter petit à petit. D'abord en traçant le rectangle 1 et en lui faisant parcourir la courbe que tu as prévu (un tableau de points précalculés ou en calculant les points à partir de la position du rect1 et d'une équation de courbe.

Quand le résultat te plaira tu rajouteras les autres rectangles en les faisant se déplacer en cercle (ou n'importe quelle autre trajectoire avec une equation pour calculer les valeurs x et y. Il faut un minimum de connaissances en math ou chercher un peu sur Google. Bonne chance.

BlatteNote

NEW il y a 5 ans

en fait je voulais que la rotation du pixel tournant soit automatique (même quand le block "rect1" ne se déplace pas) et que quand le rect1 se déplace il perd un pixel en rotation qui disparaît quand il y a une collision avec un pixel "dur", et il peu "attraper" d'autre pixel qui eux même tournerons autour du rect1 en s'additionnant au pixel non détruits.

jicehel

NEW il y a 5 ans

Je te laisse essayer de le coder pour que tu vois tes progrès et si tu n'y arrives pas. Montres nous ton code et explique là où tu bloque et quelqu'un (moi ou quelqu'un d'autre) t'aidera à réaliser ce que tu souhaites.