Animation , notion de récursivité (Python et Tkinter)

Transcription

Animation , notion de récursivité (Python et Tkinter)
Animation , notion de récursivité (Python et Tkinter)
Dans le « Interface graphique avec Python » vous avez appris à manipuler les différents widgets, ce
TP va vous permettre de créer une animation.
Pour cela vous allez apprendre à : 1-détecter et positionner un clic de souris (un exercice à faire),
2-déplacer un objet à l’aide du clavier (détection du clavier) et 3-animer un objet.
Vous mènerez ensuite en fin de séance un mini-projet en binôme.
1. Détection et positionnement d’un clic de souris
Afin de comprendre le principe, encodez et expérimentez le script ci-dessous :
# Détection et positionnement d'un clic de souris dans une fenêtre :
from tkinter import *
def pointeur(event):
chaine.configure(text = "Clic détecté en X =" + str(event.x) +\
", Y =" + str(event.y))
fen = Tk()
cadre = Frame(fen, width =200, height =150, bg="light yellow")
cadre.bind("<Button-1>", pointeur)
cadre.pack()
chaine = Label(fen)
chaine.pack()
fen.mainloop()
Explications : On créé un ‘’cadre’’ rectangulaire (Frame) dans une fenêtre ‘’fen’’ (fen = Tk()).
On déclenche la détection de l'événement <clic à l'aide du premier bouton de la souris> avec la
méthode bind appliquée au widget cadre, la fonction ‘’pointeur’’ est alors appelée:
cadre.bind("<Button-1>", pointeur)
La fonction appelée contient toujours le paramètre event (def pointeur(event):), qui renvoie les
coordonnées de notre souris sur notre fenêtre par event.x et event.y.
‘’chaine’’ est un label positionné dans la fenêtre ‘’fen’’ avec la méthode pack et modifié par la
fonction ‘’pointeur’’ (à l’aide de la méthode configure) pour afficher le texte définissant la
position de la souris.
Exercice 1 :
Modifiez le script ci-dessus de manière à faire apparaître un petit cercle rouge à l'endroit où
l'utilisateur a effectué son clic (vous devrez d'abord remplacer le widget Frame par un widget
Canvas, inutile d’afficher la position de la souris). «1-souriscercle-votrenom.py)
Point info : détection de la souris
On détecte la souris de la même façon avec la méthode bind :
<Button-1> : click sur le bouton gauche de la souris
<Button-2> : click sur la molette de la souris
<Button-3> : click sur le bouton droit de la souris
<Double-1> : double-click gauche
<Button1-Motion> : glissement de la souris avec le bouton gauche appuyé
2. Déplacer un objet avec le clavier.
Tkinter offre la possibilité de déplacer un objet (une image, un dessin ) par la fonction :
objet.coords( nomobjet , x1 , y1 , x2 , y2 ) #efface et redessine l'objet
nomobjet désigne le nom de l'objet à déplacer
x1,y1,x2,y2 sont les nouvelles coordonnées de l'objet,
Cette instruction efface l'objet et le recrée plus loin, sans qu'on ait à écrire ces deux étapes .
Afin de comprendre le principe, encodez et expérimentez le script ci-dessous :
# Déplacer un objet au clavier
from tkinter import *
# procédure générale de déplacement :
def avance(gd, hb):
global x, y
x, y = x +gd, y +hb
canevas.coords(bille,x,y, x+50,y+50)
# définition des gestionnaires d'événements :
def gauche(event):
avance(-10, 0)
def droite(event):
avance(10, 0)
def haut(event):
avance(0, -10)
def bas(event):
avance(0, 10)
#------ Programme principal ------fen=Tk()
fen.title('déplacement au clavier avec tkinter')
canevas=Canvas(fen,bg='dark gray',height=300, width=300)
canevas.pack()
x,y=50,50
bille= canevas.create_oval(x,y,x+50,y+50,fill='orange')
msg=canevas.create_text(150,10,text="Utiliser les flèches \
pour déplacer la bille",font="Arial 12")
fen.bind("<Left>",gauche)
fen.bind("<Right>",droite)
fen.bind("<Up>",haut)
fen.bind("<Down>",bas)
fen.mainloop()
Explications : Vous avez déjà compris dans le TP interface graphique que l'instruction mainloop()
était en fait une boucle de surveillance des événements clavier et souris.
Pour détecter une entrée clavier (touche flèche gauche : Left), on va relier (bind en anglais) cet
évenement à une fonction ‘’gauche(event)’’ :
fen.bind("<Left>",gauche)
A placer avant notre instruction mainloop qui doit toujours être la dernière.
Chaque fois que Python va détecter la pression sur la flèche gauche, il va déclencher la fonction
‘’gauche(event)’’ que l'on écrit avec le paramètre event, obligatoire en cas de détection
d'événements : il contient des informations sur l'événement détecté.
Vous remarquez qu'on note la fonction gauche sans parenthèses lors de l’appel, c'est normal : on
n'appelle pas la fonction gauche à cet instant, mais on relie sa définition à l'événement "quelqu'un
appuie sur la flèche gauche".
Remarquez aussi la ligne global x, y , à l'intérieur de notre fonction ’gauche(event)’’ Python
reconnait nos variables x et y, on les lui a défini juste avant, mais il refuse de les modifier sans cette
instruction global qui lui indique que ces deux variables sont utilisées dans tout le programme et
modifiables dans la fonction, pour les programmeurs habitués à d'autres langages, c'est un peu
bizarre de devoir le préciser ici, peut-être que pour vous aussi ?
Point info : détection du clavier
On détecte l'événement "une touche a été enfoncée au clavier", avec la méthode bind ,
principaux autres évènements :
<KeyPress-A> : la touche A majuscule du clavier
<KeyPress-a> : la touche a minuscule du clavier
<Control-Shift-KeyPress-A> : la combinaison de touches Ctrl+Shift+A
<Escape> : la touche Echap.
<F1> : la touche de fonction F1
<Return> : le retour chariot : touche entrée
<Any-KeyPress> : n’importe quelle touche
3. Animation.
Un exemple de déplacement d'une bille avec la fonction coords.
Afin de comprendre le principe, encodez et expérimentez le script ci-dessous:
# Animer un objet
from tkinter import *
fen=Tk()
fen.title('animation avec tkinter')
canevas=Canvas(fen,bg='dark gray',height=300, width=300)
canevas.pack()
x,y=50,50
bille= canevas.create_oval(x,y,x+50,y+50,fill='orange')
def anime():
global x, y
if x<=250:
x,y=x+1,y+1
canevas.coords(bille,x,y, x+50,y+50)
fen.after(10, anime)
anime()
fen.mainloop()
Explications :
L'instruction fen.after(10,anime) redéclenche la fonction anime au bout de 10 secondes,
comme cette instruction se trouve à la fin de la fonction ‘’anime()’’, elle va se rappeler elle-même,
on l'appelle une fonction récursive (fonction qui s'appelle elle-même).
On obtient ainsi l'animation attendue avec un affichage toutes les 10 ms.
A retenir : Fonction récursive
Une fonction récursive est une fonction qui s’appelle elle-même.
MINI-PROJET à mener en binôme.
Lire toutes les consignes avant de commencer.

