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