Breakout

Creations

JulienGio

5 years ago

This workshop is still going through changes, therefore we only provide it in French. Come back soon :)

View full creation

jicehel

NEW 5 years ago

Très bien Julien  ;)  J'ai trouvé des astuces que j'aurais pu appliquer dans mon casse-briques. Si j'y retouche, je pense que j'utiliserais le collide par exemple.

Sinon quelques petites fautes à corriger:  au début: tu met une fois casse brique (mieux vaut ajouter le s car tu le mets avant et après. Plus bas "en estiment" à corriger en "en estimant". Dans la section "Les briques", il est écrit: "Mais mieux les discerner", je pense qu'un pour a disparu et que tu voulais écrire "Mais pour mieux les discerner". Plus loin: " l'intérieur de deux accolades, n'existe pas à l'extérieur" => " l'intérieur de deux accolades, n'existent pas à l'extérieur". Avant Arc en ciel "vous devrez" => "vous devriez".

Après ce joli tuto j'espère que plein de lecteur auront des idées pour améliorer mon Breakout (casse-briques en anglais).  :D  

Juice_Lizard

NEW 5 years ago

"Un seul point-virgule vous manque et rien n'est compilé." (Lamartine à la plage)

Il faut enlever l'espace en trop dans #include <Gamebuino-Meta.h >

Et corriger les collide.rectRect en collideRectRect

Et là ça marche. Merci pour ce tuto.

Aurélien Rodot

5 years ago

Et corriger les collide.rectRect en collideRectRect

collideRectRect est obsolète, tu devrais mettre ta library à jour et utiliser gb.collide.rectRect :)

Aurélien Rodot

NEW 5 years ago

Juice_Lizard Juice_Lizard

Et corriger les collide.rectRect en collideRectRect

collideRectRect est obsolète, tu devrais mettre ta library à jour et utiliser gb.collide.rectRect :)

Juice_Lizard

5 years ago

Ma bibliothèque est déjà à jour, version 1.1.0, je ne vois pas de version plus récente. Dans votre article "Référence", c'est toujours écrit "collideRectRect".

Juice_Lizard

NEW 5 years ago

Aurélien Rodot Aurélien Rodot

Ma bibliothèque est déjà à jour, version 1.1.0, je ne vois pas de version plus récente. Dans votre article "Référence", c'est toujours écrit "collideRectRect".

Aurélien Rodot

5 years ago

La nouvelle 1.2.0 est maintenant en ligne ! https://github.com/Gamebuino/Gamebuino-META/releases/tag/1.2.0

Il faudra attendre quelques heures pour qu'elle apparaisse directement dans Arduino.

Aurélien Rodot

NEW 5 years ago

Juice_Lizard Juice_Lizard

La nouvelle 1.2.0 est maintenant en ligne ! https://github.com/Gamebuino/Gamebuino-META/releases/tag/1.2.0

Il faudra attendre quelques heures pour qu'elle apparaisse directement dans Arduino.

Grungy

NEW 5 years ago

Bonjour je débute et suis les tuto 1 par un et pour celui-ci je sèche mon casse brique reste tout blanc aucune couleurs arc en ciel, meme en faisant un copié/collé du code...


Codnpix

NEW 5 years ago

Bonjour, merci pour ce tuto ! Je suis arrivé au bout mais je crois que j'ai trouvé une petite erreur, ou alors je n'ai pas saisi quelque chose.. : 

Dans la condition pour vérifier s'il reste des briques  :

