Panier à œufs

Étape 3
Étape terminée ?

Dans cette étape nous allons mettre en place la structure de notre jeu

Comme d'habitude, avant de remplir notre IDE de lignes de code, prenons une petite pause pour placer nos différentes parties. Nous allons appliquer la méthode entrées / mise à jour / affichage.

<Gamebuino-Meta.h>

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

void loop() {
    while(!gb.update());
    // ENTRÉES
    // MISE À JOUR
    // AFFICHAGE
}

Commençons par programmer le panier. Il est très similaire aux raquettes que nous avons vu lors du workshop Pong, à la différence près que le panier est à l'horizontal.

Avant de s'attaquer aux parties entrées / mise à jour / affichage, débutons le programme par identifier les constantes et les variables du panier, sans oublier #include <Gamebuino-Meta.h> en première ligne de code !

#include <Gamebuino-Meta.h>

// Panier
int panierX = 20;  // Le panier peut bouger horizontalement, donc ce n'est pas une constante
const int PANIER_Y = gb.display.height() - 4;  // Constante car le panier est fixe selon l'axe Y
int panierLargeur = 0;  // Pas cosntant car la taille dépend de la nourriture restante
const int PANIER_HAUTEUR = 3;  // Constante

Pour compter les points et relever le défi de battre le record nous devons aussi identifier le score et le highscore. Nous en profiterons pour déclarer la variable nourriture, elle servira pour la largeur du panier...

int score = 0;
int highscore = 0;
int nourriture;  // Plus de nourriture est mieux. 0 nourriture = game over

On ne va pas démarrer avec 0 de nourriture, c'est pourquoi nous allons débuter avec 300 en le précisant dans void setup()

void setup() { 
	gb.begin();
	nourriture = 300; 
}

Nous allons attaquer entrées / mise à jour / affichage, c'est pas trop tôt ! Ça ne fera pas de mal de rappeler que ces parties sont dans la fonction void loop(), après while(!gb.update()) :

void loop() {
    while(!gb.update());
    // ENTRÉES
    // MISE À JOUR
    // AFFICHAGE

}
ENTRÉES

"En entrée je vous propose une petite terrine de légumes avec un peu de if et de else if."

C'est dans cette partie que nos actions avec les boutons vont être précisées. Pour cela nous pouvons utiliser les conditions if et else if : Si bouton gauche enfoncé alors aller à gauche sinon si bouton droit enfoncé alors aller à droite

    // ENTRÉES
    if (gb.buttons.repeat(BUTTON_LEFT, 0) && panierX > 0) {
        panierX -= 2;
    }
    else if (gb.buttons.repeat(BUTTON_RIGHT, 0) && panierX < gb.display.width() - panierLargeur) {
        panierX += 2;
    }

Tiens, dans notre proposition de code nous avons un nouveau : &&. C'est un opérateur logique booléen qui signifie ET, il peut être utilisé à l'intérieur de la condition d'une instruction if pour associer plusieurs conditions. Avec ce ET LOGIQUE, les deux conditions doivent être vraies. Et ces conditions permettent au panier de ne pas sortir de l'écran...

Idées : Pourquoi pas jeter un œil à votre Pong et s'amuser à tester cela sur les deux raquettes... ;)

MISE À JOUR

À chaque frame le score baisse et fait baisser la largeur du panier. On peut utiliser l'opérateur composé -- qui décrémente de 1 la variable nourriture à chaque frame ce qui nous donne nourriture--;

Pour influencer la largeur du panier on peut indiquer que la variable panierLargeur sera égale à nourriture / 20. On divise simplement par 20 pour obtenir une largeur cohérente.

