Collisions - By BlatteNote

Author :  BlatteNote

bonsoir,


j'aimerais dĂ©placer un block de 4x4 pixels avec les flĂšches de la croix et faire en sorte que lorsque l'on touche un bord (droit, haut, gauche, bas) le block s'arrete automatiquement (donc il ne repart pas dans l'autre sens) et ne traverse pas les bords de l’écran. et faire peut ĂȘtre un passage secret pour traverser l’écran d'un cotĂ© et rĂ©apparaĂźtre a partir du bord opposĂ©.


Désolé pour cette question si basique, mais je débute avec gamebuino et je trouve ça génial de pouvoir apprendre a coder avec un vrai hardware qui plus est une console, c'est top !


Merci pour vos réponses.

Author :  jicehel

Bonjour BlatteNote et bienvenu dans le monde de la programmation.

Tu as les tutos disponibles ici qui t'explique comment faire: dans https://gamebuino.com/creations/bouncing-ball, tu vas voir comment détecter le bord de l'écran et dans https://gamebuino.com/creations/pong tu peux te servir de la partie contrÎler la raquette pour l'adapter pour contrÎler ton block.

Un petit texte avec des instruction et du texte Ă  remplacer pour t'aider:

void loop() {

  while (gb.update());  gb.display.clear();

    // ContrÎles du déplacement du block ves le bas 

    // Si (gb.buttons.repeat(BUTTON_UP, 0) && block_posY > 0) alors faire block_posY--;

    // Si (gb.buttons.repeat(BUTTON_DOWN, 0) && block_posY < 60) alors faire block_posY++;

    // Si (gb.buttons.repeat(BUTTON_LEFT, 0) && block_posX > 0) alors faire block_posX--;

    // Si (gb.buttons.repeat(BUTTON_RIGHT, 0) && block_posX < 76) alors faire block_posX++;

    // Afficher le block
}


Author :  BlatteNote

Merci beaucoup pour les explications, j'ai rĂ©ussi a mettre les 4 collisions en plus du dĂ©placement du block. je vais rĂ©flĂ©chir pour les passages secrets, l'affichage de pixel qui seront eux mĂȘme a programmer en collisions.

Je pense que les collisions sont la base de tout jeux ...

PS: les 2 liens ne fonctionnent pas chez moi.

Author :  jicehel

Pour le premier lien, c'est normal puisqu'il avait pris la virgule avec... j'ai retiré la virgule dans le lien. Normalement, ça devrait marcher. Pour le deuxiÚme, je ne vois pas. Chez moi, ça marche bien. A voir pour les autres si ça marche et que ça ne marche pas pour toi c'est que tu dois avoir es paramétrages de sécurité trop élevés sur ton poste mais je n'y crois pas trop. En tous cas, regardes bien les premiers tutos ils sont trÚs bien (enfin je trouve), ça t'aidera bien à commencer. Pour tes pixels, une piste: tu mets leurs coordonnées dans un tableau et tu testes la collisions entre ton block et les éléments du tableau. Les tableaux sont abords un peu plus loin dans les tutos. Prends le temps de les faire tranquillement, tu gagnera du temps aprÚs dans la réalisation de ton jeu  ;)

Author :  BlatteNote

Effectivement les 2 liens fonctionnent bien. Merci pour la piste et je vais continuer les tutos pour en savoir plus sur les collisions.

Author :  BlatteNote

Je rĂ©flĂ©chis au niveau des collisions avec des murs de pixels, je crois qu'il faut mettre leur coordonnĂ©s dans 2 tableaux ([CoordonnĂ©e X], et [CoordonnĂ©e Y] (ce qui peu ĂȘtre long ... mais aprĂšs il "suffit" de faire une boucle For pour rĂ©aliser les collision de tout les 4 cotĂ©s des pixels sur tout le tableau ? 

Faut'il remplir le tableau positions par positions ou il y a un moyen de faire plus rapide au niveau de l’implĂ©mentation du tableau ?

juste niveau logique,

int [positionpixelX] = {de pixel 0 à (pixel 80-largeurpixel)} //et mĂȘme rajouter &&, || ...
int [positionpixelY] = {de pixel 0 à (pixel 64-largeurpixel)} //idem
Ceci donnera un écran rempli de pixels (c'est juste pour l'exemple), mais comment implémenter le de, à dans un tableau ?

DĂ©solĂ© pour toutes ces questions, j’espĂšre ne pas ĂȘtre trop ennuyeux.

Author :  jicehel

Oui tu peux directement tester si une zone (un rectangle) touche en autre zone, c'est expliqué dans le tuto sur le pong (collision entre la balle et la raquette).

var rect1 = {x: 5, y: 5, width: 50, height: 50}
var rect2 = {x: 20, y: 10, width: 10, height: 10}

if (rect1.x < rect2.x + rect2.width &&   rect1.x + rect1.width > rect2.x &&   rect1.y < rect2.y + rect2.height &&   rect1.height + rect1.y > rect2.y) {    // collision détectée !
}

Tu test si l'abscisse du rectangle 1 est à gauche du bord droit de rectangle 2 (rect2.x + rect2.width)  et que le bord droit du rectangle 1 est bien à droite du bord gauche du rectangle 2 puis tu fais pareil pour l'ordonnée. Essayes pour mieux comprendre en choisissant rectangle 1 et  sur l'image si dessous et en testant.


Résultat de recherche d'images pour "équation test collision entre rectangles"

Author :  BlatteNote

je vais essayer de comprendre tout ça demain, j'ai testé rapidement et ça n'a pas fonctionné comme prévu.

