6 years ago
Discover variables, the conditional structure if and draw rectangles.
Length 20 minutes
Level Complete beginner
Prerequisites
Our objective now is to build a small guest counter, that increments whenever the use presses the UP arrow, and decrements whenever the Down arrow is pressed. This counter is often found at the entrance of stadiums or events to count people. But the logic we will use can be applied in many areas of a video game, such as scores or death count. Throughout the program, we will learn how to store values in memory with variables and use conditions to handle buttons.
Let's begin with the body of our last program, "Hello, world" and making a small variation: (don't hesitate to follow along on you IDE ;) )
#include int counter = 0; // New line void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); gb.display.print(counter); // Something changed here :) }
Let's take a deeper look at the changes we made.
int counter = 0;
This line declares and initializes a variable that we display later in loop
counter
is a variable that keeps track of how many guests we have. A variable is used to store information in memory. It could be a score, an image, some text, or even a whole map for a platformer. Sadly, when you power off you console, all variables are lost :( Note for the curious: there is actually a way to store variables in the SD card as to not lose them! (we will learn more about this in an later workshop)
Here, we give our variable an initial value of 0 with the equals operator =
.
A variable has a name, here we chose counter
. Choosing a descriptive name is very important, our programs can be understood more clearly by the reader and ourselves. Avoid using names like a
, b
or var
, unless you want headaches.
A variable also has a data type. The type of a variable is set at declaration, just before naming it. Here counter
is an int
. "Int" is short for integer, also known as whole numbers. So counter
can store any integer, such as 0, 1, 5, or -34.
Here, this instruction is not placed inside of a function (functions are bounded by curly brackets {}
). In C/C++, we can place instructions outside of functions, but these will only be executed once, from top to bottom. Note this does not apply to functions (instructions end in a semicolon but functions do not).
gb.display.print(counter);
We already saw how to use the gb.display.print
function in the Hello world workshop. We used it with a string as its parameter. But you can also pass an int as a parameter, like we have done here. This will of course print the value of counter
.
If you run the code we wrote up to this point, you will see a screen displaying a 0. There is no movement, no interaction. Boring right? Let's fix this right now. Before we start coding, you must understand that a variable can change value, hence the name. Also it is good practice to write down an algorithm before we program. So I came up with this algorithm to create the guest counter:
If we press UP Then add 1 to "counter" If we press DOWN Then subtract 1 to "counter" If we press MENU Then Reset "counter" to 0
This algorithm simply states that we control the value of counter
with the UP and DOWN arrows. We can also reset its value with the MENU button. See nothing complicated right? Now we have to write the same thing, but in C++. The If ... Then ...
in our algorithm translate to:
if (condition) { // ... }
Rather straight forward. If the condition is true, Then execute everything located within those two curly brackets { }
. Applying this to the first part of the algorithm (UP arrow), we get the following:
#include int counter = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if (gb.buttons.pressed(BUTTON_UP)) { // If we press UP counter = counter + 1; // Add 1 to "counter" gb.sound.playTick(); // Play a ticking sound } // End of IF gb.display.print(counter); gb.display.fillRect(counter, 8, 2, 4); // Draw the rectangle }
The new instructions are explained below. Since we only give you one part of the algorithm, then...
It is now up to you to complete the code we started so that the two other buttons DOWN and MENU work. Do not hesitate to read over the algorithm and help yourself with the code for the UP arrow. If you ever need help with syntax, go to the Reference page (I recommend that you bookmark that page). This time I'll be nice this time and provide most of the elements you will need:
BUTTON_DOWN BUTTON_MENU
These are the names of the two other buttons you will need.
Once that works, here is an extra little challenge: personalize your counter. Here are the functions you can use (and that are used in the given code above):
gb.sound.playTick();
This plays an predefined "tick" sound. Could be useful to make the counter feel more responsive when the player presses a button.
gb.display.fillRect(x, y, w, h);
This function draws a rectangle. It takes multiple parameters, separated by comas ,
. The number and order of parameters in a a function is important. If you want to read more about this function, check out its reference, but here is a quick summary:
x
is the horizontal coordinate of the rectangle, with the left edge of the screen being 0. In the example above, ve used counter
.y
is the vertical coordinate of the rectangle, with the top edge of the screen being 0. Here it is 8
, or 8 pixels.w
is the width of the rectangle in pixels, here 2
h
is the height of the rectangle in pixels, here 4
How you use theses functions is up to you! Go crazy! Try messing with the position and size of the rectangle, or how about it color? What if instead of counting guests 1 by 1, you multiplied by 2 every time.
Share your inventions on social networks with #gamebuino #tallycounter, we go through them all the time ;)
A computer (like your Gamebuino) can execute a huge number of instructions very quickly, but a computer is not very bright. It we do exactly as it is told, literally. So the syntax and logic of each line is rather strict. There are two types of errors: syntax errors and logic errors. Syntax errors are detected by the compiler (when you compile), who will not let you compile until it is happy. Then we have the logic errors, those get past the compiler, but things don't behave like they are supposed to when you run your game.
To fix syntax errors, reading the red text given by the compiler is crucial. Here are the most "popular" errors:
Curly brackets { }
This is an error that a lot of beginners make. It is important to know that curly brackets come in pairs. Sometimes, you may forget to put one or type an extra one by accident. Either way, the compiler will not be happy because there will be a lonely bracket without a partner somewhere :( Here is a great feature of this IDE: if you place your cursor on an opening bracket, the matching closing brackt will be highlighted (and vice-versa). Note: all if statements and functions must have brackets.
The semicolon ;
Every instruction must end with a semicolon. This error is as easy to fix, as it is to make :P Just read over your code, and look for missing semicolons.
If you ever get stuck with an error that you cannot seam to fix, come by our discord channel for help. Even if you don't have problems, you can join the community's chat ;)
Here's what we came up with: (code below)
#include int counter = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if(gb.buttons.pressed(BUTTON_UP)){ counter = counter + 1; gb.sound.playOK(); } if(gb.buttons.pressed(BUTTON_DOWN)){ counter = counter - 1; gb.sound.playCancel(); } if(gb.buttons.pressed(BUTTON_MENU)){ counter = 0; gb.sound.playTick(); } gb.display.setColor(BROWN); gb.display.fillRect(0, 0, counter, gb.display.height()); gb.display.setColor(WHITE); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); }
Head to the next workshop to start you Pong game!
By Aurélien Rodot, modified by Julien Giovinazzo
Any questions / comments / suggestions, be sure to drop a comment down below!
NEW 6 years ago
Bien mieux que l'ancien. La nouvelle structure des Tuto avec les prérequis au début et une solution original et coloré à la fin est aussi bien pensé.
NEW 6 years ago
Je crois que les type int sont en fait des uint64_t et non des int32_t comme il était sur le CPU de la Gamebuino Classic donc "On peut donc y stocker un nombre sans virgule, positif ou négatif." n'est pas vrai.
Basé selon mes experience personnel lorsque j'ai adapté mon jeu vers la META
Nan finalement les int ce n'est pas usigned
NEW 6 years ago
Salut tout le monde!
J'aimerai creuser un peu l'idée du compteur et, par exemple, faire en sorte que le nombre à l'écran s'allume vert quand on appuie sur "haut" et rouge quand on appuie sur "bas"... je ne sais pas trop comment faire je me suis dit que ça serait facile mais en fait ça ne l'est pas (pour moi -_-).
#include <Gamebuino-Meta.h> int counter = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if (gb.buttons.pressed(BUTTON_UP)) { counter = counter + 1; gb.display.setColor(GREEN); gb.display.print(counter); gb.sound.playOK(); } if (gb.buttons.pressed(BUTTON_DOWN)) { counter = counter - 1; gb.display.setColor(RED); gb.display.print(counter); gb.sound.playCancel(); } if (gb.buttons.pressed(BUTTON_MENU)) { counter = 0; gb.sound.playTick(); } gb.display.setColor(BROWN); gb.display.fillRect(0, 0, counter, gb.display.height()); gb.display.setColor(WHITE); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); }
Le problème ici c'est que ça me l'affiche en vert ou rouge mais en petit dans le coin supérieur gauche. (normal vu que je n'ai précisé ni la taille ni l'emplacement mais si je le fait ça ne fonctionne pas.. J'ai en fait l'impression que l'affichage du compteur (en vert ou rouge) passe "derrière" le compteur blanc ainsi que le rectangle marron. Faut-il dire "d'enlever" le compteur blanc le temps que l'autre est affiché ou quelque chose comme ça ?
geed
6 years ago
C'est EXACTEMENT ça, imagine que la console affiche les choses dans l'ordre où tu lui demandes. Dans ton programmes tu changes la couleur AVANT de lui demander d'afficher ton compteur en blanc. Du coup, elle le change bien de couleur, mais le ré-affiche par dessus en blanc.
Perso je conditionnerai l'affichage du compteur.
C'est à dire que d'abord je fais mes calculs, puis dessine le "fond" et enfin je lui demanderai quelque chose du genre :
Si la précédente valeur est :
Je te laisse méditer ces pistes, voir commencer à imaginer de petites fonctions pour le faire.
Perso je suis aussi débutant en programmation et je fonctionne comme ça : 1) je divise le problème en petits problèmes faciles 2) je code des petites fonctions qui les résolvent 3) j'assemble le tout :p
NEW 6 years ago
C'est EXACTEMENT ça, imagine que la console affiche les choses dans l'ordre où tu lui demandes. Dans ton programmes tu changes la couleur AVANT de lui demander d'afficher ton compteur en blanc. Du coup, elle le change bien de couleur, mais le ré-affiche par dessus en blanc.
Perso je conditionnerai l'affichage du compteur.
C'est à dire que d'abord je fais mes calculs, puis dessine le "fond" et enfin je lui demanderai quelque chose du genre :
Si la précédente valeur est :
Je te laisse méditer ces pistes, voir commencer à imaginer de petites fonctions pour le faire.
Perso je suis aussi débutant en programmation et je fonctionne comme ça : 1) je divise le problème en petits problèmes faciles 2) je code des petites fonctions qui les résolvent 3) j'assemble le tout :p
NEW 6 years ago
je rajouterais que ton code est executer 25X par seconde. ton compteur vert ou rouge sera afficher uniquement 1/25 X du coup presque invisible.
Tu dois creer une variable pour sauvegarder la couleur courante de ton compteur
NEW 6 years ago
Geed ton enthousiasme fait plaisir à voir ! :D Je vois et vais essayer de partir dans ce sens là. Je vous retransmettrais mon nouveau code :)
Et Clément ce que tu dis j'y ai pensé aussi,1/25s c'est pas si pire, je veux vraiment que ça clignote mais si je peux le faire durer 2/25s voir 3/25s ça peut-être vraiment cool mais la... ça dépasse tout entendement pour mon niveau ! :)
NEW 6 years ago
Alors.. j'ai le bon affichage, à la bonne taille, etc mais ça s'affiche à côté de la valeur "blanche" du compteur. J'ai pas suivi le fonctionnement que tu m'a proposé Geed parce que j'avoue que je sais pas trop comment m'y prendre.. Dois-je continuer sur cette lancée ou aborder d'une autre manière ?
Si je continue sur ce que j'ai mit y a-t-il une solution de demander d'afficher la valeur verte ou rouge à la place de la blanche? Je ne sais pas trop comment faire...
#include <Gamebuino-Meta.h> int counter = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if (gb.buttons.pressed(BUTTON_UP)) { counter = counter + 1; gb.sound.playOK(); } if (gb.buttons.pressed(BUTTON_DOWN)) { counter = counter - 1; gb.sound.playCancel(); } if (gb.buttons.pressed(BUTTON_MENU)) { counter = 0; gb.sound.playTick(); } gb.display.setColor(BROWN); gb.display.fillRect(0, 0, counter, gb.display.height()); gb.display.setColor(WHITE); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); if (gb.buttons.pressed(BUTTON_DOWN)) { gb.display.setColor(RED); gb.display.print(counter); } if (gb.buttons.pressed(BUTTON_UP)) { gb.display.setColor(GREEN); gb.display.print(counter); } }
NEW 6 years ago
en fait tu n a pas besoin de reecrire le counter.
l idee c est au moment ou tu choisi la couleur ( a la ligne gb.display.setColor(WHITE);) tu doit choisir entre le rouge le vert ou le blanc
donc en mata code :
si mon bouton haut est appuyer je choisi le vert sinon si mon bouton bas est appuyer je choisi le rouge sinon je choisi le blanc
Pour cela tu doit te pencher sur le else je ne sais pas si il y a des exemple dans les tuto Gamebuino mais tu trouvera facilement comment ca marche sur google.
NEW 6 years ago
Ça ne marche pas, je suis à deux doigts d'aller chercher une masse afin de mieux faire comprendre à mon mac ce que je veux faire.. XD
J'ai été obligé de réécrire tout le conter pour qu'il apparaisse.
Si je met "if..." "else..." "else..." pour le deuxième "else" il me dit que ce n'est pas correct si il n'y a pas de "if" avant. Et avec ce code là quand j'appuie sur "haut" je vois le compteur qui clignote mais c'est trop rapide.. Impossible de dire s'il s'affiche en vert (il faut que je rallonge le temps d'affichage mais je ne sais pas comment) et par contre quand j'appuie sur "bas" le compteur change mais ne clignote pas.
Au moins il y a déjà l'affichage en vert qui fonctionne (peut-être) on va dire que c'est une avancée!
Voila ce que j'ai fait:
#include <Gamebuino-Meta.h> int counter = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if (gb.buttons.pressed(BUTTON_UP)) { counter = counter + 1; gb.sound.playOK(); } if (gb.buttons.pressed(BUTTON_DOWN)) { counter = counter - 1; gb.sound.playCancel(); }d if (gb.buttons.pressed(BUTTON_MENU)) { counter = 0; gb.sound.playTick(); } gb.display.setColor(BROWN); gb.display.fillRect(0, 0, counter, gb.display.height()); if (gb.buttons.pressed(BUTTON_DOWN)) { gb.display.setColor(RED); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); } if (gb.buttons.pressed(BUTTON_UP)) { gb.display.setColor(GREEN); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); } else (gb.display.setColor(WHITE)); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); }
geed
6 years ago
C'est juste un problème de syntaxe ! Pas besoin de sortir la masse :)
regarde du côté des exemple sur l'arduino IDE, section CONTROL, tu verras que le else à une structure du type if (machin) { alors } else { bidule }
https://www.arduino.cc/reference/en/
Moi à ta place, je contournerai le problème, peut être avec une deuxième variable qui passe à 1 2 ou 3 en fonction de ce que tu fais. Et en fonction de la valeur de cette variable, tu changes l'affichages. Par exemple :)
Regarde aussi du côté de la fonction Switch (bidule) {
Et bon courage ! Ne décroche pas !
clement
6 years ago
oui tu ne peux pas mettre de else sur un seul if...
mais tu peux remetre un if dans un else
Le switch que propose geed peux etre une bonne solution.
pour evité des problèmes a ton mac voici la syntax qui fonctionne du if / else qui fonctionnera pour ton cas. reste plus qu a mettre les bonne conditions dedans
if() { } else if () { } else { }
NEW 6 years ago
Bientôt, bientôt, je suis justement en train d'écrire la suite :)
Mais ça fait plaisir de voir que c'est utilisé, que certains vont au delà et que tout le monde s'entraide. Keep it up ! :D
NEW 6 years ago
C'est juste un problème de syntaxe ! Pas besoin de sortir la masse :)
regarde du côté des exemple sur l'arduino IDE, section CONTROL, tu verras que le else à une structure du type if (machin) { alors } else { bidule }
https://www.arduino.cc/reference/en/
Moi à ta place, je contournerai le problème, peut être avec une deuxième variable qui passe à 1 2 ou 3 en fonction de ce que tu fais. Et en fonction de la valeur de cette variable, tu changes l'affichages. Par exemple :)
Regarde aussi du côté de la fonction Switch (bidule) {
Et bon courage ! Ne décroche pas !
NEW 6 years ago
oui tu ne peux pas mettre de else sur un seul if...
mais tu peux remetre un if dans un else
Le switch que propose geed peux etre une bonne solution.
pour evité des problèmes a ton mac voici la syntax qui fonctionne du if / else qui fonctionnera pour ton cas. reste plus qu a mettre les bonne conditions dedans
if() { } else if () { } else { }
NEW 6 years ago
Merci, je vais essayer d'avancer la dessus ! :)
Edit:
Après une semaine sans toucher ma Gamebuino faute de temps :( j'ai suivi ton conseil Clement, et, même si je ne sais pas pourquoi ça fonctionne maintenant ! =)
#include <Gamebuino-Meta.h> int counter = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if (gb.buttons.pressed(BUTTON_UP)) { counter = counter + 1; gb.sound.playOK(); } if (gb.buttons.pressed(BUTTON_DOWN)) { counter = counter - 1; gb.sound.playCancel(); } if(gb.buttons.pressed(BUTTON_MENU)) { counter = 0; gb.sound.playTick(); } gb.display.setColor(BROWN); gb.display.fillRect(0, 0, counter, gb.display.height()); if (gb.buttons.pressed(BUTTON_DOWN)) { gb.display.setColor(RED); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); } else if (gb.buttons.pressed(BUTTON_UP)) { gb.display.setColor(GREEN); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); } else {gb.display.setColor(WHITE)); gb.display.setFontSize(4); gb.display.setCursor(8,8); gb.display.print(counter); }
J'aimerais encore faire quelques modifications comme par exemple rallonger la durée de couleur rouge ou verte mais je ne sais pas comment..
et aussi j'aimerai ajouter un "flash" mais je ne connais pas la "fonction" ?? pour allumer les led "gb.display.lesledcestjoliquandcestallumé" par exemple.. :)
Vous avez déjà été formidables avec tous vos conseils mais j'en veux plus !!
NEW 6 years ago
Hello ! Super tuto :)
Au début il est écrit "Lorsque l'on éteint la console, la valeur est perdue." Comment faire justement pour garder en mémoire la valeur ? J'ai bien envie de faire un compteur qui peut me servir dans le temps et donc ne pas perdre la valeur ;-)
J'ai été regarder dans la référence, et j'ai vu qu'il y avait une rubrique "save" :
gb.save.config gb.save.get gb.save.set gb.save.del
Merci pour vos conseils !
Sorunome
6 years ago
Yes, you save values using the gb.save
stuff, that will actually store the values on the micro SD card. You can find more on how to do that here: https://gamebuino.com/creations/gamebuino-save-format
NEW 6 years ago
Yes, you save values using the gb.save
stuff, that will actually store the values on the micro SD card. You can find more on how to do that here: https://gamebuino.com/creations/gamebuino-save-format
Nicolas
6 years ago
Merci !
Je viens de faire un test et je pense que je ne vois pas bien comment sauvegarder la valeur avec gb.save
Voici mon code :
#include <Gamebuino-Meta.h> int compteur = 0; void setup() { gb.begin(); } void loop() { while (!gb.update()); gb.display.clear(); if (gb.buttons.pressed(BUTTON_UP)) { compteur = compteur + 1; gb.sound.playOK(); } gb.display.print(compteur); gb.save.get(compteur); }
J'ai bien ajouté gb.save.get
avec la variable "compteur".
Merci pour le coup de pouce !