Profitez-en, après celui là c'est fini

Processing, huitième cours

novembre 28th, 2008 Posted in Processing

Les programmeurs aguerris qui m’ont lu jusqu’ici se sont sans doute inquiétés : qu’est-ce que c’est que ce langage sans structure, dont les commandes sont lancées n’importe comment, à la façon des langages interprétés comme le bon vieux langage Logo, créé dans les années 1960 et qui servait aussi à dessiner ? Ils peuvent se rassurer : Processing est un langage tout aussi structuré que les autres. J’espère que les lignes qui vont suivre ne paraîtront pas trop abstraites à certains de leurs lecteurs. Néanmoins le sujet sera rabâché par la suite.

Il existe deux fonctions de base réellement importantes dans processing : setup(), et draw(). La fonction setup() est lancée une seule et unique fois, au démarrage de l’animation. La fonction draw() s’exécute de manière redondante selon la fréquence qu’on lui a imposé (par exemple 25 fois par seconde).
Une chose très importante à savoir, c’est qu’un programme processing qui n’a pas de setup() ni de draw() peut rencontrer des problèmes. Les fonctions créées par le programmeur ou les fonctions relatives à l’interactivité (clic, clavier,…) ne marcheront pas, par exemple.

setup()

C’est dans le setup, lancé une seule fois, que l’on initialise des variables, que l’on règle le format d’écran, sa couleur, et plus généralement tout ce qui doit être réglé au démarrage et a fortiori ce que l’on ne veut régler qu’une seule fois.
Voici un setup() typique :

void setup(){
  size(500,500);
  background(0);
  smooth();
  frameRate(24);
}

Vous connaissez déjà les commandes size (le format de la fenêtre), background (la couleur de fond) et smooth (le lissage des dessins).  Nous découvrons en revanche la fonction frameRate(), extrêmement utile puisqu’elle sert à décider de la rapidité d’exécution d’une animation. Avec frameRate(1), nous créons une animation qui affichera une image par seconde ou, plus précisément, qui exécutera la fonction draw() une fois par seconde.

draw()

draw() est donc la fonction redondante de Processing, sa « boucle temporelle ». Toute instruction que l’on écrit dans draw() sera exécutée à une fréquence précise jusqu’à ce que l’on ferme l’application ou jusqu’à ce que le programme tombe sur l’instruction noLoop(); qui inhibe l’exécution de draw();
Avec le petit programme qui suit, une ligne va être tracée à des coordonnées aléatoires de manière régulière.

void draw(){
  line(random(100),random(100),random(100),random(100)); 
}

Notez que l’exemple ci-contre a été monté sous forme de gif animé à l’aide… d’un concurrent de processing. Ce n’est donc pas une authentique animation processing mais plutôt une simulation.
Quoi qu’il en soit, il suffit donc de créer une fonction draw() pour exécuter des actions de manière régulière. C’est ce type de disposition qui fait de processing un système spécialisé dans la création visuelle. Si l’on compare avec le langage Java (qui sert de support à processing) les choses se dérouleraient bien différemment. Il faudrait commencer par déclarer l’emploi de telles et telles « librairies », puis inventer un « timer » qui de manière redondante permettrait d’exécuter certaines actions… Bref, on s’y perd vite. Ici, les besoins spécifiques à la création artistique sont intégrés et leurs commandes sont simples à manipuler.

Les fonctions

Malgré la simplicité du système, la structure des fonctions (setup() et draw() sont des fonctions) est sans doute un peu troublante à lire pour ceux qui ne connaissent pas ce genre de langage — ou pour ceux qui ne connaissent rien à la programmation. Elle est toujours la même :
type nom( arguments ){ instructions }, où type est le genre de données que la fonction renvoie. Si elle doit renvoyer un chiffre entier, le type sera int. Si elle doit renvoyer une chaîne de caractère, le type sera String. Enfin, si la fonction ne renvoie rien, le type à indiquer est void. Les gestionnaires draw() et setup() sont des fonctions qui ne renvoient pas de données, on écrit donc void devant.
Le nom de la fonction doit être une chaîne de caractères, commençant par une lettre, sans espace. Il faut impérativement que ça ne soit pas un mot réservé de processing.
Les arguments sont les éventuels paramètres que la fonction s’attend à recevoir. Pour une fonction ne recevant aucun paramètre, on se contentera de mettre une parenthèse ouvrante et une parenthèse fermante, comme draw() ou setup(). Sans les parenthèses, le programme ne comprend pas qu’il s’agit de fonction.
Processing est un langage rigoureusement typé, c’est à dire qu’il refuse de ne pas savoir de quel type (entier, flottant, chaîne, caractère, double, booleen,…) est une variable1 . Cette fonction assez simple pourra vous permettre d’y voir un peu plus clair en pratique.