Je comprend l'idée pour afficher les 2 variables, mais j'ai pas la syntaxe. Pourquoi utilisez vous var pour déclarer une variable ? en C c'est pas plutÎt int ou const int ? mais j'aimerais savoir comment faire pour que :

     var rect1 = {x: 5, y: 5, width: 50, height: 50}
     var rect2 = {x: 20, y: 10, width: 10, height: 10}

donc pour rect1: commencer a le tracer a 5 pixels vers la droite (de l'origine qui est a  0,0 en haut a droite) et 5 vers le bas puis lui donner la taille de 50 pixels de large par 50 pixels de hauteur...

comment faire fonctionner cette "méthode" ?

PS : c'est peu ĂȘtre un gb.display.fillRect() en variable ? ou gb.display.drawRect() ? a vrai dire je comprends pas trop la difference entre ces deux fonctions ?


Author :  jicehel

LĂ , c'est juste pour montrer, si tu veux l'Ă©crire en c proprement, tu peux faire comme expliquĂ© ici: https://gamebuino.com/creations/structurer-les-objets-de-votre-programme (J'aurais dĂ» l'Ă©crire comme ça directement, sur le coup ça ma semblĂ© ĂȘtre une bonne idĂ©e mais j'avoue que ça embrouille plus qu'autre chose de mettre une autre syntaxe, dĂ©solĂ©...)

Pour la Meta, ça donnerait: 

struct s_rect{int x; int y; int width; int height;}

s_rect rect1= {5,5,50,50};

s_rect rect2 = {20,10,10,10};

Ce n'est pas beaucoup plus compliqué que ce que j'ai mis dans mon exemple et ça ne t'aurais pas embrouillé. Bonne continuation ;)


Author :  BlatteNote

Bonsoir,

aprĂšs avoir essayer, je ne comprends pas trop oĂč mettre la ligne :


struct s_rect{int x; int y; int width; int height;};     avant le void setup ?

s_rect rect1= {5,5,50,50};

s_rect rect2 = {20,10,10,10};


et les 2 rect_1 et rect_2   au mĂȘme endroit que la ligne struct ?


quand est t'il de la bonne syntaxe du If pour tester les collisions ? et comment peut t'on afficher les rectangles ? avec un gb.display.fillRect(rect_1); ?


Author :  BlatteNote

je suis allé sur la page : https://gamebuino.com/creations/structurer-les-objets-de-votre-programme , mais je ne comprends pas tout et je ne comprends surtout pas comment vous passer de :

    struct s_balle{int posX; int posY; int vitesseX; int vitesseY; int taille;};

a :

    s_balle balle = {MargeInitialeBalleX,MargeInitialeBalleY,1,1,3};

?

MargeInitialBallX correspond a int posX ? si oui pourquoi lui donner 2 noms ? ou est-ce peut ĂȘtre un nom dĂ©dier a Gamebuino ? (idem pour MargeInitialBallY ainsi que les raquettes 1 et 2).


Author :  jicehel

OK, attends, je te fais un prog avec tout dedans pour que tu comprennes mieux. D'ailleurs c'est un petit programme sympa sommes toutes pour tester les collisions et mieux les comprendre comment ça marche 'visuellement'. Tu peux rajouter dedans des petits affichages en cas de collisions pour afficher le détail des conditions vérifiées, par exemple.


Là normalement, tu as tout ce qui faut pour pouvoir t'amuser à modifier, triturer, essayer. Amuses toi bien et j'espÚre que ça va t'aider à mettre les choses en place. Surtout, suis bien les tutos de l'académie, ça permet de bien démarrer et de comprendre les premiÚres notions.


Author :  jicehel

Et voilà le code complet donne ça:

#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();
}

// Boucle principale, dans laquelle on va dĂ©placer rect1 avec les touches et vĂ©rifier s’il rentre en collision avec rect2
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) rect1.x–;
if (gb.buttons.repeat(BUTTON_RIGHT, 0) && (rect1.x + rect1.widthrect) < 80) rect1.x++;
if (gb.buttons.repeat(BUTTON_UP, 0) && rect1.y > 0) rect1.y–;
if (gb.buttons.repeat(BUTTON_DOWN, 0) && (rect1.y + rect1.heightrect) < 64) rect1.y++;

// Test de collision
if (rect1.x < rect2.x + rect2.widthrect && rect1.x + rect1.widthrect > rect2.x && rect1.y < rect2.y + rect2.heightrect && rect1.heightrect + rect1.y > rect2.y)
{ // collision détectée !
gb.display.setCursor(20, 5);
gb.display.print(“Collision”);
}

// 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);
}

Author :  BlatteNote

MERCI, je m'amuse avec , j'ai rajouter un conteur et rajouter des briques qui on la mĂȘme collisions. en ce moment j'essaye de faire en sorte que le block (ou balle) ai le mĂȘme systĂšme de collisions sur les bords du rect2 qu'il l'aurait sur les bords de l’écran, autrement dit que le rect1 ne traverse pas le rect2 mĂȘme en le contournant.

Je comprends mieux la notion de struct aussi.

Author :  jicehel

Super  ;)  C'est la base de beaucoup de choses. Si tu arrives à faire ce que tu veux obtenir, alors ce sera un succÚs et je sais le plaisir que ça procure...

Author :  BlatteNote

je bidouille un peu dans tout les sens mais je n'arrive pas a faire les collisions autours du block rect2. :-/


Author :  jicehel

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);
}

Author :  BlatteNote

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.


Author :  jicehel

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.


Author :  jicehel

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);
}
}