for (int x = 0; x < GRILLE_TAILLE; x += 1) {
          for (int y = 0; y < GRILLE_TAILLE; y += 1) {
            if (briques[y][x] == 0) {  // On a trouvé une brique!
              plusDeBriques = false;  // ne pas reinitialiser
            }
          }

est-ce que ça ne serait pas plutôt :" if (briques[y][x] == 1) " au lieu de if (briques[y][x] == 0) ? (Elles existent quand elles sont égales à 1, donc si on en trouve une égale à 1 c'est qu'elle existe encore...

___

Sinon, j'ai fait un essai de calcul pour la vitesse ajoutée en x à la balle pour pouvoir contrôler un peu l'angle avec lequel on la fait rebondir. Le rendu n'est pas très très propre mais ça fonctionne quand même à peu près comme j'imaginais. Je partage mon extrait de code, si vous avez des conseils :).

L'idée est que l'angle avec lequel la balle est renvoyée varie en fonction de la distance entre la balle et le bord de la palette au moment du rebond. Si on tape au centre de la palette la balle rebondit verticalement, si on tape plus ou moins proche du bord gauche, on rebondit plus ou moins vers la gauche, pareil pour la droite...

void update() {
//...
//collisions
    if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, padX, padY, PAD_W, PAD_H) || ballY <= 0) {
      if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, padX, padY, PAD_W, PAD_H)) {

        float dist_edgePad_left = (ballX + BALL_SIZE /2) - padX;//distance balle/côté gauche pad
        float dist_edgePad_right = (padX + PAD_W) - (ballX + BALL_SIZE /2);//distance ball/côté droit pad

        if (dist_edgePad_right > dist_edgePad_left) {
          speedX = min(-1 / dist_edgePad_left, -1);//si la balle est du coté gauche du pad, partir vers la gauche(speeX max = -1)
        }
        else if (dist_edgePad_left > dist_edgePad_right) {
          speedX = min(1 / dist_edgePad_right, 1);//si la balle est du côté droit, partir vers la droite(speeX max = 1)
        } 
        else {
          speedX = 0;
        }
      }

      speedY *= -1;
    }
//...
}

jicehel

NEW 5 years ago

Tu as raison pour le test avec if (briques[y][x] == 1) pour vérifier qu'il y a encore des briques.

Sinon tu t'embêtes à calculer la distance par rapport à la gauche ou à la droite... Est ce vraiment nécessaire ? Tu as déjà le signe si tu calcules par apport au milieu de la raquette... Par contre comme ta raquette est plate, ton rebond devrait se faire juste en inversant la vitesse en y. Pour ton genre de rebond, la raquette devrait être courbe si je ne m'abuse.

Sinon, si tu veux que ta vitesse soit plus réalise, change les vx et vy. Tant qu'ils seront en entier, tu auras des choses bizarre avec les formules que tu appliques.

Bonne chance pour tes dev et n'hésites pas à partager ton résultat. 

PS pou l'équipe et Sylvain: Pour les tutos avec des sujets communs pour que tout le monde puisse partager sa création sans créer des centaines de créations sur le même sujet. Sur une création ou un tuto, l'idée serait de pouvoir créer une création rattachée à ce sujet (qui n'apparaîtrait pas dans les listes de créations).





Codnpix

5 years ago

Merci de ta réponse.

Par contre comme ta raquette est plate, ton rebond devrait se faire juste en inversant la vitesse en y. Pour ton genre de rebond, la raquette devrait être courbe si je ne m'abuse.

L'idée était justement un peu "d'émuler" une surface de raquette un peu courbe. Même si dans la réalité elle reste plate effectivement...

Sinon, si tu veux que ta vitesse soit plus réalise, change les vx et vy. Tant qu'ils seront en entier, tu auras des choses bizarre avec les formules que tu appliques.

J'avais bien passé ballX et speedX en float pour pouvoir y mettre la valeur que je récupère avec "+ ou - 1 / distance_bord_droit_ou_gauche".  Pour speedY je n'y pas touché, c'est toujours 1 ou -1.

J'essaierai de chercher un calcul plus efficace en me basant sur le milieu plutôt que sur les bords.

Voici la totalité de mon code, ce sera plus concret (et plus simple pour tester le résultat peut-être ^^) !

#include <Gamebuino-Meta.h>

bool launched;

//balle
float ballX;
int ballY;
float speedX;
int speedY;
const int BALL_SIZE = 4;

//palette
int padX;
int padY;
const int PAD_W = 14;
const int PAD_H = 3;

//briques
const int GRID_SIZE = 8;
int briques[GRID_SIZE][GRID_SIZE];
const int BRICK_W = gb.display.width() / GRID_SIZE - 2;
const int BRICK_H = 3;

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

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

input();
if (launched) {
  updates();
}
draw();
}


