cours03 - sbalev/processing101 GitHub Wiki
Si vous avez déjà joué un jeu vidéo, il ne vous a pas échappé que les choses se déroulent dans le temps. Le jeu commence par établir les conditions initiales : vous nommez votre héro, votre score de départ est zéro et vous commencez à niveau 1. Appelons cette partie du programme qui s'exécute une seule fois au début setup()
. Après l'initialisation, vous commencez à jouer. À chaque instant, l'ordinateur vérifie ce que vous faites avec la souris et le clavier, fait des calculs en fonction de vos actions et met à jour l'image qui s'affiche sur l'écran. Appelons cette partie du programme draw()
. Elle s'exécute en boucle, encore et encore, idéalement au moins 30 fois par seconde pour une animation fluide.
Exemple 3.1. Comment on s'y prend pour faire une course ?
-
Chaussez vos baskets et étirez-vous. Faites ça une seule fois, d'accord ?
-
Faites un pas avec le pied droit, ensuite avec le pied gauche. Répétez ça encore et encore, aussi vite que vous pouvez.
-
Après 42 km, arrêtez.
Appliquons cette technique pour faire notre premier croquis dynamique. Pour ce faire, nous allons placer notre code dans deux blocs.
void setup() {
// on met ici le code d'initialisation
}
void draw() {
// on met ici le code qui s'exécute en boucle
}
Techniquement, setup()
et draw()
sont des fonctions. Pour l'instant on ne va pas s'attarder sur le mot void
et les parenthèses après le nom de la fonction. Le corps d'une fonction est un bloc de code.
Un bloc est une suite d'instructions entre accolades.
{ un bloc }
Source geektionnerd
Plus tard on verra que les blocs peuvent s'imbriquer.
{ un bloc { un deuxième bloc à l'intérieur du premier } }
Les blocs sont une construction importante permettant de séparer et gérer notre code. Par convention on indente les lignes à l'intérieur de chaque bloc pour rendre le code lisible. Processing fait ça automatiquement quand vous tapez votre code. Si votre code n'est pas bien indenté, utilisez
Modifier/Mise en forme automatique
ouCtrl + T
.
Pour l'instant, concentrons-nous sur la structure de notre croquis.
void setup() {
instruction S1;
instruction S2;
instruction S3;
}
void draw() {
instruction D1;
instruction D2;
}
Comment ça marche ? L'exécution commence par les instructions dans le corps de setup()
. Ensuite les instructions à l'intérieur de draw()
sont exécutées plusieurs fois, jusqu'à ce qu'on ferme la fenêtre. L'ordre sera le suivant :
S1, S2, S3, D1, D2, D1, D2, D1, D2, ...
Exemple 3.2. Chip en croquis « dynamique ».
// setup() s'exécute en premier une seule fois
// size() doit toujours être la première instruction
void setup() {
size(400, 400);
}
// draw() boucle en continu jusqu'à ce qu'on ferme la fenêtre
void draw() {
background(255);
strokeWeight(1);
// le corps
fill(191);
rect(165, 200, 70, 70);
// les trois LEDs
fill(255, 0, 0);
rect(175, 220, 10, 10);
fill(0, 255, 0);
rect(195, 220, 10, 10);
fill(0, 0, 255);
rect(215, 220, 10, 10);
// les roues
fill(255);
ellipse(180, 270, 20, 20);
ellipse(220, 270, 20, 20);
// la tête
fill(191);
arc(200, 195, 70, 70, -PI, 0, CHORD);
// la caméra
fill(63, 0, 0);
ellipse(200, 180, 20, 20);
// l'antenne
strokeWeight(3);
line(200, 160, 200, 120);
}
En exécutant ce croquis on voit qu'il n'y a rien qui bouge ! Tout ça pour ça ? En examinant le code, on se rend compte que rien ne change dans la fonction draw()
. À chaque passage, on exécute exactement les mêmes instructions et par conséquent on dessine la même image. C'est pourquoi ce qu'on voit nous semble statique.
Exercice 3.1 Transformer votre « chose » en croquis dynamique. Même si elle ne bouge pas pour l'instant, vous avez droit d'être fier de vous.
Pour faire bouger les choses, on peut utiliser la position de la souris à la place de nombres dans les fonctions qui dessinent des formes. Les mots clefs mouseX
et mouseY
désignent la position horizontale et verticale du curseur de la souris. Lorsqu'on bouge la souris, ces valeurs changent.
Exemple 3.3.
void setup() {
size(400, 400);
}
void draw() {
background(255);
fill(127);
rectMode(CENTER);
// mouseX et mouseY sont des mots clefs que Processing remplace
// par la position horizontale et verticale de la souris
rect(mouseX, mouseY, 50, 50);
}
Exercice 3.2. Déplacer l'instruction background(255);
dans setup()
. Que se passe-t-il ? Pourquoi ?
Une instruction invisible
On peut se demander quand exactement Processing affiche les formes dans la fenêtre. On peut penser que cela se fait à chaque instruction, mais si c'était le cas, il y aurait un très désagréable clignotement. Pour éviter ce problème, Processing prépare l'image dans une zone de mémoire spéciale et le dessine sur la fenêtre seulement à la fin de chaque exécution de
draw()
.void draw() { // votre code ici // mise à jour de la fenêtre - une instruction qu'on ne voit pas }Cette technique s'appelle double buffering.
On peut pousser cette idée plus loin et faire un dessin plus complexe suivre la souris.
Exemple 3.4 Chip se déplace avec la souris
void setup() {
size(400, 400);
}
void draw() {
background(255);
strokeWeight(1);
// le corps
fill(191);
rect(mouseX - 35, mouseY, 70, 70);
// les trois LEDs
fill(255, 0, 0);
rect(mouseX - 25, mouseY + 20, 10, 10);
fill(0, 255, 0);
rect(mouseX - 5, mouseY + 20, 10, 10);
fill(0, 0, 255);
rect(mouseX + 15, mouseY + 20, 10, 10);
// les roues
fill(255);
ellipse(mouseX - 20, mouseY + 70, 20, 20);
ellipse(mouseX + 20, mouseY + 70, 20, 20);
// la tête
fill(191);
arc(200, 195, 70, 70, -PI, 0, CHORD);
// la caméra
fill(63, 0, 0);
ellipse(200, 180, 20, 20);
// l'antenne
strokeWeight(3);
line(200, 160, 200, 120);
}
Exercice 3.3. Modifier l'exemple précédent pour que la tête de Chip suive la souris avec le reste de son corps.
En plus de mouseX
et mouseY
, on peut utiliser pmouseX
et pmouseY
. Ces mots clefs désignent la position précédente de la souris, c'est-à-dire là où elle était lors du précédent passage par draw()
.
Exemple 3.5. Une ligne continue qui suit la souris.
void setup() {
size(400, 400);
background(255);
}
void draw() {
// dessiner une ligne entre la position précédente
// et la position courante de la souris
line(pmouseX, pmouseY, mouseX, mouseY);
}
Exercice 3.4. Modifier l'exemple précédent pour que l'épaisseur de la ligne varie en fonction de la vitesse de la souris.
Indications :
- la fonction
strokeWeight()
permet de changer l'épaisseur du contour ; - la fonction
dist()
calcule la distance entre deux points.
Les clics de souris et les appuis de touches sont des événements. Si on veut répondre à un événement, il faut ajouter une nouvelle fonction à notre croquis. Le code qu'on met dedans sera exécuté une fois chaque fois que l'événement arrive. On a besoin de deux nouvelles fonctions :
-
mousePressed()
qui gère les clics de souris ; -
keyPressed()
qui gère les appuis sur les touches.
Exemple 3.6.
void setup() {
size(400, 400);
background(255);
}
void draw() {
// rien ne se passe ici
}
// un cercle est dessiné à chaque clic de souris
void mousePressed() {
fill(127);
ellipse(mouseX, mouseY, 20, 20);
}
// la fenêtre est nettoyée lorsque l'utilisateur appuie sur une touche
void keyPressed() {
background(255);
}
Après un passage par setup()
on commence à boucler sur draw()
. Comme elle est vide, rien ne se passe. Le code dans mousePressed()
et keyPressed()
est là en attente. Lorsque l'utilisateur clique avec la souris (ou appuie sur une touche) il entre en action et s'exécute une seule fois.
Exercice 3.5. Ajouter background(255);
dans draw()
. Pourquoi le programme cesse de fonctionner correctement ?
Utilisons tous ces éléments pour rendre notre Chip interactif :
- Son corps suit la souris.
- Les couleurs de ses LEDs sont déterminées par sa position. Pour cela on utilise
colorMode()
et deux nouveaux mots clefswidth
etheight
qui désignent respectivement la largeur et la hauteur de la fenêtre. - Son bout d'antenne est relatif à la position précédente de la souris pour créer une impression de résistance de l'air.
- À chaque clic de souris, Chip affiche sa position actuelle. Noter l'utilisation de
+
dansprintln()
qui permet de « coller » ensemble plusieurs morceaux pour former une longue chaîne de caractères.
À noter également une nouvelle fonction qu'on utilise dans setup()
. frameRate()
permet de spécifier la vitesse à laquelle Processing boucle dans draw()
. frameRate(30)
signifie 30 images par seconde. La valeur par défaut est 60. C'est un maximum, si le dessin est trop complexe ou l'ordinateur n'est pas assez puissant, la vitesse actuelle pourrait être inférieure.
Exemple 3.7.
void setup() {
size(400, 400);
frameRate(30);
}
void draw() {
background(255);
strokeWeight(1);
// le corps
fill(191);
rect(mouseX - 35, mouseY, 70, 70);
// les trois LEDs
colorMode(RGB, width, height, width + height);
fill(mouseX, 0, 0);
rect(mouseX - 25, mouseY + 20, 10, 10);
fill(0, mouseY, 0);
rect(mouseX - 5, mouseY + 20, 10, 10);
fill(0, 0, mouseX + mouseY);
rect(mouseX + 15, mouseY + 20, 10, 10);
colorMode(RGB, 255, 255, 255);
// les roues
fill(255);
ellipse(mouseX - 20, mouseY + 70, 20, 20);
ellipse(mouseX + 20, mouseY + 70, 20, 20);
// la tête
fill(191);
arc(mouseX, mouseY - 5, 70, 70, -PI, 0, CHORD);
// la caméra
fill(63, 0, 0);
ellipse(mouseX, mouseY - 20, 20, 20);
// l'antenne
strokeWeight(3);
line(mouseX, mouseY - 40, pmouseX, pmouseY - 80);
}
void mousePressed() {
println("Je suis sur (" + mouseX + ", " + mouseY + ")");
}
Exercice 3.6. Dessiner un rectangle qui reste dans le centre de la fenêtre mais dont la taille varie en fonction de la position de la souris (le curseur coïncide avec l'un des sommets du rectangle). Indication : utiliser la fonction abs()
.
Exercice 3.7. Dessiner un cercle qui reste dans le centre de la fenêtre et dont la taille change en fonction de la position de la souris (le curseur est sur le contour du cercle). Indication : utiliser la fonction dist()
.
Exercice 3.8. Faire en sorte que la couleur du fond de la fenêtre change en fonction de la position x de la souris en variant de noir quand le curseur est à gauche à blanc quand le curseur est à droite. Indication : utiliser colorMode()
.
Exercice 3.9. Reprendre le dessin statique de l'Exercice 2.1. Rendre votre « chose » dynamique en la faisant interagir avec la souris. Cette interaction peut inclure des formes qui suivent la souris, qui changent leur couleur et leur taille en fonction de la souris, etc.