Que se passe-t-il quand le panier disparait ? La partie est finie et on en recommence une. Pour ce faire on peut utiliser une condition que l'on peut résumer : "Si la nourriture est inférieure ou égale à 0 alors score égal 0 et nourriture égal 300". Ça veut dire qu'une fois le panier complètement disparu, on reset le score à 0 et on commence de nouveau avec 300 de nourriture.

    // MISE À JOUR
    // La nourriture fait doucement baisser notre nourriture dans le panier
    nourriture--;
    panierLargeur = nourriture / 20;

    // Sommes-nous mort par manque de nourriture??
    if (nourriture <= 0) {
        score = 0;  // Recommencer le jeu
        nourriture = 300;  // Reset nourriture
    }
AFFICHAGE

"Il est temp d'utiliser des pixels !"

Pour commencer, gb.display.clear() sera indispensable pour rafraîchir l'écran à chaque frame. Ensuite nous intégrons le panier en lui définissant une couleur puis en appelant la fonction fillRect, pour dessiner un rectangle. Concernant le score, il faut définir la couleur, la position du texte et appeler la variable pour l'afficher. Nous ferons la même chose pour highscore.

    // AFFICHAGE
    gb.display.clear();

    // Panier
    gb.display.setColor(WHITE);
    gb.display.fillRect(panierX, PANIER_Y, panierLargeur, PANIER_HAUTEUR);

    // Score
    gb.display.setColor(WHITE);
    gb.display.setCursor(gb.display.width() - 8, 0);
    gb.display.print(score);

    gb.display.setColor(RED);
    gb.display.setCursor(gb.display.width() - 8, 8);
    gb.display.print(highscore);
}

Code final de cette étape

Si nous mettons bout à bout tout ce que nous venons de voir, le code de base prend cette forme :

#include <Gamebuino-Meta.h>

// Panier
int panierX = 20;  // Le panier peut bouger horizontalement, donc ce n'est pas une constante
const int PANIER_Y = gb.display.height() - 4;  // Constante car le panier est fixe selon l'axe Y
int panierLargeur = 0;  // Pas cosntant car la taille dépend de la nourriture restante
const int PANIER_HAUTEUR = 3;  // Constante

int score = 0;
int highscore = 0;
int nourriture;  // Plus de nourriture est mieux. 0 nourriture = game over


void setup() {
  gb.begin();

  nourriture = 300;
}

void loop() {
    while(!gb.update());
    // ENTRÉES
    if (gb.buttons.repeat(BUTTON_LEFT, 0) && panierX > 0) {
        panierX -= 2;
    }
    else if (gb.buttons.repeat(BUTTON_RIGHT, 0) && panierX < gb.display.width() - panierLargeur) {
        panierX += 2;
    }

    // MISE À JOUR
    // La nourriture baisse dans le panier et diminue sa largeur
    nourriture--;
    panierLargeur = nourriture / 20;

    // Somme-nous mort par manque de nourriture??
    if (nourriture <= 0) {
        score = 0;  // Recommencer le jeu
        nourriture = 300;  // Reset nourriture
    }

    // AFFICHAGE
    gb.display.clear();

    // Panier
    gb.display.setColor(WHITE);
    gb.display.fillRect(panierX, PANIER_Y, panierLargeur, PANIER_HAUTEUR);

    // Score
    gb.display.setColor(WHITE);
    gb.display.setCursor(gb.display.width() - 8, 0);
    gb.display.print(score);

    gb.display.setColor(RED);
    gb.display.setCursor(gb.display.width() - 8, 8);
    gb.display.print(highscore);
}

Désormais le joueur peut déplacer le panier avec les flèches gauche et droite mais on l'empêche de sortir de l'écran.

On en a aussi profité pour commencer à implémenter le système de nourriture : comme nous avons dit précédemment, le joueur doit remplir son panier d'œufs. Chaque œuf augmente sa quantité de nourriture mais à chaque image de jeu (chaque frame), cette quantité diminue un peu.

Pour pouvoir visualiser nourriture, la largeur du panier est directement liée à sa valeur. Si jamais elle atteint 0, la partie est perdue.

Rendez-vous à l'étape suivante !

Étapes