TP 2: Interactivité

Programmation évènementielle (event-driven programming)

Nous allons faire un programme "réactif" à un évènement qui est un clic effectué avec la souris dans la fenêtre. La réaction est que le fond de la fenêtre devient noir. S'il n'y a pas de clic elle reste blanche.

Processing a un autre type de fonction prédéfinie qui gère ce type d'évènement. Ici ce sera la fonction mousePressed() mais contrairement à la semaine dernière où on utilisait ellipse() ou rect(), ici il faut construire la fonction mousePressed(). Comment ?. En précisant ce que l'on veut faire entre accolades lorsque la souris est pressée.

Voilà le programme


void setup(){
	size(400,400);
	background(255);
}
// voila comment on définit mousePressed()
void mousePressed(){
	background(0);
}
void draw(){
}

Deux remarques importantes

  1. Mouse and keyboard events only work when a program has draw(). Without draw(), the code is only run once and then stops listening for events. (Reference)
  2. Une fonction de la forme void nom_fonction(){....} doit être définie , c'est à dire on doit remplacer les ... par des fonctions prédéfinies (pour l'instant) ou par rien. Mais cette fonction doit être appelée pour être exécutée sauf les fonctions mousePressed(), mouseReleased(), et toutes les fonctions qui "écoutent " les évènements venant du clavier,de l'écran ,de la souris et finalement setup() et draw()

Donc la programmation évènementielle fait intervenir une fonction draw() qui exécutée 60 fois par seconde(par défaut) est à l'écoute des "évènements" provenant de la souris, du clavier, de l'écran à condition que les fonctions associées à ces évènements soient définis

Un évènement vient de :

Pour "écouter" et gérer ces évènements il y a des fonctions prédéfinies, comme mousePressed() qu'il faut redéfinir

Pour que l'écoute fonctionne la fonction draw() doit être active (par défaut 60 Hz)

Exercices

Remplacer mousePressed par mouseClicked(), mouseReleased(),mouseDragged(), keyPressed(), etc...et observer.

setup() et draw()

Un programme est donc pour l'instant une suite de fonctions "actives" ou dynamiques du type :


void nom_fonction(){
...à remplir....
}

Parmi ces fonctions à part celles qui écoutent les évènements deux jouent un rôle important, setup() et draw()

setup() n'est exécutée qu'une fois, alors que draw() est exécutée 60 fois par secondes, par défaut. Pour prendre conscience de cela , exécutons le programme suivant qu utilise une fonction nouvelle println() qui affiche dans la console, un message entre "" ( à l'intérieur des parenthèses). La fonction frameRate() définit la fréquence de draw(). On la règle ici à 2 Hz pour qu'on ait le temps de voir quelque chose.


void setup(){
	size(400,400);
	background(0);
	frameRate(2);
	println("Exécution de setup()");
}

void draw(){
	println("Exécution de draw()");
}

Variables : mouseX, mouseY, pMouseX, pMouseY

Continuons de rendre de plus en plus "réactifs" nos programmes, en introduisant une notion importante celle de variable

mouseX et mouseY sont des variables qui contiennent les coordonnées actuelles du pointeur de la souris

Nous allons reprendre le programme qui dessine le pacman de la semaine dernière en le transformant de manière à ce que le pacman "suit" le pointeur de la souris.

Voici le programme


void setup(){
    size(400,400);
   
}

void draw(){
    background(255);
    strokeWeight(2);
    fill(216,245,17);
    arc(mouseX,mouseY,80,80,PI/6,11*PI/6,PIE);
    fill(0);
    ellipse(mouseX+10,mouseY-20,5,5);
}

Enlever la commande background(255) dans draw() et la mettre dans setup(). Qu'observez vous ? Expliquer.

pMouseX et pMouseY sont des variables contenant les coordonnées du pointeur à l'état précédent (previous). (Lire la documentation)

Voici un programme. Que fait-il ?


void setup(){
	size(300,300);
	background(255);
}
void draw(){
	line(pmouseX, pmouseY, mouseX, mouseY);
}

les variables width et height

Les variables width et height (largeur et hauteur en français) conservent les valeurs de la largeur et de la hauteur de la fenêtre graphique. Pour quoi faire ? Par exemple si on veut se repérer dans le programme par rapport au centre de la fenêtre dans ce cas on sait que les coordonnées du centre sont (width/2,height/2)

Remarque très importante: Ainsi si au début du programme dans setup() on change les valeurs à l'intérieur de size(), on n'a pas besoin de modifier les parties du programme où interviennent la largeur et la hauteur de la fenêtre.

Que fait le programme suivant ? Remplacer les nombres à l'intérieur de size() et observer que le programme produit le même résultat


void setup(){
  size(400,400);
  background(255);
}

void draw(){
 
  line(width/2, 0, width/2, height);
  line(0, height/2, width, height/2);
}

La lisibilité du programme devient meilleure car les "magic numbers" disparaissent peu à peu pour laisser la place à des variables au nom significatif

Variables: type,déclaration et affectation

Au lieu de passer directement d'un fonds blanc à un fonds noir on aimerait que la couleur du fonds varie graduellement à chaque clic de souris.

//déclaration de la variable globale couleurFonds
int couleurFonds;
void setup(){
//affectation initiale de la variable
  couleurFonds = 255;
  size(400,400);
  background(couleurFonds);
}

void mousePressed(){
//affectation de la variable
   couleurFonds = couleurFonds - 10;
   
}
void draw(){
 	println(couleurFonds);
    	background(couleurFonds);
}

 

Pour faire cela on va introduire une variable nommé couleurFonds.

Tester le programme ci-dessus.

Une variable a un type, par exemple int pour integer c'est à dire entier pour des nombres comme 2 ou 100 ou -5, float pour décimal comme 2.95 ou encore -1.5. Le premier type de variable est dit primitif (voir le dictionnaire). Un autre type est dit composite. Nous verrons cela au fur et à mesure de nos besoins.

La mémoire de l'ordinateur peut être vue comme une ensemble de boîtes (variables). Un programme peut être vue comme une suite d'instructions (séparées par des ; ) qui agissent sur le contenu de ces boîtes. Chaque boîte utilisée par le programme a un type , un nom et contient une valeur.

Déclarer une variable revient à réserver une boîte en mémoire en précisant le nom de la boîte et ce que l'on y met dans la boîte. Par exemple int couleurFonds; est l'instruction qui déclare la variable couleurFonds de type int

Affecter une valeur à une variable nommée couleurFonds se fait en écrivant dans le programme une instruction de la forme

couleurFonds = .....

A droite du signe égal il peut y avoir un nombre comme 255, dans ce cas cela signifie que la valeur contenue dans la variable couleurFonds est 255, mais il peut y avoir une expression comme couleurFonds - 20, ce qui signifie que (en lisant de la droite vers la gauche) on retranche 20 à la valeur contenue dans couleurFonds, puis on met le résultat dans couleurFonds.

Variables: portée

La portée d'une variable est le corps de la fonction dans laquelle elle a été déclarée. Elle n'est reconnue qu'à l'intérieur de cette zone. Si elle a été déclarée en dehors de toute fonction alors on dit qu'elle est globale

Mini-projet personnel ( à rendre avant J+7)

  1. Faire un programme (votre nom_1) qui dessine un cercle à l'écran qui suit le pointeur de la souris (/5 points)
  2. Faire un programme (votre nom_2)qui réalise un dessin symétrique de la manière suivante: Lorsque vous tracez une courbe avec le pointeur de la souris,le symétrique de cette courbe par rapport à la droite verticale passant par le centre de la fenêtre, est tracée aussi(/5 points)