INTRODUCTION |
Les graphiques par ordinateur sont souvent utilisés pour représenter des données variant avec le temps. On s’en sert par exemple pour simuler un processus physique ou biologique ou encore pour créer des jeux. On parle alors généralement d’animation. Pour montrer une séquence temporelle, de nouvelles images sont dessinées les unes après les autres, espacées de manière régulière, ce que l’on nomme pas d’animation. |
MODIFIER LES VARIABLES GLOBALES |
Il est très courant d’introduire une boucle d'animation infinie dans le programme principal dont le rôle est d’appeler la fonction step() de manière répétitive. En terminant cette boucle par un délai, on peut définir les pauses à marquer entre chaque étape de l’animation et de ce fait régler la vitesse d’animation. La fonction step() incrémente la variable globale tà chaque pas de la simulation et la réinitialise à 0 une fois le tour complet effectué. On sait que le tour est terminé lorsque t >= 2*pi = 2 * 3.14 = 6.28. Une fois le tour terminé, on change de couleur. import math from gpanel import * def step(): global t x = r * math.cos(t) y = r * math.sin(t) t = t + 0.1 if t > 6.28: t = 0 setColor(getRandomX11Color()) move(x, y) fillCircle(10) makeGPanel(-500, 500, -500, 500) bgColor("darkgreen") t = 0 r = 200 while True: step() delay(10) |
MEMENTO |
Python ne permet pas de changer la valeur des variables globales de l’intérieur d’une fonction, car cela pourrait poser de nombreux problèmes qu’il faut éviter à tout prix. On peut cependant faire sauter cette sécurité en déclarant la variable comme globale au sein de la fonction à l’aide du mot-clé global. Ce mot-clé global doit être utilisé avec la plus grande prudence car il implique un risque dont il faut être conscient : toute fonction peut non seulement modifier une variable déclarée comme globale, mais il peut également la créer comme le montre l’exemple suivant ::def set(): global a a = 2 def get(): print "a =", a set() get() Du fait que set() engendre une variable a qui est visible dans tout le programme, on dit que la fonction set() engendre des effets de bord. Remarquez en passant la manière dont la commande print permet d’écrire plusieurs choses différentes dans la fenêtre de sortie en les séparant par des virgules. Dans la sortie, les virgules sont remplacées par des espaces. |
ANIMATIONS FLUIDES |
Pour que l’animation soit fluide et régulière, il faut s’arranger pour que les pauses entre chaque étape de l’animation soient de même durée, sans quoi le mouvement risque d’apparaître saccadé. La fonction step() permet de préparer la prochaine étape de l’animation. Le temps d’exécution de cette opération peut varier selon la situation, du fait que le programme n’exécute pas toujours les mêmes parties du code d’une part et surtout parce que le processeur peut être plus ou moins occupé à d’autres tâches de fond qui pourraient retarder l’exécution du code Python à certains moments. Pour compenser cette variation dans la durée d’exécution de step(), on peut utiliser l’astuce suivante à laquelle vous avez peut-être déjà pensé : avant d'appeler step(), on mémorise le temps actuel dans la variable startTime. Après avoir terminé l’exécution de step(), on attend dans une boucle d’attente jusqu’à ce que la difference entre l’heure actuelle et l’heure précédemment mémorisée corresponde à la période d’attente désirée entre chaque étape de l’animation.
from gpanel import * import time def step(): global x global v clear() lineWidth(5) move(25, 300) rectangle(50, 100) move(575, 300) rectangle(50, 100) x = x + v image("_sprites/football.gif", x, 275) if x > 500 or x < 50: v = -v makeGPanel(0, 600, 0, 600) bgColor("forestgreen") enableRepaint(False) x = 300 v = 10 while True: startTime = time.clock() step() repaint() while (time.clock() - startTime) < 0.020: delay(1) |
MEMENTO |
Avec time.clock(), on peut récupérer l’heure actuelle sous forme d’un nombre décimal. La valeur retournée est dépendante de l’ordinateur et du système d’exploitation. Dans certains environnements, time.clock() retourne le temps processeur et dans d’autres le temps écoulé depuis le premier appel à clock(). Mais comme on ne s’intéresse qu’à la différence entre les deux mesures du temps, cela n’a pas d’importance. Il suffit de mémoriser l’heure avant l’appel de step() et d’attendre à la fin de boucle d’animation, avec delay(1), que la différence entre l’heure actuelle et celle mémorisée dans startTime corresponde environ à la période d’animation désirée. Notez cette astuce car vous allez devoir la réutiliser à chaque fois qu’il faudra faire quelque chose à intervalles réguliers. Chaque commande graphique est immédiatement visible dans la fenêtre GPanel. De ce fait, effacer avec clear() pendant une animation va brièvement faire apparaître une fenêtre vide, ce qui cause un clignotement de l’animation désagréable. Pour éviter ce phénomène, il faut utiliser la technique du double buffering lors du rendu de nos animations. Cette technique consiste à utiliser l’instruction enableRepaint(False), qui permet d’effectuer le rendu graphique dans une mémoire tampon (buffer en anglais) hors écran et de n’afficher l’image que lorsque le rendu est terminé, ce qui réduit considérablement les effets de clignotement indésirables. Ainsi, la fonction clear() n’affecte que le tampon du rendu graphique et n’efface plus le contenu de la fenêtre graphique. Il faut par contre prendre soin d’afficher manuellement le contenu du tampon de rendu sur l’écran au moment opportun en appelant repaint(). Il faut veiller également à déclarer les variables x et v comme globales au sein de la fonction step() puisqu’il s’agit de variables globales modifiées depuis l’intérieur de la fonction. |
EXERCICES |
|