..... a. Cahier des charges...... b. Cadre graphique de travail...... c. Fonctionnement général...... d. Détails techniques...... e. Mise au point.
Ce T.P. propose de mettre en place un moteur d'animation un peu plus élaboré que celui du mini-projet 2. En effet, dans le mini-projet 2,
nous n'avions qu'un seul objet géré par le moteur d'animation : la balle (la raquette étant gérée indépendemment à la souris).
Maintenant que nous disposons des listes, nous allons voir ici comment les exploiter pour gérer simultanément un grand nombre d'objets dans notre animation.
Ce T.P. s'avère indispensable à réaliser pour beaucoup de projets de jeux vidéos proposés : ce même mécanisme pouvant être ré-employé dans de nombreux contextes.
a) Cahier des charges.
dans ce T.P., partant d'une image de fond : Lionnes, nous aimerions "faire pleuvoir" des flocons de neige
pour produire l'animation suivante :
b) Cadre graphique de travail.
Créer une fenêtre tKinter avec un canevas 640x426 et l'image de fond proposée ci-dessus.
c) Fonctionnement général.
Modèle de données :
comme le suggère la vidéo ci-dessus, nous allons devoir gérer simultanément un grand nombre de flocons (des items oval dans tKinter).
Pour s'y retrouver, il semble pertinent de les classer dans une liste "flocons".
Les positions de ces flocons seront quant à elles stockées dans 2 autres listes : "posfloconsx" et "posfloconsy" (abscisses et ordonnées).
Initialisations :
Nous initialiserons ces 3 listes dans le main :
posfloconsx=[]
posfloconsy=[]
flocons=[]
Fonction d'animation :
ce sera le cerveau et le moteur de notre animation. Elle accomplit deux principales missions :
créer des flocons,
déplacer les flocons, et les supprimer des 3 listes lorsqu'ils sortent de l'écran.
Cette fonction devant mettre à jour les flocons et les affichages régulièrement, elle sera récursive.
d) Détails techniques.
Etape 1 : production des flocons :
afin de ne pas remplir l'écran entier de flocons, au risque de ne plus rien voir, nous pourrons nous limiter à 20 flocons maximum à la fois,
s'il n'y a pas encore 20 flocons dans la liste : on tire au sort une colonne où tombera le prochain flocon (from random import randint, puis : col = randint(0, 63)),
on ajoute à l'aide de la méthode append ce nouveau flocon dans les 3 listes,
pour ne pas créer qu'un seul flocon et attaquer la production des flocons suivants : fen.after(100, ...)
Etape 2 : déplacement des flocons :
dans l'étape 1, nous voyons apparaître nos 20 premiers flocons, mais ceux-ci restent figés en haut de la fenêtre. Faisons les tomber maintenant :
l'idée sera de parcourir toute la liste des ordonnées de flocons :
si le flocon est sorti de la fenêtre (ordonnée > 436), on supprime ce flocon des 3 listes,
sinon, on augmente l'ordonnées de 10 pixels, et on déplace le flocon à l'écran : méthode "move".
Problème technique :
la taille de nos listes va changer durant le parcours de la boucle puisque certains flocons (et leurs positions) seront supprimés durant le parcours de la boucle !
Une boucle "for" du type : "for compteur in range(0, len(flocons)) :" est donc exclue : len(flocons) va changer au cours du parcours de la boucle.
Nous devrons donc parcourir ces listes avec une boucle while "artisanale" :
Le résultat obtenu est presque parfait, mais un point doit choquer votre oeil expert : les flocons tombent par vagues successives !
En effet, une fois les 20 premiers flocons créés, il faut attendre que certains disparaissent, en bas de la fenêtre, pour que d'autres puissent à nouveau être produits.
Nous aimerions donc étaler dans le temps la production de ces 20 flocons, pour que tous ne soient produits tout de suite, et avoir un rendu plus naturel.
Pour y parvenir, il faudrait que notre boucle d'animation ne produise pas de flocon à tous les tours de boucles. Nous allons ainsi rendre aléatoire la production (ou non)
d'un flocon, lors d'un tour de boucle. Nous pourrons par exemple utiliser une instruction du type :
if len(flocons) < 20 and randint(0, 1) == 0 :
Ainsi un nouveau flocon n'est fabriqué, en moyenne, que dans un tour de boucle sur 2 !