Programmation Python
Ce document est un tutoriel permettant de dĂ©couvrir le langage de programmation Python au travers d'un objectif : programmer le jeu « Pong » avec la librairie Pygame sous l'environnement de dĂ©veloppement EduPython. Ce document a Ă©tĂ© utilisĂ© par plusieurs enseignants pour des Ă©lĂšves de seconde, 1Ăšre et terminale, ainsi que des Ă©tudiants en DSAA DSAA : DiplĂŽme SupĂ©rieur d’Arts AppliquĂ©s n’ayant aucune formation poussĂ©e en science. Ce document est donc destinĂ© aux dĂ©butants en programmation. Suivre la construction pas Ă  pas d'un jeu comme Pong devrait permettre de comprendre et manipuler les notions de base de la programmation (boucles, tests conditionnels, etc.) ainsi que des notions plus avancĂ©es (animations, Ă©vĂšnements clavier-souris, notions de programmation objet). Le tutoriel vous accompagnera pour Ă©crire le programme du jeu Pong. Il est dĂ©coupĂ© en Ă©tapes clĂ©s (crĂ©er une fenĂȘtre de jeu, tracer une balle, animer un objet, contrĂŽles au clavier, etc.) et il sera possible d'avancer Ă  votre rythme sans jamais ĂȘtre bloquĂ©. En effet, chaque partie sera organisĂ©e de la maniĂšre suivante :
  • Objectif : par exemple, afficher une balle
  • Explication thĂ©oriques : par exemple, comment positionner et donner une couleur Ă  une figure gĂ©omĂ©trique
  • Exercices : par exemple, tracer des cercles de couleurs diffĂ©rentes Ă  diffĂ©rentes positions de la fenĂȘtre
  • Correction ou indices

PremiĂšre prise en main

Edupython est une distribution clé en main développée par le groupe AmiensPython. Il comprend des librairies utiles pour la programmation, les sciences et les mathématiques au lycée, ainsi que la librairie Pygame permettant de développer des jeux en 2D. Il est à la fois léger, complet et propose une version portable. C'est donc un excellent choix pour pratiquer la programmation au lycée et au delà. Si vous suivez ce tutoriel de chez vous, commencez par installer Edupython sur votre machine

L'interface de développement ou IDEIDE signifie Integrated Development Environment, ou Environnement de Développement.

L’interface de dĂ©veloppement est assez intuitive (voir figure ci-dessous). Les programmes seront rĂ©digĂ©s dans la zone d'Ă©dition. Parfois des petits tests pourront ĂȘtre rĂ©alisĂ©s dans la console. Il est possible de gĂ©rer plusieurs fichiers Ă  l'aide de la barre d'onglets. Un gestionnaire de variable permet Ă©galement de mieux dĂ©boguer ses programmes.
Le rendu du programme s’obtient simplement en cliquant sur le bouton « run » ou avec le raccourci clavier Ctrl + F9 Ouvrez Edupython. Dans la zone d'Ă©dition, entrez la commande suivante :
print("Bonjour, je vais bientĂŽt programmer le jeu Pong !!!")
Enregistrez ce fichier dans un nouveau dossier nommé pong, et l'appeler premier_programme.py Exécutez le programme. A quoi sert la commande print() ?

Indice 1

Pour exécuter, le programme, cliquez sur ou appuyer sur Ctrl + F9

Indice 2

On voit dans la console que la commande print() permet d'afficher le message que vous souhaitez

Indice 3

N'oubliez pas les "guillemets" pour afficher une chaĂźne de caractĂšres !
Nous proposons de crĂ©er une fenĂȘtre d'affichage de $200$ pixels par $200$ pixels, un fond blanc et une balle rouge de rayon $20$ pixels dont le centre Ă  pour coordonnĂ©es $(100,100)$. Le contenu graphique dans la fenĂȘtre d'affichage nĂ©cessite d'introduire la maniĂšre de reprĂ©senter numĂ©riquement les couleurs. La partie suivante y est consacrĂ©e. Afin de rĂ©alisĂ© l'objectif prĂ©cĂ©dent, il est important de bien comprendre comment sont positionnĂ©s les objets dans le plan, et la maniĂšre de reprĂ©senter les couleurs :

Comment sont représentées les couleurs numériquement ?

Positionnement dans une fenĂȘtre d'affichage.

Tout jeu utilisant la librairie Pygame commencera de la mĂȘme maniĂšre : un programme minimal qui consiste Ă  ouvrir une fenĂȘtre d'affichage avec un fond blanc.
  • Ouvrir l'IDE
  • Dans la zone d'Ă©dition, taper le programme ci-dessous
  • L'enregistrer dans un dossier nommĂ© pong, et l'appeler pong0.py
  • ExĂ©cuter le programme en appuyant sur run
  • Admirer :)
#importation de la librairie pygame import pygame #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = pygame.display.set_mode([500,500]) #remplissage du fond par la couleur dĂ©finie screen.fill([255,255,255]) #activer le rendu graphique (sans lequel rien n'est affichĂ©) pygame.display.flip() Changer la couleur du fond. Changer la taille de la fenĂȘtre du jeu.

Indice 1

La couleur est représentée par une liste de 3 valeurs [rouge, vert, bleu]

Indice 2

La taille de la fenĂȘtre est reprĂ©sentĂ©e par une liste de 2 valeurs [largeur, hauteur]
Pour l'instant, fermer la fenĂȘtre du jeu gĂ©nĂšre un bug. Nous le rĂšglerons Ă  la partie suivante.
L'objectif de tracer une balle rouge dans la fenĂȘtre n'est pas encore rempli. Quand on dĂ©couvre un langage de programmation, on sait ce qu'on peut faire (ici tracer un disque rouge), mais rarement comment. C'est pourquoi il est important de savoir utiliser la documentation pour trouver ces rĂ©ponses :

DĂ©couvrir la documentation de Pygame...

AprĂšs avoir dĂ©couvert commenter tracer un cercle dans la documentation, ajouter la ligne de code encadrĂ©e au fichier prĂ©cĂ©dent pong0.py, comme indiquĂ© ci-dessous : #importation de la librairie pygame import pygame #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = pygame.display.set_mode([500,500]) #remplissage du fond par la couleur dĂ©finie screen.fill([255,255,255]) # dessin d'un cercle avec les arguments suivant : # screen : nom de la fenĂȘtre # [255,0,0] : couleur rouge # [50,60] : position du centre x=50 et y=60 # 20 : rayon du cercle # 0 : Ă©paisseur du contour (0 pour aucun contour) pygame.draw.circle(screen, [255,0,0] , [50,60], 20, 0) #activer le rendu graphique (sans lequel rien n'est affichĂ©) pygame.display.flip() code source : pong0.py Modifier la couleur de la balle. Modifier le rayon de la balle. RĂ©aliser la figure suivante dans un nouveau fichier nommĂ© cible.py:

Indice 1

Tracer 7 disques (un rouge, un blanc), de mĂȘme centre.

Indice 2

Les rayons sont des multiples de 10 pixels.

Indice 3

Commencer par dessiner le plus petit est une mauvaise idée.
code source : cible.py
La librairie Pygame commence à rendre le code compliqué avec ses longues expressions comme pygame.draw.circle() pour tracer un cercle, ou encore pygame.display.flip(). Il est possible de raccourcir ces écritures : On souhaite simplifier le code en raccourcissant les longues instructions Pygame. Pour remplir cet objectif, il faut comprendre comment sont structurées les librairies Python comme Pygame :

L'utilisation de librairies en Python...

En appelant diffĂ©remment nos librairies, simplifier le programme pong prĂ©cĂ©dent comme indiquĂ© ci-dessous : #importation de la librairie pygame import pygame from pygame.draw import * from pygame.display import * #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode([500,500]) #remplissage du fond par la couleur dĂ©finie screen.fill([255,255,255]) # dessin d'un cercle avec les arguments suivant : # screen : nom de la fenĂȘtre # [255,0,0] : couleur rouge # [50,60] : position du centre x=50 et y=60 # 20 : rayon du cercle # 0 : Ă©paisseur du contour (0 pour aucun contour) circle(screen, [255,0,0] , [50,60], 20, 0) #activer le rendu graphique (sans lequel rien n'est affichĂ©) flip() code source : pong0.1.py
La fenĂȘtre de dessin semble toujours avoir du mal Ă  se fermer. Dans la partir suivante, nous rĂ©glons ce problĂšme. Nous souhaitons quitter le jeu en cliquant sur la croix de la fenĂȘtre gĂ©nĂ©rer d'erreur. Pour quitter le programme sans bug, il faut :
  • Fermer en premier la fenĂȘtre d'affichage avec pygame.display.quit()
  • Quitter le programme avec sys.exit() provenant du module sys
Attention ! Si on ajoute ces deux lignes de code Ă  notre programme, la fenĂȘtre s'ouvre et se ferme aussitĂŽt. Il faut donc ajouter une temporisation de quelques secondes. On utilisera pour ça la fonction delay() de la librairie time. Modifiez le programme comme indiquĂ© ci-dessous afin que la fenĂȘtre se ferme au bout de deux secondes d'affichage : #importation des librairies pygame et sys import pygame,sys from pygame.draw import * from pygame.display import * #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode([500,500]) #remplissage du fond par la couleur dĂ©finie screen.fill([255,255,255]) # dessin d'un cercle avec les arguments suivant : # screen : nom de la fenĂȘtre # [255,0,0] : couleur rouge # [50,60] : position du centre x=50 et y=60 # 20 : rayon du cercle # 0 : Ă©paisseur du contour (0 pour aucun contour) circle(screen, [255,0,0] , [50,60], 20, 0) #activer le rendu graphique (sans lequel rien n'est affichĂ©) flip() pygame.time.delay(2000)#attendre deux secondes pygame.display.quit()#fermer la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong0.2.py
L'objectif ici est de mettre en place le mouvement en pouvant faire varier les attributs de la balle (position, vitesse, couleur, etc.). Commençons par détailler les attributs naturels de la balle : on considÚre qu'à l'instant $t$, la balle est à la position $(x,y)$ dans un repÚre orthogonal $(O;I;J)$. A la frame suivante, à l'instant $t+dt$, sa nouvelle position est $(x+dx;y+dy)$. La balle est caractérisée par :
  • Sa position $(x,y)$
  • Son dĂ©placement $(dx,dy)$
  • Sa couleur $(r,g,b)$
  • Sa forme, qu'on considĂšrera ici comme circulaire.
La balle est également caractérisée par des actions : La balle réalisera les actions suivantes :
  • Afficher : Cela paraĂźt trivial, mais il est tout d’abord nĂ©cessaire de dessiner la balle pour qu’elle apparaisse sur la fenĂȘtre d’affichage. Il faut alors un cercle de rayon $r$, Ă  la position $(x,y)$, rempli avec la couleur $c$.
  • Avancer ou bouger : Faire avancer la balle de $dx$ suivant l’axe $x$ et de $dy$ suivant l’axe $y$, entre deux frames consĂ©cutives.
  • Rebondir ou Test de collision : Faire rebondir la balle sur les bords de la fenĂȘtre d’affichage. Par la suite, nous ferons Ă©voluer cette action en permettant la collision avec une raquette. Nous pourrons aussi rajouter du son Ă  chaque collision.
On peut aussi dĂ©finir un vecteur position $\vec{p} = \left(\begin{array}{c} x \\y \end{array}\right)$ ainsi qu’un vecteur dĂ©placement $\vec{d} = \left(\begin{array}{c} dx \\dy \end{array}\right)$. On considĂšre dans un premier temps deux paramĂštres au lieu d’un vecteur. Attention, dans les reprĂ©sentations d'images numĂ©riques et les logiciels de traitement d'image, l'axe des ordonnĂ©es est orientĂ© vers le bas.
Pour représenter informatiquement les attributs naturels de la balle, nous avons besoin pour les représenter de maniÚre informatique d'introduire les notions de variables et de types :

Les différents types de variables que l'on peut rencontrer en programmation.