void input() {
    //ENTREES//
    if (gb.buttons.pressed(BUTTON_A)) {
      launched = true;
    }
    if (gb.buttons.repeat(BUTTON_LEFT,0)) {
      movePad("left");
    }
    if (gb.buttons.repeat(BUTTON_RIGHT,0)) {
      movePad("right");
    }
}


void updates() {
    //UPDATES//

    //collisions
    if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, padX, padY, PAD_W, PAD_H) || ballY <= 0) {
      if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, padX, padY, PAD_W, PAD_H)) {

        float dist_edgePad_left = (ballX + BALL_SIZE /2) - padX;//distance balle/côté gauche pad
        float dist_edgePad_right = (padX + PAD_W) - (ballX + BALL_SIZE /2);//distance balle/côté droit pad

        if (dist_edgePad_right > dist_edgePad_left) {
          speedX = min(-1 / dist_edgePad_left, -1);//si la balle est du coté gauche du pad, partir vers la gauche(speeX max = -1)
        }
        else if (dist_edgePad_left > dist_edgePad_right) {
          speedX = min(1 / dist_edgePad_right, 1);//si la balle est du côté droit, partir vers la droite(speeX max = 1)
        } 
        else {
          speedX = 0;
        }
      }

      speedY *= -1;
    }

    else if (ballX + BALL_SIZE >= gb.display.width() || ballX <= 0) {
      speedX *= -1;
    }

    else if (ballY + BALL_SIZE >= gb.display.height()) {
      initGame();
    }

    //collisions briques

    for (int rangee = 0; rangee < GRID_SIZE; rangee++) {
      for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
        if (briques[rangee][colonne] == 0) {
          continue;
        }
        int briqueX =  colonne * (BRICK_W +2) +1;
        int briqueY = rangee * (BRICK_H +2) +1;
        if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, briqueX, briqueY, BRICK_W, BRICK_H)) {
          speedY *= -1;
          briques[rangee][colonne] = 0;//detruire la brique en cas de collision
          //verifier briques restantes
          bool zeroBriques = true;//passera à false si il reste au moins une brique
          for (int x = 0; x < GRID_SIZE; x++) {
            for (int y = 0; y < GRID_SIZE; y++) {
              if (briques[y][x] == 1) {
                zeroBriques = false;
              }
            }
          }
          if (zeroBriques) {
            initGame();
          }
        }
      }
    }
    ballX += speedX;
    ballY += speedY;
}

void initGame() {
  padX = gb.display.width() /2 - 5;
  padY = gb.display.height() -3;
  ballX = padX + PAD_W /2 - BALL_SIZE /2;
  ballY = padY - BALL_SIZE;
  speedX = 0;
  speedY = -1;
  launched = false;

  for (int rangee = 0; rangee < GRID_SIZE; rangee++) {
    for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
      briques[rangee][colonne] = 0;
    }
  }

  for (int rangee = 0; rangee < GRID_SIZE; rangee++) {
    for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
      briques[rangee][colonne] = rangee + 1;
    }
  }
}

void movePad(char dir[6]) {
  if (dir == "left") {
    if (padX <=0) {
      padX = 0;
    } else {
      padX -= 1;
    }
  }
  else if (dir == "right") {
    if (padX + PAD_W >= gb.display.width()) {
      padX = gb.display.width() - PAD_W;
    } else {
      padX += 1;
    }
  } else {
    padX = padX;
  }
}


void draw() {
    //DISPLAY//
  gb.display.clear();
  //paddle 
  gb.display.fillRect(padX, padY, PAD_W, PAD_H);
  //ball
  gb.display.fillRect(ballX, ballY, BALL_SIZE, BALL_SIZE);
  //briques
  const Color rainbow[8] = {WHITE, PURPLE, RED, YELLOW, LIGHTGREEN, GREEN, DARKBLUE, BLUE};
  for (int rangee = 0; rangee < GRID_SIZE; rangee ++) {
    for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
      if(briques[rangee][colonne] == 0) {
        continue;
      }
      gb.display.setColor(rainbow[briques[rangee][colonne] - 1]);
      int briqueX = colonne * (BRICK_W + 2) + 1;
      int briqueY = rangee * (BRICK_H +2) +1;
      gb.display.fillRect(briqueX, briqueY, BRICK_W, BRICK_H);
    }
  }
}

