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 )
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.
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.
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
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:
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.