Programme à réaliser : Pseudo jeu du Pac-Man
Écrivez un programme qui permette de déplacer un Pac-Man (représenté par un
cercle) sur le canevas dans l'une des 4 directions : droite, gauche, haut, bas.
Le joueur lance la partie avec un bouton START : le Pac-Man commence alors à
avancer (sans que le joueur ait à appuyer sur une touche)
Le joueur peut à tout moment :



changer la direction suivie par le Pac-Man à l'aide des touches fléchées
du clavier.
Stopper la Pac-Man avec un bouton STOP.
Arrêter de jouer avec un bouton QUITTER.
Le joueur a perdu lorsque le Pac-Man touche l'une des parois.







Analysez ce cahier des charges et définissez les variables, fonctions, frames,
canevas …dont vous aurez besoin
Ecrivez l’algorithme en pseudo-code sur papier
Répartissez-vous le travail
Appelez la professeure pour lui montrer ce travail
Codez votre algorithme, nom du programme : «Animation-nom1-nom2.py »
Testez le, commentez-le, toilettez-le.
Sauvegardez-le sur le réseau, vous pouvez alors signaler que vous avez terminé.
Poursuivez sur votre lancée : Améliorations (à apporter dans l’ordre, pensez à sauvegarder à
chaque étape la version validée et testée sur le réseau) :
1. Sur le canevas se trouvent également des « proies » (des petits carrés fixes disposés au
hasard). Il faut diriger le Pac-Man de manière à ce qu'il « mange » les proies sans arriver
en contact avec les bords du canevas. A chaque fois qu'une proie est mangée, le PacMan grossit, le joueur gagne un point, et une nouvelle proie apparaît ailleurs., La partie
s'arrête lorsque le Pac-Man touche l'une des parois ou lorsqu'il a atteint une certaine
taille.
2. Le Pac-Man ressemble à un Pac-Man !!! (bouche ouverte et avec un œil et la bouche est
dirigée dans le sens de la marche)
3. Chaque fois que le joueur change de direction la vitesse augmente
4. Le joueur choisit la vitesse du Pac-Man avec un curseur en début de partie.
5. Le joueur place lui-même les proies avant de commencer
6. Selon votre inspiration …..
Sitographie :
Sources d’inspiration de ce TP :
http://python.developpez.com/cours/TutoSwinnen/?page=Chapitre8
http://softdmi.free.fr/tuto_python/tuto-python.php?chapitre=2&page=1
et pour aller plus loin :
http://fsincere.free.fr/isn/python/cours_python_tkinter.php
http://fr.wikibooks.org/wiki/Apprendre_%C3%A0_programmer_avec_Python/Utilisation_de
_fen%C3%AAtres_et_de_graphismes