float distance(float x1, float y1, float x2, float y2) {
  float cote1 = x1-x2;
  float cote2 = y1-y2;
  return sqrt(pow(cote1, 2)+pow(cote2, 2));
}

Pour l’anecdote, la fonction ci-dessus sert à calculer la distance qui sépare deux points à l’aide du théorème de Pythagore. Chaque ligne dont on connaît les coordonnées sur un écran est en fait l’hypoténuse d’un triangle-rectangle. Avec une ligne dons les points sont (x1, y1) et (x2, y2), je sais que la longueur du côté horizontal de mon triangle-rectangle est (x2-x1) – ou x2-x1, ça reviendra au même – et que son côté vertical a pour longueur (y2-y1). Nous connaissons donc nos deux côtés. Puisque nous savons que le carré de l’hypoténuse est égal à la somme des carrés des deux autres côtés, nous savons aussi que la racine carrée de la somme des carrés des deux autres côtés est égale à la longueur de l’hypoténuse. Ainsi si j’invoque ma fonction de cette manière : distance(0, 0, 100, 100), je recevrais 141.421… comme résultat, car c’est la longueur de l’hypoténuse d’un carré de 100×100. Toujours pour l’anecdote, sqrt(x) renvoie la racine carrée de x et pow(z, 2) élève z au carré.
Dans ma fonction, float est donc le type de variable que la fonction doit retourner. On peut dire que la réponse de notre fonction sera un nombre décimal (ou « à virgule flottante », d’où le « float »).
Le nom de la fonction est distance. Ce n’est pas un nom interne à Processing, c’est moi qui l’invente. J’aurais pu aussi bien nommer cette fonction obtiensDistance ou pythagore.
Les arguments qui sont envoyés entre parenthèses à ma fonction sont ici au nombre de quatre (l’abscisse du premier point, l’ordonnée du premier point, l’abscisse du second point et l’ordonnée du second point). Pour chaque argument, Processing doit savoir de quel type de variable il s’agit. Ici, tous les nombres qui sont envoyés sont des décimales, donc ils sont passés, séparés les uns des autres par des virgules et précédés chacun de leur type de donnée. Si j’invoque ma fonction comme ceci : distance(1, 2, 3, 4), la fonction placera le chiffre 1 dans sa variable flottante x1, le chiffre 2 dans sa variable flottante y1, le chiffre 3 dans x2 et le chiffre 3 dans y2.
Les deux lignes suivantes pratiquent divers calculs arithmétiques qui sont renvoyés par le mot return.

Je suppose que beaucoup auront souffert avec cette page austère et au contenu pour le moins abstrait.
La suite devrait être plus amusante.

  1. les langages strictement typés sont les plus performants car ils sont plus proches de la manière d’exécuter les programmes du système. C, C++ ou Java sont strictement typés tandis que Lingo, PHP et Javascript sont plus désinvoltes et donc moins performants. []
  1. 3 Responses to “Processing, huitième cours”

  2. By SOLIVERES on Avr 4, 2012

    Bonjour,
    Le dernier sketch qui calcule la distance entre deux points n’affiche pas le résultat.
    On pourrait donner un code qui fait tourner la fonction distance sur un exemple et affiche le résultat.

    Merci d’avance.

  3. By Jean-no on Avr 4, 2012

    Un truc comme ça ?

    void draw(){
    background(0);
    text(dist(mouseX, mouseY, width/2, height/2), 10,10);
    }

  4. By SOLIVERES on Avr 4, 2012

    Oui, pas mal…et le jeu consiste à positionner sa souris au centre de la fenêtre !

Postez un commentaire


Veuillez noter que l'auteur de ce blog s'autorise à modifier vos commentaires afin d'améliorer leur mise en forme (liens, orthographe) si cela est nécessaire.
En ajoutant un commentaire à cette page, vous acceptez implicitement que celui-ci soit diffusé non seulement ici-même mais aussi sous une autre forme, électronique ou imprimée par exemple.