Comment ça le score reste à 10 ? Je ne comprends pas…
Par contre, tu t’es trompé à la ligne 133 :
if (gb.buttons.pressed(BUTTON_A)) game.state = State::play;
Le nouvel état n’est pas State::play
mais State::start
:
if (gb.buttons.pressed(BUTTON_A)) game.state = State::start;
Curieux… Tu l’avais pourtant bien écrit dans ta v1…
En ce qui concerne le clignotement, tu fais l’erreur de raisonnement que beaucoup de débutants font :
for (int i=0; i<1000; ++i); {
gb.display.print(17, 30, "APPUYER SUR A");
gb.display.print(17, 40, "POUR DEMARRER");
}
for (int i=0; i<1000; ++i); {
gb.display.print(17, 30, " ");
gb.display.print(17, 40, " ");
}
Si tu écris les choses comme ça, les boucles sont bien effectuées… mais dans le même cycle de la fonction loop()
. Autrement dit, avant que le moindre raffraîchissement graphique n’ait pu avoir lieu. En effet, souviens toi que le chef d’orchestre est la fonction loop()
:
void loop() {
gb.waitForUpdate();
gb.display.clear();
switch (game.state) {
case State::start:
start();
break;
case State::play:
play();
break;
case State::game_over:
gameOver();
}
}
À chaque cycle de la fonction loop()
la première instruction permet d’effectuer les tâches internes de la lib Gamebuino-Meta
:
gb.waitForUpdate();
C’est cette instruction qui permet d’effectuer la lecture de l’état des boutons, la gestion du son, la gestion des LEDs, etc… et surtout le raffraîchissement de l’écran. Tout ceci s’exécute 25 fois par secondes (valeur par défaut, si tu ne modiifies pas le frame rate).
Autrement dit, tout ce que tu dessines à chaque cycle de la fonction loop()
ne sera visible qu’à partir du moment où le prochain cycle s’exécute. Par conséquent, tu ne peux pas gérer le clignotement comme tu l’as fait.
L’idée consiste en fait à répartir l’affichage ou non de l’élément que tu souhaites faire clignoter sur plusieurs cycles de la fonction loop()
. La librairie fournit un compteur de cycles : gb.frameCount
. Tu peux donc t’appuyer sur la valeur de ce compteur pour compter les cycles de raffraîchissements de l’écran et déterminer lesquels doivent afficher ou non l’élément à faire clignoter. Une manière très simple de faire cela consiste, par exemple, à utiliser l’opérateur de congruence %
(modulo) :
void start() {
if (gb.buttons.pressed(BUTTON_A)) game.state = State::play;
gb.display.print(17, 10, "PONG 1 PLAYER");
if (gb.frameCount % 25 < 13) {
gb.display.print(17, 30, "APPUYER SUR A");
gb.display.print(17, 40, "POUR DEMARRER");
}
game.resetScores();
}
À chaque cycle de la fonction loop()
, l’expression suivante est évaluée :
gb.frameCount % 25 < 13
Note que l’opérateur %
est ici prioritaire devant l’opérateur <
, sinon il aurait fallu écrire :
(gb.frameCount % 25) < 13
a % b
retourne le reste de la division euclidienne de a
par b
. Autrement dit, quelle que soit la valeur de gb.frameCount
, l’expression :
gb.frameCount % 25
retournera toujours une valeur comprise entre 0
et 24
. Et comme gb.frameCount
est incrémentée d’une unité à chaque cycle de la fonction loop()
, tu es sûr de parcourir indéfiniment la séquence de valeurs 0, 1, 2, … 24.
L’astuce consiste donc simplement à comparer la valeur courante (dans cet intervalle) à une valeur pivot pour équilibrer les phases d’affichage et de non affichage de l’élément à faire clignoter. Ici j’ai pris la valeur 13
comme pivot, donc le texte est affiché pour les valeurs comprises entre 0
et 12
, mais ne sera pas affiché pour les valeurs comprises entre 13
et 24.
Et le tour est joué ! Tu obtiens bien le clignotement désiré.
Tu peux jouer sur la valeur limite (25
) et la valeur pivot (13
) pour obtenir des clignotements plus ou moins rapides. À toi de déterminer quelles valeurs conviennent à l’effet de clignotement que tu préfères.
J’espère avoir été assez clair…