Les variables caractérisant notre balles seront celles-ci :
Attributs de la balle Nom de la variable Type de la variable
Couleur c Liste de 3 entiers int
Rayon r int
Position (abscisse) x int
Position (ordonnée) y int
DĂ©placement (abscisse) dx int
Déplacement (ordonnée) dy int
Forme cercle (pour l'instant cette variable ne changera pas) ---
Ces variables sont dĂ©clarĂ©es en dĂ©but de programme, et utilisĂ©es par la suite dans toute le programme. C'est ce qu'on qualifie de variable globale.Les variables globales sont gĂ©nĂ©ralement Ă  Ă©viter dans des projets plus complexes. D'autres solutions sont prĂ©fĂ©rables, notamment les attributs d'une classe en programmation orientĂ©e objet. Modifier le code comme indiquĂ© ci-dessous afin d'utiliser des variables pour dĂ©finir les attributs de la balle : Le code est le suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales #############################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [2, 1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) #remplissage du fond par la couleur dĂ©finie screen.fill(couleurFond) # dessin d'un cercle : # 0 : dernier paramĂštre - Ă©paisseur du contour (0 pour aucun contour) circle(screen, couleurBalle , [x,y], r, 0) # voir documentation : https://www.pygame.org/docs/ref/draw.html #activer le rendu graphique (sans lequel rien n'est affichĂ©) flip() pygame.time.delay(2000)#attend deux secondes pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong0.3.py
L'objectif est maintenant de faire avancer la balle. Il va donc falloir simuler le mouvement par la sucession rapide de plusieurs images à la maniÚre d'un film. Une fréquence de rafraßchissement de 30 images par seconde donne un rendu suffisamment fluide.

Actuellement, l'image est tracĂ©e une seule fois. Il va falloir utiliser une boucle infinie modifiant le contenu de la fenĂȘtre d'affichage 30 fois par seconde. CelĂ  signifie que chaque itĂ©ration de la boucle doit durer $\frac{1}{30}$-Ăšme de seconde.

Cette boucle de jeu sera créee à l'aide d'une boucle "While" qui vous est présentée ici : Présentation de la boucle while permettant de répéter des instructions de maniÚre répétée...

Pour commencer, nous souhaitons mettre la balle en mouvement comme ceci : Entre chaque frame la balle doit se dĂ©placer de dx suivant l’axe x et dy suivant l’axe y. Il faut donc rajouter dans la boucle infinie les instructions suivantes : x = x+dx y = y+dy Pour donner l'illusion du mouvement, modifiez le programme comme indiquĂ© ci-dessous afin de :
  1. Mettre en place la boucle infinie
  2. Afficher la balle à chaque itération
  3. DĂ©placer la balle
  4. Attendre 15 ms ($\simeq 60$ fpsfps = "frames per second" ou "images par seconde" dans la langue de Jul)
  5. RafraĂźchir le contenu de la fenĂȘtre
  6. Test d'arrĂȘt pour sortir de la boucle et fermer Pygame
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [2, 1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) #remplissage du fond par la couleur blanche screen.fill(couleurFond) while True: #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.0.py

Normalement, le résultat est le suivant :

Nous remarquons que la balle laisse la trace de toutes les positions successive au cours du mouvement. Pour effacer les traces, il faut redessiner la couleur du fond à chaque début de boucle avant d'afficher la balle. Ajouter une instruction permettant d'"effacer" la trace laissée derriÚre la balle.

Indice 1

Une fois par itĂ©ration, il faut "repeindre toute la fenĂȘtre en rouge avant de tracer la balle"

Indice 2

Afin de colorier la fenĂȘtre on ajoute l'instruction au bon endroit : screen.fill(couleurFond)
Ce qui donne le code suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [2, 1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.1.py Il existe des opĂ©rateurs d’assignation qui permettent de simplifier l’écriture x = x+dx et y=y+dy. Ils se rĂ©sument dans le tableau suivant :
Attribution Ă  $x$ d'une valeur $a$ Ajouter $a$ Ă  une variable $x$ Retirer $a$ Ă  une variable $x$ Multiplier une variable $x$ par $a$ Diviser une variable $x$ par $a$
x=a x+=a x-=a x*=a x/=a
La partie « faire avancer la balle » du code précédent peut se remplacer par : #déplacement de la balle : x+=dx y+=dy
La balle ne rebondit pas encore sur les bords. C’est l’objet de cette partie. On souhaite simuler le rebond sur bord droit comme ceci : L'objectif est de trouver une maniĂšre de dĂ©tecter lorsque la balle heurte le bord de l'Ă©cran afin de lui faire changer de sens horizontalement.

Convention de déplacement suivant $x$

D’aprùs l’orientation des axes (voir partie III-1) :
  • si la balle se dĂ©place de gauche Ă  droite, alors dx est positif
  • si la balle se dĂ©place de droite Ă  gauche, alors dx est nĂ©gatif

Condition de rebond

L'algorithme est le suivant : si (la balle touche le bord) alors le sens de dĂ©placement change de signe (sens opposĂ©) fin si MathĂ©matiquement, le changement de signe de dx revient Ă  multiplier cette valeur par -1. On Ă©crit : dx ← dx * (-1) En python, on peut l'Ă©crire de diffĂ©rentes maniĂšres :
dx = dx * (-1) dx *= (-1) dx = -dx
Il reste à trouver à quel moment la balle touche le bord, ou quand elle est sur le point de le dépasser :
  • Ă  la frame d’avant la collision (instant $t_{n-1}$), le bord droit de la balle (point $M_{n-1}$) se situe Ă  une distance $a$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq a \lt dx$
  • et Ă  l’instant d’aprĂšs la collision(instant $t_n$), le bord droit de la balle (point $M_n$) se situe Ă  une distance $b$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq b \lt dx$.
Ce qui est rĂ©sumĂ© par l'image suivante : Dans la figure prĂ©cĂ©dente, on remarque qu’à l’instant $t_n$, lors de la collision, le point $M_n$ d’abscisses $x+r$ dĂ©passe le bord droit de la fenĂȘtre d’affichage d'abscisse $x=width$.

On considÚre que la balle entre en collision avec le bord lorsque la condition suivante est vérifiée : $$x+r >width$$

Algorithme de la collision sur le bord vertical droit de la fenĂȘtre d’affichage

L’algorithme de collision sur le bord droit est donc le suivant : si la condition (x+r >width) est vraie alors dx ← -dx fin si On modifie la boucle infinie pour introduire la condition de rebond Ă  droite : Modifier le programme prĂ©cĂ©dent afin d'ajouter le rebond Ă  droite comme indiquĂ© ci-dessous : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bords droit if x+r > width: dx=-dx flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.2.py
On souhaite ajouter le rebond sur le bord gauche : En s'inspirant de la partie précédente, détecter et réaliser le rebond sur le bord vertical gauche.

Condition de rebond

Comme pour la collision sur le bord droit :
  • Ă  la frame d’avant la collision (instant $t_{n-1}$), le bord gauche de la balle (point $N_{n-1}$) se situe Ă  une distance $a$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq a \lt dx$,
  • et Ă  l’instant d’aprĂšs la collision (instant $t_n$), le bord gauche de la balle (point $N_n$) se situe Ă  une distance $b$ du bord de la fenĂȘtre d’affichage, telle que $0 \leq b \lt dx$.
Dans la figure suivante, on remarque qu’à l’instant $t_n$, lors de la collision, le point $N_n$ d’abscisses $x-r$ dĂ©passe le bord droit de la fenĂȘtre d’affichage reprĂ©sentĂ© par la droite d’équation $x=width$.

On considÚre que la balle entre en collision avec le bord lorsque la condition suivante est vérifiée : $$(x-r \lt 0)$$

Algorithme de la collision sur le bord vertical droit de la fenĂȘtre d’affichage

L’algorithme de collision sur le bord droit est donc le suivant : si la condition (x-r < 0) est vraie alors dx ← -dx fin si On modifie la boucle infinie pour introduire la condition de rebond Ă  gauche : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bord droit if x+r > width: dx=-d #test de collision bord gauche if x-r < 0: dx=-dx flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme

code source : pong1.3.py

Si l'une des condition x+r > width OU x-r < 0 est remplie, elle rĂ©alisera la mĂȘme instruction dx = -dx. On peut regrouper ces deux conditions en un seul test : si (x+r > width) OU (x-r < 0) alors dx ← -dx fin si Ce qui peut ĂȘtre traduit de la maniĂšre suivante en python : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bords droite et gauche if (x+r > width) or (x-r < 0): dx=-dx flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.4.py
On souhaite ajouter les rebonds sur les bords du haut et du bas : En s'inspirant des deux parties prĂ©cĂ©dentes, proposer une modification du code afin de rĂ©aliser les rebonds sur les bords horizontaux. Tout le raisonnement effectuĂ© pour la collision sur les bords verticaux se transpose intĂ©gralement par analogie sur les bords horizontaux. Dans les deux lignes de code correspondant Ă  l’action « Test de collision suivant x », il suffit d’effectuer les changements de variable suivants : $$ \begin{array}{ccc} \text{Axe } x & & \text{Axe }y\\ \hline x & \leftrightarrow & y \\ dx & \leftrightarrow & dy \\ width & \leftrightarrow & height \end{array} $$ Le code Python est le suivant : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=x+dx y=y+dy #test de collision bords droite et gauche if (x+r > width) or (x-r < 0): dx=-dx #test de collision bords haut et bas if (y+r > height) or (y-r < 0): dy=-dy flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong1.5.py Lors des diffĂ©rents tests conditionnels, nous avons introduits un certain nombre d’opĂ©rateurs de comparaison (relationnels) qui peuvent se rĂ©sumer dans le tableau suivant :
supérieur inférieur supérieur ou égal inférieur ou égal égalité
> < >= <= ==
Nous avons introduit aussi un certain nombre d’opĂ©rateurs arithmĂ©tique :
addition soustraction multiplication division modulo (reste de la division euclidienne)
+ - * / %
Enfin nous avons introduits des opĂ©rateurs d’assignation :
Attribution Ă  $x$ d'une valeur $a$ Ajouter $a$ Ă  une variable $x$ Retirer $a$ Ă  une variable $x$ Multiplier une variable $x$ par $a$ Diviser une variable $x$ par $a$
x=a x+=a x-=a x*=a x/=a
Proposer une modification du code précédent pour que :
  • la balle ne rebondisse plus
  • mais qu'elle soit "tĂ©lĂ©portĂ©e" sur le bord opposĂ© (comme pour pacman)

Indice 1

Effacer la partie sur les rebonds

Indice 2

Utiliser l'opérateur modulo %

Indice 3

x "modulo" width
y "modulo" height
L'animation voulue est celle-ci : Le code Python est le suivant : while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : circle(screen, couleurBalle , [x,y], r, 0)# dessin d'un cercle : #dĂ©placement de la balle : x=(x+dx)%width y=(y+dy)%height flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong-teleportation.py

On souhaite maintenant ajouter des balles au jeu. Chaque balle doit avoir 5 attributs (positions [x,y], vitesses [dx, dy], rayon r). Actuellement, Si on veut afficher 10 balles, cela revient Ă  manipuler 5*10 = 50 variables diffĂ©rentes. De mĂȘme, chaque balle doit avoir des actions propres (afficher, avancer, test de collision) qu'il faudrait dupliquer.

Une mĂ©thode grossiĂšre consiste Ă  copier chaque partie du code rĂ©alisĂ© pour la premiĂšre balle et Ă  l’adapter pour chaque balle. Cela conduirait Ă  un code trĂšs long, rĂ©pĂ©titif et fastidieux Ă  lire.

Une des solutions pour remédier à ce problÚme est :
  • l’utilisation de « fonctions d’action » gĂ©nĂ©riques et rĂ©utilisables pour chaque balle
  • L'utilisation de listes de variables qui regroupent les attributs de toutes les balles en un seul objet.
  • l'utilisation d'une boucle « for » qui permet d’effectuer de maniĂšre itĂ©rative les mĂȘmes tĂąches rĂ©pĂ©titives pour chaque balle.
Nous introduisons dans un premier temps la notion de fonctionpour la balle unique crĂ©Ă©e dans la partie prĂ©cĂ©dente. Nous introduisons ensuite la notion de liste et de boucle for pour gĂ©rer les balles multiples. Lorsque la balle Ă©volue dans la fenĂȘtre d’affichage, pour chaque itĂ©ration de la boucle while, on peut rĂ©sumer notre programme par les actions Ă©lĂ©mentaires suivantes : Pour chaque itĂ©ration de la boucle : Afficher la balle Avancer Tester la collision Fin pour

Il suffit pour cela d’incorporer les diffĂ©rentes lignes de codes Ă©crites pour chaque actions dans la boucle while dans des fonctions indĂ©pendantes qui peuvent ĂȘtre appelĂ©es Ă  n’importe quel instant.

De maniĂšre gĂ©nĂ©rale, une fonction peut avoir des paramĂštres en entrĂ©e et renvoyer des paramĂštres en sortie. Dans le cas prĂ©sent, dans le cas d’une balle unique, on pourra dĂ©finir les fonctions suivantes :
  • afficher() : permet de dessiner la balle
  • avancer() : permet de faire avancer la balle
  • testCollision() : teste la collision sur les bords
A priori, aucune de ces méthodes ne prend de paramÚtre en entrée et ne renvoie de paramÚtre en sortie. Nous avons déjà utilisé quelques fonctions prédéfinies, issues de la libraire Pygame comme :
  • fill(color) : donne une couleur color au fond
  • circle(screen, couleurBalle , [x,y], r, 0) : dessine un cercle sur l'Ă©cran Ă  une position donnĂ©e, une couleur et un rayon.
  • etc.
Nous allons maintenant créer nos propres fonctions.
Les trois fonctions doivent ĂȘtre dĂ©clarĂ©es avant leur exĂ©cution (donc au dessus de la boucle while). Par exemple, pour la fonction afficher(), nous procĂ©dons de la maniĂšre suivante :
  • On dĂ©finit la mĂ©thode afficher() avec le mot clĂ© def
  • On dĂ©place les lignes de codes correspondant Ă  la partie « affichage de la balle », Ă  l’intĂ©rieur des accolades d’encapsulation de la fonction afficher().
On procĂšde de la mĂȘme maniĂšre pour les deux autres comme ceci : Le code est le suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [3,1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0,10]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle # Nos fonctions d'actions def afficher(): circle(screen, couleurBalle , [x,y], r, 0) def avancer(): x=x+dx y=y+dy def testCollision(): #bords verticaux if x+r > width or x-r < 0: dx=-dx #bords horizontaux if y+r > height or y-r < 0: dy=-dy #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher() #dĂ©placement de la balle : avancer() #test de collision testCollision() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme code source : pong0=1.6.1.py Si vous avez exĂ©cutĂ© le programme prĂ©cĂ©dent avec les trois nouvelles fonctions, vous avez rencontrĂ© l'erreur suivante :
UnboundLocalError: local variable 'x' referenced before assignment

C'est normal ! CelĂ  signifie que la variable x est inconnue dans la fonction afficher().

En effet, les variables utilisĂ©es dans chaque fonction ont par dĂ©faut une portĂ©e locale. CelĂ  signifie qu'elle doivent ĂȘtre dĂ©clarĂ©e et utilisĂ©e Ă  l'intĂ©rieur de la fonction. Elle n'existent pas en dehors de cette fonction.

Si une variable, dĂ©clarĂ©e a l'extĂ©rieur, doit ĂȘtre utilisĂ©e et modifiĂ©e Ă  l'intĂ©rieur de la fonction il est nĂ©cessaire de la dĂ©clarĂ©e comme variable globale en dĂ©but de fonction comme ceci :

global x,y,dx,dy

Il suffit d'ajouter une ligne au début de chaque fonction pour que le programme fonctionne : # Nos fonctions d'actions def afficher(): global x,y,couleurBalle,r circle(screen, couleurBalle , [x,y], r, 0) def avancer(): global x,y,dx,dy x=x+dx y=y+dy def testCollision(): global x,y,width,height,r,dx,dy #bords verticaux if x+r > width or x-r < 0: dx=-dx #bords horizontaux if y+r > height or y-r < 0: dy=-dy code source : pong0=1.6.2.py
CrĂ©er une fonction testEvenement() qui s'occupe de la dĂ©tection des Ă©vĂšnements clavier/souris et qui gĂšre l'arrĂȘt du jeu et la fermeture de la fenĂȘtre.

Indice 1

Il s'agit de la partie du code qui commence par : for event in pygame.event.get():

Indice 2

Déclarer une fonction testEvenement() et y copier le code précédent

Indice 3

Ne pas oublier d'appeler la fonction dans la boucle while
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage #attributs de la balle [dx,dy] = [3,1]#vecteur de dĂ©placement entre deux frames consĂ©cutives couleurFond = [255, 0, 0,10]#rouge couleurBalle= [0,0,255]#bleu [x,y]=[100,100] # position initiale de la balle r=20 #rayon de la balle # Nos fonctions d'actions def afficher(): circle(screen, couleurBalle , [x,y], r, 0) def avancer(): x=x+dx y=y+dy def testCollision(): #bords verticaux if x+r > width or x-r < 0: dx=-dx #bords horizontaux if y+r > height or y-r < 0: dy=-dy def testEvenement(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher() #dĂ©placement de la balle : avancer() #test de collision testCollision() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test d'arrĂȘt du jeu testEvenement() code source : pong0=1.6.3.py
Nous allons maintenant faire Ă©voluer le programme de sorte qu’il puisse gĂ©rer un nombre N de balles. Pour cela, il est nĂ©cessaire d’introduite la notion de listes. Nous allons tout d’abord crĂ©er, puis manipuler 3 balles dont la gestion sera effectuĂ©e par l’utilisation de listes. Nous crĂ©erons ensuite un grand nombre de balles et introduiront la boucle itĂ©rative « for » pour pouvoir les manipuler. Comme nous l’avons vu prĂ©cĂ©demment, chaque balle dispose de 6 attributs qui la caractĂ©risent de maniĂšre unique. Si on dĂ©cide de faire Ă©voluer N=10 balles, cela revient Ă  manipuler 6*10 = 60 variables diffĂ©rentes, ce qui est trĂšs lourd.

La solution est de dĂ©finir une liste de valeurs pour chaque attribut de la balle. Si nous manipulons N balles, chaque liste comportera N valeurs de mĂȘme type. Chaque liste est alors considĂ©rĂ© comme une variable unique qui permet de manipuler N valeurs.

Quel que soit le nombre N de balles, l’utilisation des listes permet alors de ne manipuler que 6 variables correspondant à chaque attribut d’une balle.

Pour découvrir les listes, nous allons utiliser la console de l'IDE :

Dans la console, crĂ©er une liste L de 3 valeurs (qui pourrait reprĂ©senter une couleur RVB) >>> L = [20,10,15] Reprenons l'exemple prĂ©cĂ©dent (L Ă©tant toujours en mĂ©moire dans la console) : Il est possible d'accĂ©der Ă  un Ă©lĂ©ment d'une liste en prĂ©cisant son indice entre crochets []. Taper la commande suivante : >>> L[0] Elle doit renvoyer 20 car le premier Ă©lĂ©ment de la liste est repĂ©rĂ© par l'indice 0 Il est possible de modifier un Ă©lĂ©ment d'une liste avec une simple affectation. Taper la commande suivante : >>> L[0] = "pong is the best game !!" Afficher la liste LElle vaut maintenant ['pong is the best game!!', 10, 15]. Les listes en Python peuvent ĂȘtre composĂ©es d'objets de types diffĂ©rents. Ici L contient une chaĂźne de caractĂšre et deux entiers.
Commande Commentaire
len(L) La fonction len renvoie la longueur de la liste L
L.append(val) ajouter une valeur val aprÚs le dernier élément de la liste
L.insert(i,val) ajouter une valeur val aprÚs le i-Úme élément de la liste
L+=L0 concaténer la liste L0 à la liste L
del(L[i]) retirer le i-Úme élément de la liste L
a=L.pop() retirer le dernier élément de la liste L et le stocke dans a .
L.remove(val) retirer la premiĂšre occurence d'un Ă©lĂ©ment ayant la mĂȘme valeur que val .
L.reverse() renverse l'ordre
L.sort() réordonne les éléments de la liste
val in L renvoie True si un élément de la liste vaut val , False sinon.
val not in L renvoie False si un élément de la liste vaut val , True sinon.
Pour ĂȘtre sĂ»r d'avoir bien compris, on peut s'entraĂźner : Dans la console, utiliser les commandes prĂ©cĂ©dentes pour : Afficher la longueur de L Ajouter la valeur 42 Ă  la fin de la liste Ajouter la valeur 3.141592 en 2Ăšme position de la liste (attention le "premier" est L[0]) Retirer le 3-Ăšme Ă©lĂ©ment de la liste >>> len(L) >>> L.append(42) >>> L.insert(1,3.141592) >>> del(L[2]) ou L.remove(3.141592)
On va initialiser (avec des valeurs quelconques) des listes représentant les différents attributs de la balle :
  • dx : listes des dĂ©placements horizontaux entre deux frames
  • dy : liste des dĂ©placement verticaux entre deux frames
  • x : liste des abscisses des positions
  • y : liste des ordonnĂ©es des positions
  • r : liste des rayons des balles
Pour commencer, on donne la mĂȘme couleur Ă  chaque balle

Initialisation des listes

On donne 3 valeurs quelconques pour chaque attribut : dx = [3,2,5] #vecteur de déplacement entre deux frames consécutives dy = [-1, 1,3] x = [100, 250, 50] y = [30, 400, 100] r = [20, 25, 15]

Modification des fonctions d'action

Il faut préciser à chaque fonction l'indice i de la balle sur laquelle elle s'applique. On ajoute un argument i en entrée de la fonction : def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i]

Appels des fonctions d'action dans la boucle infinie

while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements()

Code final

Le code final est le suivant : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle= [0,0,255]#les balles ont la mĂȘme couleur #balle dx = [3,2,5] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [-1, 1,3] x = [100, 250, 50] y = [30, 400, 100] r = [20, 25, 15] # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements()   code source : pong2.0.py Modifier le code prĂ©cĂ©dent pour donner une couleur diffĂ©rente Ă  chaque balle en utilisant une liste de couleurs.

Indice 1

Vous pouvez déclarer 3 variables couleurBalle1, couleurBalle2 et couleurBalle3

Indice 2

Regrouper les 3 variables de couleurs dans une liste couleurBalle (une liste contenant des listes !)

Indice 3

Dans la fonction afficher(i), utiliser la bonne couleur couleurBalle1[i]
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge #balle dx = [3,2,5] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [-1, 1,3] x = [100, 250, 50] y = [30, 400, 100] r = [20, 25, 15] #tableau de couleur couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur couleurBalle2= [255,0,255]#les balles ont la mĂȘme couleur couleurBalle3= [255,255,255]#les balles ont la mĂȘme couleur couleurBalle = [couleurBalle1,couleurBalle2,couleurBalle3] # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.1.py
Nous souhaitons pouvoir afficher un nombre quelconque de balles. On propose une méthode plus générale pour déclarer les listes qui s'adaptera beaucoup mieux à la gestion d'un grand nombre de balles.
  • On dĂ©clare une liste vide
  • On ajoute chaque Ă©lĂ©ment de la liste l'un aprĂšs l'autre avec la mĂ©thode append vue prĂ©cĂ©demment
Cela permettra de plus d'ajouter ou de retirer des balles pendant le jeu.
Appliquer la méthode générale pour modifier dans le code précédent la déclaration des listes dx, dy, x, y et r.

Indice 1

Affection d'une liste vide : dx=[]

Indice 2

Ajouter un élément à la liste : dx.append(valeur)

Indice 3

Ajouter un autre élément à la liste : dx.append(nouvelleValeur)
# déclaration des listes vides des attributs des balles dx = [] #vecteur de déplacement entre deux frames consécutives dy = [] x = [] y = [] r = [] #initialisation des listes dx.append(3) dx.append(2) dx.append(5) dy.append(-1) dy.append(1) dy.append(3) x.append(100) x.append(250) x.append(50) y.append(100) y.append(400) y.append(100) r.append(20) r.append(25) r.append(15) code source : pong2.2.py Cette méthode semble pour l'instant plus longue que la précédente, mais s'adaptera parfaitement à un nombre de balles plus important.
En prévision d'un nombre de balles important, on souhaite ne pas avoir à gérer les valeurs de tous les attributs à la main. Nous proposons de les générer aléatoirement. Nous proposons de faire appel à la librairie python randomrandom signifie aléatoire en anglais On va tirer au hasard des nombres entiers. Pour cela on n'aura besoin que de la fonction randint() de la librairie random. On l'importe de la maniÚre suivante : from random import randint Pour tirer un nombre au hasard entre valMin et valMax (compris), on utilise : randint(valMin, valMax) Appliquer cette méthode pour donner des valeurs aléatoires aux éléments des listes dx, dy, x, y, r ET couleurBalle

Indice 1

Définir des variables rMin, rMax, dxMin, dxMax, dyMin, dyMax permettant de borner les valeurs aléatoires.

Indice 2

Les balles peuvent se dĂ©placer vers la gauche... dxMin doit ĂȘtre nĂ©gatif.

Indice 3

dx.append(randint(dxMin,dxMax))

Indice 4

Attention à ne pas créer une balle qui sort du cadre : x.append(randint(rmax,width-rmax))

Indice 5

Les valeurs RVB des couleurs sont comprises entre 0 et 255
#importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur dxMin=-5 dxMax=5 dyMin=-5 dyMax=5 rmax = 40 rmin = 10 # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] #initialisation des listes dx.append(randint(dxMin,dxMax)) dx.append(randint(dxMin,dxMax)) dx.append(randint(dxMin,dxMax)) dy.append(randint(dyMin,dyMax)) dy.append(randint(dyMin,dyMax)) dy.append(randint(dyMin,dyMax)) x.append(randint(rmax,width-rmax)) x.append(randint(rmax,width-rmax)) x.append(randint(rmax,width-rmax)) y.append(randint(rmax,height-rmax)) y.append(randint(rmax,height-rmax)) y.append(randint(rmax,height-rmax)) r.append(randint(rmin,rmax)) r.append(randint(rmin,rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle1= [0,0,randint(0,255)] couleurBalle2= [0,0,randint(0,255)] couleurBalle3= [0,0,randint(0,255)] couleurBalle = [couleurBalle1,couleurBalle2,couleurBalle3] # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) #afficher la balle : afficher(0) afficher(1) afficher(2) #dĂ©placement de la balle : avancer(0) avancer(1) avancer(2) #test de collision testCollision(0) testCollision(1) testCollision(2) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.3.py
La boucle itĂ©rative « for » permets l’exĂ©cution d’un bloc d’instructions un certain nombre de fois, en faisant gĂ©nĂ©ralement varier un indice entre une valeur initiale et une valeur finale avec un pas d’incrĂ©mentation. Lorsque le nombre N de balle est grand, il ne sera trĂšs fastidieux dĂ©clarer et d'initialiser "Ă  la main" chacun des 6 paramĂštres de chaque balle. En effet, supposons que nous crĂ©ons 30 balles, le nombre de paramĂštres Ă  initialiser est 30*6=180. La solution est d'utiliser une boucle itĂ©rative for qui permet l’exĂ©cution d’un bloc d’instructions un certain nombre de fois, en faisant gĂ©nĂ©ralement varier un indice entre une valeur initiale et une valeur finale avec un pas d’incrĂ©mentation for i in range(0,5): print("l'indice vaut : ", i ) Ce code affichera : l'indice vaut : 0 l'indice vaut : 1 l'indice vaut : 2 l'indice vaut : 3 l'indice vaut : 4 L'indice i varie d'une valeur initiale i=0 Ă  une valeur finale i=4 et non 5 !!. Une petite prĂ©cision concernant range() Si on exĂ©cute dans la console list(range(0,5)), on obtient : [0, 1, 2, 3, 4] Cette commande crĂ©e une liste de 5 Ă©lĂ©ments de 0 Ă  4 avec un pas de 1. Tapez dans la console les commandes suivantes pour comprendre le fonctionnement de range. list(range(2,5)) list(range(0,100,10)) list(range(10,0,-1)) Quel est le rĂŽle du troisiĂšme argument ?
  • Le troisiĂšme argument reprĂ©sente le pas d'incrĂ©mentation de la liste
  • La derniĂšre valeur n'est pas atteinte
  • Le pas peut ĂȘtre nĂ©gatif
  • Le pas ne peut ĂȘtre qu'entier
On comprend donc que la boucle for peut itérer sur n'importe quelle liste : L=["Marseille","New York","Alger","Tokyo","Dakar"] for ville in L: print("J'adore la ville de ", ville ) Ce code affichera : J'adore la ville de Marseille J'adore la ville de New York J'adore la ville de Alger J'adore la ville de Tokyo J'adore la ville de Dakar
Il est maintenant possible d’appliquer la boucle « for » pour simplifier l’écriture des taches itĂ©ratives :
  • Pour l’initialisation des diffĂ©rents tableaux dans le setup() : d, x, y, dx, dy, c.
  • Pour l’appel aux diffĂ©rentes mĂ©thodes appliquĂ©es Ă  chaque balle : affiche(i), avancer(i) et testCollision(i).
Modifier le code du pong prĂ©cĂ©dent pour gĂ©rer les instruction rĂ©pĂ©titives Ă©crites Ă  la main Ă  l'aide de boucles for. #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #initialisation des listes for i in range(0,3): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,3): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.4.py L'intĂ©rĂȘt des boucles for est que maintenant, la structure du programme pour afficher 1, 3, 10 ou 30 balles est la mĂȘme. Introduire une nouvelle variable globale N qui reprĂ©sente le nombre de balles. Modifier le code prĂ©cĂ©dent pour afficher N balles. Testez diffĂ©rentes valeurs. #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong2.5.py
La raquette est positionnée à gauche par convention. Son abscisse est donc fixe, et son ordonnée sera commandée par des interaction clavier. On ajoute donc plusieurs variables pour représenter la raquette :
  • rx = 20 : abscisse de la raquette
  • ry = height/2 : ordonnĂ©e de la raquette (positionnĂ©e au milieu initialement mais qui variera)
  • dry = 5 : dĂ©placement vertical de la raquette
  • rh = 100 : hauteur de la raquette
  • rw = 20 : largeur de la raquette
  • rcolor = [255, 255, 255] : couleur de la raquette (ici blanc)
Pour reprĂ©senter graphique la raquette, il suffit de dessiner un rectangle. On utilise la methode pygame.draw.rect() qui s'utilise de la maniĂšre suivante : rect(screen, rcolor, [rx, ry, rw, rh]) Afficher une raquette blanche dans la fenĂȘtre du jeu avec les caractĂ©ristiques prĂ©cĂ©dentes On ajoute les variables et une fonction afficher_raquette() : #importation de la librairie pygame import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #dĂ©claration des attributs de la raquette rx=20 ry=height/2 dry=5 rh=100 rw=20 rcolor=[255,255,255] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme #fonctions de la raquette def afficher_raquette(): rect(screen, rcolor, [rx, ry, rw, rh]) #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) afficher_raquette() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong3.0.py
On a besoin d'interagir avec le clavier (flĂšche du haut et flĂšche du bas) pour commander la position de la raquette. On va importer les importer les attributs de pygame au dĂ©but du programme en ajoutant la ligne suivante en entĂȘte du programme : from pygame.locals import * Cela nous permettra de taper KEYDOWN ou QUIT ou K_UP, etc. au lieu de pygame.KEYDOWN ou pygame.QUIT ou pygame.K_UP, etc. L'appui sur une touche est considĂ©rĂ© par pygame comme un nouvel Ă©vĂšnement. Nous avons dĂ©jĂ  crĂ©Ă© la fonction testEvenements() qui gĂšre l'Ă©vĂšnement "quitter la fenĂȘtre de jeu". Si l'Ă©vĂšnement vaut pygame.KEYDOWN, c'est que une touche (n'importe laquelle) a Ă©tĂ© appuyĂ©e. On modifie maintenant la fonction testEvenement() comme ceci : def testEvenements(): for event in pygame.event.get(): if event.type == QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: print("Une touche vient d'ĂȘtre pressĂ©e") Pour l'instant appuyer sur une touche ne produit aucun rĂ©sultat visible sur la raquette, et ne fait qu'afficher un message dans la console. La prochaine Ă©tape est de dĂ©tecter quelle touche a Ă©tĂ© pressĂ©e.
  • La mĂ©thode pygame.key.get_pressed() renvoie une liste reprĂ©sentant l'Ă©tat de chaque touche du clavier : 1 pour appuyĂ©e, 0 pour relĂąchĂ©e.
  • L'indice de la touche "flĂšche du haut" dans le tableau pygame.key.get_pressed() est 273, celui de "flĂšche du bas" est 274
  • Pour ne pas avoir Ă  retenir ces indices, pygame a dĂ©fini des constantes : K_UP vaut 273 et K_DOWN vaut 274.
  • Les noms de toutes les constantes associĂ©es Ă  chaque touche sont disponibles sur le site de pygame.