Codnpix

NEW 5 years ago

jicehel jicehel

Merci de ta réponse.

Par contre comme ta raquette est plate, ton rebond devrait se faire juste en inversant la vitesse en y. Pour ton genre de rebond, la raquette devrait être courbe si je ne m'abuse.

L'idée était justement un peu "d'émuler" une surface de raquette un peu courbe. Même si dans la réalité elle reste plate effectivement...

Sinon, si tu veux que ta vitesse soit plus réalise, change les vx et vy. Tant qu'ils seront en entier, tu auras des choses bizarre avec les formules que tu appliques.

J'avais bien passé ballX et speedX en float pour pouvoir y mettre la valeur que je récupère avec "+ ou - 1 / distance_bord_droit_ou_gauche".  Pour speedY je n'y pas touché, c'est toujours 1 ou -1.

J'essaierai de chercher un calcul plus efficace en me basant sur le milieu plutôt que sur les bords.

Voici la totalité de mon code, ce sera plus concret (et plus simple pour tester le résultat peut-être ^^) !

#include <Gamebuino-Meta.h>

bool launched;

//balle
float ballX;
int ballY;
float speedX;
int speedY;
const int BALL_SIZE = 4;

//palette
int padX;
int padY;
const int PAD_W = 14;
const int PAD_H = 3;

//briques
const int GRID_SIZE = 8;
int briques[GRID_SIZE][GRID_SIZE];
const int BRICK_W = gb.display.width() / GRID_SIZE - 2;
const int BRICK_H = 3;

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

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

input();
if (launched) {
  updates();
}
draw();
}


void input() {
    //ENTREES//
    if (gb.buttons.pressed(BUTTON_A)) {
      launched = true;
    }
    if (gb.buttons.repeat(BUTTON_LEFT,0)) {
      movePad("left");
    }
    if (gb.buttons.repeat(BUTTON_RIGHT,0)) {
      movePad("right");
    }
}


void updates() {
    //UPDATES//

    //collisions
    if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, padX, padY, PAD_W, PAD_H) || ballY <= 0) {
      if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, padX, padY, PAD_W, PAD_H)) {

        float dist_edgePad_left = (ballX + BALL_SIZE /2) - padX;//distance balle/côté gauche pad
        float dist_edgePad_right = (padX + PAD_W) - (ballX + BALL_SIZE /2);//distance balle/côté droit pad

        if (dist_edgePad_right > dist_edgePad_left) {
          speedX = min(-1 / dist_edgePad_left, -1);//si la balle est du coté gauche du pad, partir vers la gauche(speeX max = -1)
        }
        else if (dist_edgePad_left > dist_edgePad_right) {
          speedX = min(1 / dist_edgePad_right, 1);//si la balle est du côté droit, partir vers la droite(speeX max = 1)
        } 
        else {
          speedX = 0;
        }
      }

      speedY *= -1;
    }

    else if (ballX + BALL_SIZE >= gb.display.width() || ballX <= 0) {
      speedX *= -1;
    }

    else if (ballY + BALL_SIZE >= gb.display.height()) {
      initGame();
    }

    //collisions briques

    for (int rangee = 0; rangee < GRID_SIZE; rangee++) {
      for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
        if (briques[rangee][colonne] == 0) {
          continue;
        }
        int briqueX =  colonne * (BRICK_W +2) +1;
        int briqueY = rangee * (BRICK_H +2) +1;
        if (gb.collide.rectRect(ballX, ballY, BALL_SIZE, BALL_SIZE, briqueX, briqueY, BRICK_W, BRICK_H)) {
          speedY *= -1;
          briques[rangee][colonne] = 0;//detruire la brique en cas de collision
          //verifier briques restantes
          bool zeroBriques = true;//passera à false si il reste au moins une brique
          for (int x = 0; x < GRID_SIZE; x++) {
            for (int y = 0; y < GRID_SIZE; y++) {
              if (briques[y][x] == 1) {
                zeroBriques = false;
              }
            }
          }
          if (zeroBriques) {
            initGame();
          }
        }
      }
    }
    ballX += speedX;
    ballY += speedY;
}

