Les rebonds (tutoriel collectif)

Bon vous avez suivi l’étape 3 du workshop 2 (Pong), vous savez donc comment fonctionne l’écran, vous savez afficher un carré à une position donnée et le faire rebondir à l’écran. Si vous avez oublié, relisez le ici : https://gamebuino.com/fr/academy/workshop/make-your-very-first-games-with-pong/bouncing-ball

Après une balle carré faisons rebondir une balle ronde
Bien, maintenant, nous allons travailler sur les rebonds d’une balle.
Nous allons afficher une grosse balle d’un rayon de 3 pixels à l’aide de l’instruction : fillCircle( int16_t x , int16_t y , int16_t r )

Cercle_sur_ecran

Reprenons le code que nous avions à la fin de l’étape 3 du Workshop mais à la différence que la balle rebondira sur le bord gauche lorsque la position en X sera inférieure ou égale au rayon de la balle.

collision_gauche

Note : pensez toujours bien à mettre des sécurité. Par exemple ici, nous pourrions faire le rebond lorsque la position en X est égale au rayon car la vitesse est de 1 mais si plus tard nous décidons d’avoir une vitesse supérieure, nous pourrions avoir une position qui ne passe jamais par cette valeur mais directement d’une valeur supérieure à une valeur inférieure. Blindez votre code, prévoyez des sécurité.

Au début comme nous l’avons vue dans le tutoriel, nous avons une vitesse en X positive dans notre code, la balle va donc aller vers la droite. Si nous voulons la faire rebondir sur le bord droit, nous devons le faire lorsque la position de la balle en X est égale à la position en X du bord droit moins R.

collision_droite

Code :

#include <Gamebuino-Meta.h>

#define RAY 5
#define SPEED 3

int positionX = 32;
int speedX = SPEED;

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

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

  positionX = positionX + speedX;
  
  // Si la balle atteint ou dépasse le bord gauche
  if(positionX < RAY){
    // On part à droite
    speedX = SPEED;
    positionX = -(positionX - RAY - 1);
  }

  // Si la balle atteint ou dépasse le bord droit
  if(positionX > gb.display.width() - RAY){
    // On part à gauche
    speedX = -SPEED;
    positionX = gb.display.width() + gb.display.width() - (positionX + RAY + 1); 
  }

  gb.display.print("positionX: ");
  gb.display.print(positionX);
  gb.display.print("\nspeedX: ");
  gb.display.print(speedX);

  // draw a red circle
  gb.display.setColor(RED);
  gb.display.fillCircle(positionX, 25, RAY);
}

Bien, comme exercice : faites rebondir la balle verticalement puis ajoutez une vitesse horizontale et une vitesse verticale et gérer les rebond horizontaux et verticaux
Pour ceux qui connaissent la programmation orientée objet, faites une version de ce programme en POO avec la classe Balle. J’attends vos codes :blush:

Testons si notre balle rentre en collision avec un point
Pour dessiner un point à l’écran (pixel en anglais), nous avons l’instruction drawPixel( int16_t x , int16_t y [, Color] ).
Pour détecter la collision entre un point et un disque, nous avons l’instruction gb.collide.pointCircle ( int16_t pointX , int16_t pointY , int16_t centerX , int16_t centerY , int16_t r ).

Nous allons donc reprendre le code précédent et lui ajouter un point. Nous testerons si ce point est touché par la « boule » rebondissante. Si oui, il y a collision et la balle inverse sa direction.

Code :

#include <Gamebuino-Meta.h>

#define RAY 5
#define SPEED 3

int8_t positionX = 32;
int8_t positionY = 25;
int8_t speedX = SPEED;
int8_t speedY = SPEED;

int8_t pointX = 54;
int8_t pointY = 50;

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

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

  // --- ENTREES --- //

  // - MISE A JOUR - //
  positionX = positionX + speedX;
  positionY = positionY + speedY;

    if (gb.collide.pointCircle(pointX, pointY, positionX, positionY, RAY)) {
    positionX = positionX - speedX;
    positionY = positionY - speedY;  
    float tempSpeedX = speedX;
    float tempSpeedY = speedY;  

    while(gb.collide.pointCircle(pointX, pointY, positionX + tempSpeedX, positionY + tempSpeedY, RAY)) {
       tempSpeedX = 0.5 * tempSpeedX;
       tempSpeedY = 0.5 * tempSpeedY; 
    }
    positionX = positionX + tempSpeedX;
    positionY = positionY + tempSpeedY;
    speedX = -speedX;
    speedY = -speedY;

  } else {
 
      // Si la balle atteint ou dépasse le bord gauche
      if(positionX < RAY){
          // On part à droite
          speedX = SPEED;
          positionX = -(positionX - RAY - 1);
      }

      // Si la balle atteint ou dépasse le bord droit
      if(positionX > gb.display.width() - RAY){
            // On part à gauche
            speedX = -SPEED;
            positionX = gb.display.width() + gb.display.width() - (positionX + RAY + 1); 
      }

      // Si la balle atteint ou dépasse le bord haut
      if(positionY < RAY){
            // On part vers le bas
            speedY = SPEED;
            positionY =  -(positionY - RAY - 1);
      }

      // Si la balle atteint ou dépasse le bord bas
      if(positionY > gb.display.height() - RAY){
            // On part vers le haut
            speedY = -SPEED;
            positionY = gb.display.height() + gb.display.height()-(positionY + RAY +1); 
      }
  }

  // - AFFICHAGE - //

  gb.display.clear();

  gb.display.print("X: ");
  gb.display.print(positionX);
  gb.display.print("   Y: ");
  gb.display.print(positionY);
  gb.display.print("\nspeedX: ");
  gb.display.print(speedX);
  gb.display.print("   \nspeedY: ");
  gb.display.print(speedY);
     
  // draw a red circle
  gb.display.setColor(RED);
  gb.display.fillCircle(positionX, positionY, RAY);

  // draw a blue point
  gb.display.drawPixel(pointX,pointY,BLUE); 
    
}

Résultat:
BouncingBall

Conclusion de cette première partie:
Voilà, nous ferons d’autres tests de collisions bientôt. Amusez-vous, faites moi vos retours et les améliorations que vous verriez. Si vous le souhaitez reproduisez ce code en le passant en POO (classes : point et balle)
Une fois la classe point définit, faites un tableau de 5 points et gérez les collisions. Si la balle touche 2 point en même temps ou un point et un bord, quoi doit-elle faire. Quels mécanismes mettaient vous en œuvre pour gérer ces situations ?
Essayez, j’attends vos codes, vos questions et vos suggestions.

2 Likes

Merci @Jicehel
C’est un très bon tuto, avec de belles illustrations.

1 Like

Merci, j’ai prévu d’y ajouter une suite plus tard si je vois que ça intéresse du monde et qu’ils font leurs exercices / propose des codes / améliorations etc …En fait ce tuto par de 2 sujets pour le moments: gestion du rebond en changeant la direction et gestion des collisions. Le prochain, ce sera la gravité, le rebond et les vitesse horizontale et verticale mais bon, je verrais avant si ça vaut le coup par ce que du monde est intéressé et a envie de participer, proposer, modifier, triturer, :wink:

1 Like