On donne la fonction bouger_raquette() suivante : def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: #dĂ©placer vers le haut .... if pygame.key.get_pressed()[K_DOWN]: #dĂ©placer vers le bas .... ComplĂ©ter le code de la fonction bouge_raquette() afin de rĂ©aliser le dĂ©placement souhaitĂ©. Appeler cette fonction lorsqu'un Ă©vĂšnement KEYDOWN est dĂ©tectĂ© def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: bouger_raquette() def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: ry-=dry if pygame.key.get_pressed()[K_DOWN]: ry+=dry Vous avez certainement remarquĂ© qu'il faut appuyer plusieurs fois sur les touches bas et haut pour dĂ©placer le raquette. Maintenir une touche appuyĂ©e ne dĂ©clenche qu'un seul Ă©vĂšnement clavier. Pour obliger pygame Ă  vĂ©rifier les Ă©venements claviers toutes les 10ms (par exemple), il faut ajouter la ligne suivante juste aprĂšs avoir initialisĂ© pygame : #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #vĂ©rifier les interactions clavier toutes les 10ms pygame.key.set_repeat(10, 10) On obtient donc le code entier suivant : #importation de la librairie pygame from pygame.locals import * import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #dĂ©claration des attributs de la raquette rx=20 ry=height/2 dry=2 rh=100 rw=20 rcolor=[255,255,255] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] def testEvenements(): for event in pygame.event.get(): if event.type == QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: bouger_raquette() #fonctions de la raquette def afficher_raquette(): rect(screen, rcolor, [rx, ry, rw, rh]) def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: ry-=dry if pygame.key.get_pressed()[K_DOWN]: ry+=dry #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #vĂ©rifier les interactions clavier toutes les 10ms pygame.key.set_repeat(10, 10) #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) afficher_raquette() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong3.1.py
Nous proposons ici de modifier la fonction testCollision(i) qui teste la collision de la ballei avec les bords. Il est nĂ©cessaire de faire un schĂ©ma pour bien comprendre la situation : Pour qu’il y ait collision entre la balle et la raquette, il faut que le point N de la iĂšme balle soit tangent ou traverse lĂ©gĂšrement le bord droit de la raquette. Les conditions suivantes doivent simultanĂ©ment ĂȘtre respectĂ©es :
  • Suivant x : l’abscisse du point N doit ĂȘtre infĂ©rieure Ă  celle du point A et B, soit, $$ x – r \lt rx + rw $$
  • Suivant y : l’ordonnĂ©e du point N doit ĂȘtre comprise entre l’ordonnĂ©e du point A et l’ordonnĂ©e du point B, soit, $$ ry \lt y \lt ry + rh . $$