void initGame() {
  padX = gb.display.width() /2 - 5;
  padY = gb.display.height() -3;
  ballX = padX + PAD_W /2 - BALL_SIZE /2;
  ballY = padY - BALL_SIZE;
  speedX = 0;
  speedY = -1;
  launched = false;

  for (int rangee = 0; rangee < GRID_SIZE; rangee++) {
    for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
      briques[rangee][colonne] = 0;
    }
  }

  for (int rangee = 0; rangee < GRID_SIZE; rangee++) {
    for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
      briques[rangee][colonne] = rangee + 1;
    }
  }
}

void movePad(char dir[6]) {
  if (dir == "left") {
    if (padX <=0) {
      padX = 0;
    } else {
      padX -= 1;
    }
  }
  else if (dir == "right") {
    if (padX + PAD_W >= gb.display.width()) {
      padX = gb.display.width() - PAD_W;
    } else {
      padX += 1;
    }
  } else {
    padX = padX;
  }
}


void draw() {
    //DISPLAY//
  gb.display.clear();
  //paddle 
  gb.display.fillRect(padX, padY, PAD_W, PAD_H);
  //ball
  gb.display.fillRect(ballX, ballY, BALL_SIZE, BALL_SIZE);
  //briques
  const Color rainbow[8] = {WHITE, PURPLE, RED, YELLOW, LIGHTGREEN, GREEN, DARKBLUE, BLUE};
  for (int rangee = 0; rangee < GRID_SIZE; rangee ++) {
    for (int colonne = 0; colonne < GRID_SIZE; colonne++) {
      if(briques[rangee][colonne] == 0) {
        continue;
      }
      gb.display.setColor(rainbow[briques[rangee][colonne] - 1]);
      int briqueX = colonne * (BRICK_W + 2) + 1;
      int briqueY = rangee * (BRICK_H +2) +1;
      gb.display.fillRect(briqueX, briqueY, BRICK_W, BRICK_H);
    }
  }
}

Max_NN

NEW 5 years ago

Bonjour tout le monde ! J'ai un problème, je veux faire un programme qui dessine un cercle avec une taille aléatoire, mais pour le moment la taille est toujours la même. Voici mon programme. Merci !

#include <Gamebuino-Meta.h>

int ballSize = random(1, 15);

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

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

 
  gb.display.print(ballSize);
  gb.display.setColor(WHITE);
  gb.display.drawCircle(39, 31, ballSize);
}

deeph

5 years ago

Tu devrais créer ta propre discussion parce que là c'est un peu hors sujet.

En regardant rapidement ton code, le problème c'est que ton calcul aléatoire est en dehors de la boucle, donc qu'il ne s’exécute qu'une fois. Essaie plutôt ça :

#include <Gamebuino-Meta.h>

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

void loop() {
  gb.display.clear();
  gb.display.setColor(WHITE);
  int ballSize = random(1, 15);
  gb.display.print(ballSize);
  gb.display.drawCircle(39, 31, ballSize);
  while (!gb.update());
}

deeph

NEW 5 years ago

Max_NN Max_NN

Tu devrais créer ta propre discussion parce que là c'est un peu hors sujet.

En regardant rapidement ton code, le problème c'est que ton calcul aléatoire est en dehors de la boucle, donc qu'il ne s’exécute qu'une fois. Essaie plutôt ça :

#include <Gamebuino-Meta.h>

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

void loop() {
  gb.display.clear();
  gb.display.setColor(WHITE);
  int ballSize = random(1, 15);
  gb.display.print(ballSize);
  gb.display.drawCircle(39, 31, ballSize);
  while (!gb.update());
}