Méthodetutorial de programmation |
|
Soll Le Witt Wall Drawings #935, 1999 |
En 1968, Sol LeWitt conçoit son premier "Wall drawing" à la Galerie Paula Cooper à New York.Tout au long de sa vie il concevrait encore des centaines des WallDrawings par tout dans le monde. Le Wall drawing's consiste en une courte description, dans le genre a wall divided horizontally and vertically into four equal parts. Within each part, three of the four kinds of lines are superimposed."( Wall Drawing #11, 1968)qui sont ensuite exécuté par un ou plusieurs assistants. |
|
Sol LeWitt, Wall drawing #11, 1968 |
Par cet acte, il manifeste la primauté de l'idée avant l'execution. Mais il met aussi en question l'oeuvre d'art comme unique et précieux. Il développe ensuite ses idées sur l'art conceptuel dans "Paragraphs on Conceptual Art" (1969). Ghislain Mollet-Viéville résume l'art conceptuel de LeWitt d'une manière suivante:
Cette conception d'art a évidement plusieurs parallèle avec l'art conçu par l'ordinateur. D'abord, l'oeuvre existe avant sa matérialisation picturale. Sa conception consiste en une description précise (le code) et elle est indépendant de sa visualisation. Sa réalisation a une statut éphémère, c'est seulement l'idée qui est consistant. Son exécution n'est pas fait par l'artiste (c'est l'ordinateur)
Dans ce cours, nous allons approfondir le concept d'instruction et d'apprendre comment crée ses propres instructions,appeler: méthode.
Sol LeWitt: "Paragraphs on Conceptual Art "
Casea Rea: Software and drawing
Une méthode est un des éléments de base pour structurer les programmes. Nous avons déjà utilisé souvent des fonctions, sans le savoir. C'est quoi alors une fonction? C'est simple: Une fonction a un nom et exécute des instructions. On peut appeler ces fonctions mais aussi les créer nous même. D'abord, on regarde les différents fonctions que nous avons déjà rencontré.
Quand nous dessinons un rectangle, nous appelons la fonction rect et remplissons les arguments ou bien des paramètres qu'il exige: la position x, y, la largeur et hauteur. Nous définissons ces arguments entre les parenthèses qui suivent le nom de la fonction.
Nous avons rencontré également des fonctions qui n'ont pas des arguments: noFill() par exemple est une fonction sans argument. Nous avons pas besoin de la spécifier comment remplir les formes suivants.
Le troisième type de fonction nous donne un valeur en retour. random(50) par exemple nous donne une float entre 0 et 50 en retour. Ce genre de fonction peut être affecté à un variable ou bien devient lui même argument dans une fonction:
int maVariable = random(20)// on affecte le( valeur d'un) méthode à une variable.
rect (random(10, 15), 15, 25, random(2, width); on utilise la méthode comme argument.
Nous allons créer maintenant nos propres méthodes:
Nous avons déjà rencontré void dans setup et draw. Avons de comprendre ceci nous avons crée notre propre méthode void. Imaginons qu'on veut dessiner un croix, au lieu de le écrire directement dans le corps de programme je me crée une méthode:
void croix(){
strokeWeight(10);
stroke(255,0,0);
line (width/2-20, height/2+20, width/2+20, height/2-20);
line (width/2-20, height/2-20, width/2+20, height/2+20);
}
Cool, mais je voit rien? ...On a dit qu' il faut appeler la fonction:
void setup(){
}
void draw(){
croix();
}
void croix(){
strokeWeight(10);
stroke(255,0,0);
line (width/2-20, height/2+20, width/2+20, height/2-20);
line (width/2-20, height/2-20, width/2+20, height/2+20);
}
Donc d'un coup notre programme principale comporte qu'un seul ligne et il est plus compréhensible d'écrire croix() que tous les lignes de codes qui sont dans la méthode. Même dans 2 semaines je comprends encore à quoi ressemble croix().
C'est très beau de faire une ligne de code au lieu de 4, mais on peu faire encore mieux. Imaginons que nous voulons faire pleins des croix. Si j' écris:
croix();
croix();
croix();
J'ai écrit 3 croix, mais ils sont superposé, donc ce n'est pas la bonne méthode. Il faut rajouter une argument (ou aussi appeler 'paramètre') pour pouvoir le placer ou je veux, donc une position x et y comme pour la méthode point() et comme je veux aussi changer sa taille, je rajoute un 3ème argument.
void croix(int posX, int posY, int taille){
strokeWeight(taille/3);//l'epaisseur du trait est proportionnel à la taille>
stroke(255,0,0);
line (posX-taille/2, posY+taille/2, posX+taille/2, posY-taille/2);
line (posX-taille/2, posY-taille/2, posX+taille/2, posY+taille/2);
}
Mes arguments sont alors des variables que je définis entre les parenthèses. Quand j'appelle maintenant ma fonction, je dois évidement renseigner les trois arguments qui seront injecter dans la méthode par ordre
croix(20, 30, 10);
croix(20,60, 20);
croix(50,random(width), 30);
Ainsi je passe des valeurs de mon programme dans mon sous-programme ou il affecte des variables. Dans croix(20,30,10) le premier chiffre '20' devient la valeur pour le premier argument (int positionX) de ma méthode et ainsi de suite.
On appelle fonction un sous-programme qui permet d'effectuer un ensemble d'instruction par simple appel de la fonction dans le corps du programme principal. Les fonctions permettent d'exécuter dans plusieurs parties du programme une série d'instructions, cela permet une simplicité du code et donc une taille de programme principale minimale. Nous distinguons des fonctions sans et avec arguments et sans et avec valeur de retour.
Nous avons vue que la méthode random() nous donne un valeur, on peut écrire x=random(10); par contre
x=point(2,8);n'est pas possible.
La méthode random() est donc une méthode avec un valeur de retour. Notre méthode croix() exécute des lignes de code, mais elle même ne contient pas de valeur. Il y a donc cet autre type de méthode qui à la place de void contient un type de donnée. On peut créer des méthodes int, float, boolean ect. et à la fin de la méthode, on indique quel valeur contient la méthode par le mot clé return (retour en français). Cela sonne compliqué mais c'est simple. Alors un exemple:
void setup(){
}
void draw(){
rect(nouvelleValeur(), height/2, 20,20);
}
int nouvelleValeur(){ // ma propre méthode!!
int x= 50;
return x;
}
J'ai crée un méthode qui s'appelle "nouvelleValeur" dont la valeur de retour est un integer (int) . Ensuite, il y a les lignes de codes, dans ce cas seulement une qui assigne 50 à la variable x. Dans la ligne suivant, on rencontre le mot clé return qui indique ce que la méthode doit contenir comme valeur, ce qui est dans notre cas la valeur de x. C'est à dire elle envoie la valeur de x à la place de l'appel de la méthode en haut dans le code, ce qui donne rect(50, height/2, 20,20). La méthode devient un sort de variable intelligente.
Revenons sur la méthode void. Maintenant on comprend ce que cela signifie void = vide. La méthode void ne contient pas de valeur de retour (ce qui ne pas du tout la même chose que 0). Si on écrit x=maMethodeVoid(); Processing va protester, on ne peut pas associer un nonValeur à un variable qui stock des valeurs...
Maintenant on peut bien sure rajouter des arguments a notre variable de retour. Pour faire simple, imaginons on veut crée une méthode qui additionne 2 chiffres est qui nous donne le résultat en retour. addition() dans le code contient la valeur 5.
void setup(){
int a=2;
int b=3;
int c= addition(a, b)
print(c);
}
int addition(int cumulande1, int cumulande2){
int somme=cumuland1+cumulande2;
return somme;
}
Attention, les variables qui sont crée dans la méthode ont un 'scoop local', il est uniquement connu dans la méthode. Si j'aurais écrit: int c=somme; processing aurait protesté.
La méthode nous permet de couper le code en plusieurs morceaux et au lieu que l'ordinateur lie le code ligne après ligne, on peut faire sauter la lecture d'un bout à l'autre qui ne sont pas forcement écrit successivement. Cet aspect de redirectionner le code d'un bout à l'autre est renforcé par la possibilité d'appeler une méthode dans une autre.
void setup(){
methode1();
}
void methode1( ){
methode2();
}
void methode2( ){
rect(20, 20, 20, 20);
}
Reprenons l'exemple du croix qu'on veut faire bouger et rebondir aux bords.Pour chaque chose on écrit une méthode différente.
nt x, y, tailleCroix=30;
int acc=5;
void setup(){
size(400, 400);
}
void draw(){
background(0);
croix(x, y, tailleCroix);
x=bouge(x, acc);
y=bouge(y, acc);
changerDirection(width, height);
}
void croix(int posX, int posY, int taille){
strokeWeight(taille/3);
stroke(255,0,0);
line (posX-taille/2, posY+taille/2, posX+taille/2, posY-taille/2);
line (posX-taille/2, posY-taille/2, posX+taille/2, posY+taille/2);
}
int bouge(int position, int accLocal){
position=position+accLocal;
return position;
}
boolean checkEdge(int large, int haut){
if (x>large|| y >haut||x<0||y<0){
return true;
}
else{
return false;
}
}
void changerDirection (int limiteHorizontal, int limiteVertical){
if(checkEdge(limiteHorizontal,limiteVertical)){
acc=acc*-1;
}
}
Il existe encore d'autres facçon d'utiliser les méthodes, l'un c'est la surcharge de méthode et l'autre la méthode recursive. La surcharge de méthode permet d'utiliser les même nom pour une méthode mais avec différents arguments. En principe, nous les connaissons déjà, par exemple la méthode color permet de renseigner un, deux, trois ou quatre arguments (1 ton de gris, 2=ton de gris et alpha, 3=rgb...). De la même manière, nous pouvons écrire maMethode(int argu1) {...code} et ma methode(int argu1, float argu2){...code}
Si j'appelle maMethode(3);, Processing va chercher la première méthode et si j'écrit maMethode(2, 2.5); Processing va chercher la deuxième méthode.
Les méthodes recursives sont en principe aussi très simple, mais dans la pratique un peu moins simple. Le principe est qu'un méthode s'appelle soi même. C'est comparable à deux mirroir qui sont en face, l'image se reproduit sans fin. Si on ferait la même chose avec l'ordinateur, il sera content, car il calculera sans fin (ce qu'il aime bien) mais pour nous c'est embêtant, car il bug.
Imaginons un methode de additioner tous les chiffres entiers:
int MethodePourAdditionner(int chiffre){
chiffre = chiffre+1;
int resultat = chiffre;
MethodePourAdditionner(resultat);
return (resultat);
}
Nous appellons notre méthode dans le setup (nous n'avons pas besoin le draw) - Processing refuse de le faire, mais pourquoi!
void setup(){
MethodePourAdditionner(1);
}
L'ordinateur lit jusq'à la 4ème ligne et récommence, lit jusq'à la 4ème ligne et récommence, lit jusq'à la 4ème ligne et récommence, lit jusq'à la 4ème ligne et récommence, lit jusq'à la 4ème ligne et récommence, ...
Alors il faut intégrer une condition pour sortir de ce boucle infernal, genre
int resultat;
void setup(){
int somme =MethodePourAdditionner(1);
println(somme);
}
int MethodePourAdditionner(int chiffre){
chiffre = chiffre+1;
resultat += chiffre;
if (chiffre <10){
MethodePourAdditionner(chiffre);
return (resultat);
}
else {
return (resultat);
}
}
Une methode avec valeur de retour doit toujours pouvoir retourner un resultat, c'est pour cela le "return" apparait dans les deux condition ( if + else)
Ce qu'il faut connaître: |
void draw(){
forme();
event();
transformeForme();
...
}