Algorithmiquement, il faut donc que la condition $ry \lt y$ et que la condition $ y \lt ry + rh$ et que la condition $x – r \lt rx+rw$ soient vĂ©rifiĂ©es simultanĂ©ment. En programmation Python, le « et logique » s’écrit and. Pour la i-Ăšme balle, cette condition logique s'Ă©crit donc : (ry < y[i]) and (y[i] < (ry + rh)) and ((x[i] – r[i]) < (rx+rw)) Modifier la fonction testCollision pour que le bord droit de la raquette se comporte comporte comme le bord droit de l'Ă©cran et fasse rebondir la balle. def testCollision(i): global x,y,width,height,r,dx,dy,ry,rh,rw #bords verticaux if x[i]+r[i] > width or x[i]-r[i] < 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] #rebond raquette : if (ry < y[i]) and (y[i] < (ry + rh)) and ((x[i] - r[i]) < (rx + rw)): dx[i]=-dx[i] Ce qui produit le programme final suivant : #importation de la librairie pygame from pygame.locals import * import pygame,sys from pygame.draw import * from pygame.display import * from random import randint # variables globales ##########################################################" size = width, height = 500, 500 # taille de la fenĂȘtre d'affichage couleurFond = [255, 0, 0,10]#rouge couleurBalle1= [0,0,255]#les balles ont la mĂȘme couleur rmax = 40 rmin = 10 N = 10 #nb de balles # dĂ©claration des listes vides des attributs des balles dx = [] #vecteur de dĂ©placement entre deux frames consĂ©cutives dy = [] x = [] y = [] r = [] couleurBalle = [] #dĂ©claration des attributs de la raquette rx=20 ry=height/2 dry=2 rh=100 rw=20 rcolor=[255,255,255] #initialisation des listes for i in range(0,N): dx.append(randint(-5,5)) dy.append(randint(-5,5)) x.append(randint(width-rmax,height-rmax)) y.append(randint(width-rmax,height-rmax)) r.append(randint(rmin,rmax)) #tableau de couleur (dĂ©gradĂ© de bleu) couleurBalle.append([0,0,randint(0,255)]) # Nos fonctions d'actions def afficher(i): global x,y,couleurBalle,r circle(screen, couleurBalle[i] , [x[i],y[i]], r[i], 0) def avancer(i): global x,y,dx,dy x[i]=x[i]+dx[i] y[i]=y[i]+dy[i] def testCollision(i): global x,y,width,height,r,dx,dy,ry,rh,rw #bords verticaux if x[i]+r[i] > width or x[i]-r[i] 0: dx[i]=-dx[i] #bords horizontaux if y[i]+r[i] > height or y[i]-r[i] < 0: dy[i]=-dy[i] if (ry < y[i]) and (y[i] < (ry + rh)) and ((x[i] - r[i]) < (rx + rw)): dx[i]=-dx[i] def testEvenements(): for event in pygame.event.get(): if event.type == pygame.QUIT:#si clique sur la croix quitter pygame.display.quit()#ferme la fenĂȘtre sys.exit()#arrĂȘte le programme if event.type == KEYDOWN: bouger_raquette() #fonctions de la raquette def afficher_raquette(): rect(screen, rcolor, [rx, ry, rw, rh]) def bouger_raquette(): global ry, dry if pygame.key.get_pressed()[K_UP]: ry-=dry if pygame.key.get_pressed()[K_DOWN]: ry+=dry #lancement des fonctionnalitĂ©s de la librairie pygame pygame.init() #vĂ©rifier les interactions clavier toutes les 10ms pygame.key.set_repeat(10, 10) #affichage d'une fenĂȘtre de dessin de largeur 500 pixels et de hauteur 500 pixels screen = set_mode(size) while True: #remplissage du fond par la couleur blanche screen.fill(couleurFond) for i in range(0,N): #afficher la balle : afficher(i) #dĂ©placement de la balle : avancer(i) #test de collision testCollision(i) afficher_raquette() flip()#activer le rendu graphique pygame.time.delay(15)#une image toute les 15 ms #test evenements, arrĂȘt de jeu : testEvenements() code source : pong3.1.py

Le pong réalisé est ainsi jouable. Il ne s'agit bien sûr pas d'un jeu finalisé. Il nous aura permis d'introduire toutes les notions fondamentales de programmation python ainsi que des morceaux de code réutilisables pour d'autres types de projets.

Il est possible de poursuivre et d'améliorer le jeu :