Introduction à Pygame

Cet article est inspiré d’un document initial de Brice Canvel, c'est une introduction à la bibliothèque Pygame pour les programmeurs Python. C'est une bibliothèque d'extension de Python, enveloppe de la bibliothèque SDL.
  1. Un avant-goût
  2. Vidéos sur la création d’un jeu sous Python à l’aide de Pygame (pour les impatients)
  3. Déplacer une image

Un avant-goût

Le meilleur moyen pour saisir le fonctionnement d'une nouvelle bibliothèque est de directement regarder un exemple parlant. Jetons un coup d'œil à une version simplifiée d'une animation de balle rebondissante.

In [ ]:
import pygame
pygame.init()

size = width, height = 320, 240
speed = [2, 2]
color = 255, 255, 255
screen = pygame.display.set_mode(size)

ball = pygame.image.load("ball.png")
ballrect = ball.get_rect()
game_over = False

while not game_over:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_over = True
        ballrect = ballrect.move(speed)
        if ballrect.left < 0 or ballrect.right > width:
            speed[0] = -speed[0]
        if ballrect.top < 0 or ballrect.bottom > height:
            speed[1] = -speed[1]

        screen.fill(color)
        screen.blit(ball, ballrect)
        pygame.display.flip()
        
pygame.quit()
quit()

Si vous voulez essayer cet exemple, mettez dans le même dossier, une image nommée ball.png

  • C'est la façon la plus simple d'obtenir une animation de balle rebondissante. On voit au début du code l'importation et l'initialisation du module Pygame, ce qui ne change pas vraiment d'un programme à un autre. La ligne $\texttt{import pygame} \, $ importe toutes les modules disponibles de Pygame, c'est la seule obligatoire pour importer tous les modules de Pygame existants. L'instruction $\texttt{from pygame.locals import *}\quad$ est optionnelle et sert à rendre publiques certaines constantes et fonctions de Pygame. L'appel de $\texttt{pygame.init()}$ initialise chacun de ces modules.
  • À la ligne 7, une fenêtre graphique est créée par l'appel de $\texttt{pygame.display.set_mode()}$. Pygame et SDL nous simplifie la vie en sélectionnant par défaut les modes graphiques les plus adaptés au matériel graphique. Pygame représente les images comme des objets Surface. La fonction $\texttt{display.set_mode()}$ crée un nouvel objet Surface représentant le graphisme actuel à afficher. Tous les dessins que vous faites sur cette surface seront visibles à l'écran.
  • À la ligne 10, nous chargeons notre image de balle. Pygame supporte une grande variété de format d'image, comme la bibliothèque SDL_image, les formats pris en compte sont : JPG, PNG, TGA et GIF. La fonction $\texttt{pygame.image.load()}$ nous retourne la surface contenant l'image de balle. La surface gardera toutes les propriétés (couleur clé et/ou de transparence alpha) du fichier d'origine. Après le chargement de l'image de la balle, nous créons une variable ballrect. Pygame possède un objet très utile nommé $\texttt{Rect}$ qui représente une zone rectangulaire. Dans la partie du code chargée de l'animation, nous verrons quel est le rôle des objets $\texttt{Rect}$.
  • À la ligne 13, notre programme est initialisé et prêt à être lancé. À l'intérieur d'une boucle infinie qui gère les évènements générés par l'utilisateur, le code dessine et fait bouger la balle. Si vous êtes familier avec la programmation de $\texttt{GUI}$ (Graphical User Interface, ou Interface Utilisateur Graphique), vous avez certainement une notion de ce que sont les évènements. Avec Pygame, il s'agit de la même chose. Lorsqu'un évènement se produit, le programme l'intercepte et agit en conséquence. Le premier évènement pris en compte est l'action de quitter le programme. Si cet évènement survient, le programme agit en conséquence en appelant la méthode $\texttt{sys.exit()}$.
  • Ensuite vient le traitement de l'actualisation de la position de la balle. Les lignes 17 et 21 déplace la variable ballrect par sa vitesse courante. Si la balle s'est déplacée à l'extérieur de l'écran, la vitesse de la balle est inversée pour qu'elle reparte dans l'autre sens. Ça ne correspond pas exactement aux lois de Newton, mais ce n'était pas l'objectif de ce premier programme de toute façon.
  • À la ligne 23, nous effaçons l'écran en le remplissant de la couleur color. Si vous n'avez jamais travaillé avec des animations, ceci peut vous paraître étrange. Vous pouvez vous demander : Pourquoi avons-nous besoin de tout effacer ? Pourquoi n'avons-nous pas juste la balle à bouger sur l'écran ?, ceci n'est pas vraiment la manière de fonctionner des animations sur ordinateur. Une animation n'est rien de plus qu'une succession d'images, mais cette succession des images est tellement rapide que le cerveau humain voit une animation. screen n'est qu'une image que l'utilisateur voit. Si vous n'avez pas pris le temps d'effacer la balle de l'écran, nous pourrions voir la trace de la balle tout en continuant de voir la balle dans ses nouvelles positions.
  • À la ligne 24, nous dessinons l'image de la balle sur l'écran. Le dessin de ces images est géré par la méthode $\texttt{Surface.blit()}$. Un blit signifie que l'on copie les couleurs de chaque pixel d'une image sur une autre. Avec la méthode $\texttt{blit()}$, on prend une surface dite source que l'on applique sur la surface destination, le tout à une position définie.
  • La dernière chose dont nous avons besoin, est la mise à jour de l'affichage visible. Pygame gère l'affichage avec un double tampon (double buffer). Quand nous avons fini de dessiner, nous faisons appel à la fonction $\texttt{pygame.display.flip()}$. Ceci fait que tout ce que nous avons dessiné sur la Surface screen devient visible. Cette mise en tampon fait que nous sommes sûr de voir des images complètes dessinée à l'écran. Sans cette manipulation par tampon, l'utilisateur verrait l'image se dessiner au fur et à mesure sur son écran.
  • Les modules ont généralement une fonction $\texttt{quit()}$ pour quitter en libérant la mémoire.

Vous allez être surpris en visitant le site internet de Pygame en voyant ce que les autres utilisateurs sont capables de faire avec Python.

Lorsque vous comprenez Python, vous pourrez utiliser Pygame pour créer un simple jeu en une ou deux semaines. Mais pour avoir un jeu complètement présentable, il vous faudra de nombreuses heures de travail.

Vidéos sur la création d’un jeu sous Python à l’aide de Pygame

Pour télécharger le dossier ressources cliquer ici : Téléchargez le fichier. Téléchargez le fichier source

Première vidéo

In [1]:
from IPython.display import HTML
HTML('<iframe height="360" frameborder="0" width="640" src="http://www.youtube.com/embed/IGSmLvfEz18?feature=oembed"></iframe>')
Out[1]:

Et la deuxième …

In [2]:
from IPython.display import HTML
HTML('<iframe height="480" frameborder="0" width="640" src="http://www.youtube.com/embed/HXe-bq5i3nk?feature=oembed"></iframe>')
Out[2]:

La troisième sur l’implémentation des meilleurs scores et l’utilisation des bases de données

In [3]:
from IPython.display import HTML
HTML('<iframe height="480" frameborder="0" width="640" src="http://www.youtube.com/embed/og31B02dlFs?feature=oembed"></iframe>')
Out[3]:

Déplacer une image

Une introduction aux fonctions basiques de Pygame.

De simples pixels sur l'écran

Pygame possède une Surface d'affichage. C'est typiquement l'image visible à l'écran, et cette image est constituée de pixels. La principale façon de modifier ces pixels est d'appeler la fonction blit() : elle copie les pixels d'une image sur une autre.

C'est la première chose à comprendre. En appelant la fonction $\texttt{blit()}$ d'une image sur l'écran, vous changez simplement la couleur des pixels de l'écran. Les pixels ne sont pas ajoutés ou déplacés, c'est seulement la couleur de certains pixels qui est modifiée. Ces images que vous blitez sur l'écran sont des Surfaces dans Pygame, mais elles ne sont aucunement connectées à la Surface d'affichage. Quand elles sont blitées sur l'écran, elles sont copiées sur la Surface d'affichage, mais vous avez toujours accès à l'image originale.

Avec cette brève description, peut-être pouvez-vous déjà comprendre ce que nécessite l'animation d'une image. En réalité, nous ne déplaçons rien. Nous faisons simplement un blit de l'image dans une nouvelle position. Mais avant de dessiner l'image dans une nouvelle position, il faut effacer l'ancienne. Autrement, l'image serait visible à deux places sur l'écran. En effaçant rapidement l'image et en la redessinant à un nouvel endroit, nous réalisons l'illusion du mouvement.

À travers le reste du tutoriel, nous décomposerons ce processus en étapes simples. Nous verrons également comment animer plusieurs images à l'écran en même temps. Vous avez probablement déjà des questions, par exemple : comment effacer l'image avant de la redessiner dans une nouvelle position ? Peut-être êtes-vous déjà totalement perdu ? Espérons que le reste de ce tutoriel pourra éclaircir certaines choses.

Retournons sur nos pas

Peut-être que ce concept de pixels et d'images est encore un peu étranger à vos yeux ? Bonne nouvelle, durant les prochaines sections nous utiliserons du code pour faire tout ce que nous voulons, il n'utilisera pas de pixels. Nous allons créer une petite liste de 6 nombres en Python, et imaginer qu'elle représente des graphismes fantastiques que nous pourrions visualiser sur l'écran. Et il est surprenant de s'apercevoir à quel point cela correspond à ce que nous ferons plus tard avec des graphismes réels.

Alors commençons par créer notre liste et remplissons-la d'un beau paysage fait de $1$ et de $2$.

In [10]:
screen = [1, 1, 2, 2, 2, 1]
print(screen)
[1, 1, 2, 2, 2, 1]

Nous venons de créer l'arrière-plan. Mais ça ne sera pas franchement excitant tant que nous n'aurons pas dessiné un joueur à l'écran. Nous allons créer un puissant Héros qui ressemblera à un $8$. Déposons-le au milieu de la carte et voyons de quoi il a l'air.

In [11]:
screen[3] = 8
print(screen)
[1, 1, 2, 8, 2, 1]

Maintenant que notre écran n'est qu'une simple liste de nombres, il est plus facile de voir comment les déplacer ?

Déplacement de notre Héros

Avant que nous puissions déplacer notre personnage, nous avons besoin de garder une trace de sa position. Dans la section précédente, quand nous l'avons dessiné, nous l'avons juste posé à une position arbitraire. Faisons-le plus rigoureusement cette fois-ci.

In [12]:
playerpos = 3
screen[playerpos] = 8
print(screen)
[1, 1, 2, 8, 2, 1]

Maintenant il est assez facile de le déplacer vers une nouvelle position. Changeons simplement la valeur de playerpos, et dessinons-le une nouvelle fois à l'écran.

In [13]:
playerpos = playerpos - 1
screen[playerpos] = 8
print(screen)
[1, 1, 8, 8, 2, 1]

Aïe! Maintenant nous pouvons voir 2 héros. Un dans l'ancienne position, et un dans la nouvelle. C'est exactement la raison pour laquelle nous avons besoin d'effacer le héros dans son ancienne position avant de le dessiner sur sa nouvelle position. Pour l'effacer, nous devons changer la valeur dans la liste pour qu'elle soit de nouveau comme avant la présence du héros. Pour ça, nous devons conserver une trace des valeurs de l'affichage avant que notre héros ne les remplace. Il y a plusieurs manières de le faire, mais la plus simple est de garder une copie séparée de l'arrière-plan. Ceci signifie que nous devons faire subir quelques modifications à notre jeu.

Création d'une carte

Ce que nous voulons faire c'est créer une liste séparée que nous appellerons arrière-plan. Nous créerons cet arrière-plan de façon à ce qu'il soit comme notre écran original rempli de $1$ et de $2$. Ensuite nous copierons chaque objet dans l'ordre de d'affichage : de l'arrière-plan vers l'écran. Après, nous pourrons redessiner notre héros sur l'écran.

In [14]:
background = [1, 1, 2, 2, 2, 1]
screen = [0]*6                     #a new blank screen
for i in range(6):
    screen[i] = background[i]
print(screen)
playerpos = 3
screen[playerpos] = 8
print(screen)
[1, 1, 2, 2, 2, 1]
[1, 1, 2, 8, 2, 1]

Cela peut sembler être un surplus de travail. Nous n'en sommes pas plus loin d'où nous étions la dernière fois, lorsque nous avons tenté de le déplacer. Mais cette fois nous avons plus d'information pour pouvoir le déplacer correctement.

Déplacement de notre Héros (2ème essai)

Cette fois ci, il sera plus simple de déplacer le héros. D'abord nous effacerons le héros de son ancienne position. Nous faisons cela en recopiant les bonnes valeurs de l'arrière-plan sur l'écran. Ensuite, nous dessinerons le personnage dans sa nouvelle position sur l'écran.

In [15]:
print(screen)
screen[playerpos] = background[playerpos]
playerpos = playerpos - 1
screen[playerpos] = 8
print(screen)
[1, 1, 2, 8, 2, 1]
[1, 1, 8, 2, 2, 1]

Et voilà. Le héros s'est déplacé d'un pas vers la gauche. Nous pouvons utiliser le même code pour le bouger une nouvelle fois à gauche.

In [16]:
screen[playerpos] = background[playerpos]
playerpos = playerpos - 1
screen[playerpos] = 8
print(screen)
[1, 8, 2, 2, 2, 1]

Excellent! Ce n'est pas exactement ce que l'on pourrait appeler une animation fluide. Mais avec quelques arrangements, nous ferons ce travail directement avec des graphismes sur l'écran.

Définition de blit

Dans la prochaine partie, nous transformerons notre programme qui utilise des listes en un programme qui utilise de vrais graphismes. Pour l'affichage des graphismes, nous utiliserons le terme blit fréquemment. Si vous êtes débutant dans le graphisme, vous êtes probablement peu familier avec ce terme.

**Blit**
À la base, un *blit* signifie copier le graphisme d'une image vers une autre. Une définition plus formelle serait copier un tableau de données source vers un tableau de données destination. Vous pouvez considérer qu'un *blit* n'est qu'une assignation de pixels. Comme définir des valeurs dans notre liste de nombres, *blit* assigne la couleur des pixels dans notre image.

De la liste à l'écran

Utiliser le code que nous avons vu dans les exemples plus haut, et le faire fonctionner avec Pygame est très simple :

  1. Nous supposons que nous avons chargé de jolies images et que nous les avons nommées : terrain1, terrain2 et hero.
  2. Au lieu d'assigné des nombres à une liste, maintenant nous allons bliter des images à l'écran.
  3. Au lieu d'employer des positions en tant que simple index (de 0 à 5), nous aurons besoin de coordonnées à deux dimensions. Nous supposerons également que chaque image de notre jeu aura une largeur de $10$ pixels donc avec des positions multiples de $10$. Cela revient à multiplier les indices par $10$ pour obtenir les coordonnées.
In [ ]:
background = [terrain1, terrain1, terrain2, terrain2, terrain2, terrain1]
screen = create_graphics_screen()
for i in range(6):
    screen.blit(background[i], (i*10, 0))
playerpos = 3
screen.blit(playerimage, (playerpos*10, 0))

Ce code devrait vous sembler très familier, et prendre un peu de sens. La seule partie qui soit un travail supplémentaire est celle qui convertit la position du joueur en coordonnées sur l'écran. Pour l'instant nous utilisons simplement $\texttt{(playerpos*10, 0)}$.

Maintenant déplaçons l'image du joueur dans un autre endroit. Ce code ne devrait pas vous surprendre :

In [ ]:
screen.blit(background[playerpos], (playerpos*10, 0))
playerpos = playerpos - 1
screen.blit(playerimage, (playerpos*10, 0))

Voila! Avec ce code, nous avons vu comment afficher un simple arrière-plan avec l'image du héros dessus. Ensuite nous avons correctement déplacé le héros d'un espace vers la gauche.

Mais c'est encore un peu maladroit. La première chose que nous voudrions faire serait de trouver une manière plus propre de représenter l'arrière-plan et la position du joueur. Et peut être de faire une vraie animation fluide.

Coordonnées écran

Pour positionner un objet sur l'écran, nous avons besoin de la fonction $\texttt{blit()}$ où l'on met l'image. Dans Pygame nous passons toujours nos positions comme des coordonnées $(X,Y)$. $X$ est le nombre de pixels vers la droite et $Y$ le nombre de pixels vers le bas. Le coin supérieur gauche d'une Surface correspond aux coordonnées $(0, 0)$. Un déplacement vers la droite donnerait $(10, 0)$, et ajouter un déplacement vers le bas nous donnerait $(10, 10)$. Quand nous blitons, l'argument passé en position représente le coin supérieur gauche de la source devant être placé sur la destination.

Pygame possède un conteneur intéressant, l'objet $\texttt{Rect}$ qui représente une zone rectangulaire avec ses coordonnées. Il est définit par son coin supérieur gauche et sa dimension. L'objet $\texttt{Rect}$ possède de nombreuses méthodes utiles qui peuvent vous aider à le déplacer et le positionner. Dans notre prochain exemple, nous représenterons les positions de nos objets avec des $\texttt{Rect}$.

Ensuite sachez que beaucoup de fonctions de Pygame utilisent les $\texttt{attributs}$ des objets $\texttt{Rect}$. Toutes ces fonctions peuvent accepter un simple tuple de 4 éléments (position gauche, position dessus, largeur, hauteur). Vous n'êtes pas toujours obligé d'utiliser ces objets $\texttt{Rect}$, mais vous les trouverez utiles. Ainsi, la fonction $\texttt{blit()}$ peut accepter un objet $\texttt{Rect}$ en tant qu'argument de position, elle utilise le coin supérieur gauche du $\texttt{Rect}$ comme position réelle.

Changer l'arrière-plan

Précédemment, nous avons stocké l'arrière-plan comme une liste de différents types de sol. C'est une bonne manière de créer un jeu basé sur des cases, mais nous voulons faire un défilement (scrolling en anglais) fluide. Pour faire simple, nous commencerons par modifier l'arrière-plan en une simple image qui couvre entièrement l'écran. De cette façon, quand nous voudrons effacer nos objets (avant de les redessiner) nous aurons simplement besoin de bliter la section effacée de l'arrière-plan dans l'écran.

En passant un troisième argument optionnel à la fonction $\texttt{blit()}$, nous lui indiquerons de bliter uniquement une sous-section de l'image source. Vous la verrez en action quand nous effacerons l'image du joueur.

Notez également, que lorsque nous aurons fini de tout dessiner, nous invoquerons la fonction $\texttt{pygame.display.update()} \quad$ qui affichera tout ce que nous avons dessiné sur l'écran.

Mouvement fluide

Pour obtenir quelque chose qui apparaisse comme un mouvement fluide, nous déplacerons quelques pixels à la fois. Voici le code pour faire un objet qui se déplace de manière fluide à travers l'écran :

In [ ]:
screen = create_screen()
player = load_player_image()
background = load_background_image()
screen.blit(background, (0, 0))       #draw the background
position = player.get_rect()
screen.blit(player, position)         #draw the player
pygame.display.update()               #and show it all
for x in range(100):                  #animate 100 frames
    screen.blit(background, position, position) #erase
    position = position.move(2, 0)     #move player
    screen.blit(player, position)      #draw new player
    pygame.display.update()            #and show it all
    pygame.time.delay(100)             #stop the program for 1/10 second

Nous pouvons aussi utiliser un joli personnage d'arrière-plan. Un autre avantage sur cette façon de procéder, est que l'image du joueur peut inclure de la transparence ou être découpée en section, elle sera toujours dessinée correctement sur l'arrière-plan.

Nous avons aussi fait appel à la fonction $\texttt{pygame.time.delay()}\quad$ à la fin de notre boucle pour ralentir un peu notre programme, autrement il tournerait tellement vite qu'on aurait pas le temps de le voir.

Et ensuite ?

À ce stade, le code n'est pas encore prêt pour réaliser le prochain jeu le plus vendu. Comment faire pour obtenir simplement de multiple déplacements d'objets ? Que sont réellement ces mystérieuses fonctions comme $\texttt{load_player_image()}$ ? Nous avons également besoin d'une manière simple d'accéder aux entrées de l'utilisateur (clavier, souris ou autre), et boucler sur plus de 100 images.

Les fonctions mystères

Des informations complètes sur ces types de fonctions peuvent être trouvées dans d'autres tutoriaux et références. Le module $\texttt{pygame.image}\quad$ possède une fonction $\texttt{load()}$ qui fera ce que nous voudrons. Les lignes pour charger des images devraient ressembler à ceci :

In [ ]:
player = pygame.image.load('player.bmp').convert()
background = pygame.image.load('liquid.bmp').convert()

La fonction de chargement demande seulement un nom de fichier et retourne une nouvelle surface avec l'image chargée. Après le chargement, nous faisons appel à la méthode de Surface : $\texttt{convert()}\quad$ qui nous retourne une nouvelle Surface contenant l'image, mais convertie dans le même espace colorimétrique que notre affichage. Maintenant que les images ont le même format d'affichage, le blit est très rapide. Si nous ne faisons pas la conversion, la fonction $\texttt{blit()}$ est plus lente, c'est pourquoi il est préférable de faire la conversion de pixels d'un format à un autre au fur et à mesure.

Les deux fonctions, $\texttt{load()}$ et $\texttt{convert()}$, retournent de nouvelles Surfaces. Ceci signifie que nous avons réellement créé deux Surfaces à chacune de ces lignes. Dans d'autres langages de programmation, on obtiendrait une fuite de mémoire (ce n'est clairement pas une bonne chose). Heureusement Python est là pour les gérer, et Pygame effacera proprement la Surface que nous n'utiliserons pas.

Cette autre fonction mystérieuse que nous avons vue dans l'exemple précédent était $\texttt{create_screen()}$. Dans Pygame, c'est simple de créer une nouvelle fenêtre pour les graphismes. Le code pour créer une surface de $640\times480$ pixels est le suivant : (sans passer aucun autre argument, Pygame choisit la meilleure profondeur de couleur et le meilleur espace colorimétrique pour nous)

In [ ]:
screen = pygame.display.set_mode((640, 480))

Manipulation des entrées utilisateur

Nous avons désespérément besoin de modifier la boucle principale pour prendre en compte une entrée utilisateur, comme par exemple, lorsque celui ci ferme la fenêtre. Nous devons ajouter la manipulation d'évènements à notre programme.Tous les programmes graphiques utilisent ce concept basé sur les évènements. Le programme reçoit des évènements de l'ordinateur lorsqu'une touche du clavier est enfoncée ou lorsque la souris s'est déplacée. Alors le programme répond aux différents évènements. Au lieu de boucler sur 100 images, nous continuons à boucler jusqu'à ce que l'utilisateur nous demande d'arrêter :

In [ ]:
while 1:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            sys.exit()
    move_and_draw_all_game_objects()

Ce code boucle en continu, et vérifie s'il y a un quelconque évènement provenant de l'utilisateur. Nous quittons le programme si l'utilistateur appuie sur un bouton de son clavier ou clique sur le bouton de fermeture de la fenêtre. Ensuite, après avoir vérifié tous les évènements, nous déplaçons et dessinons tous les objets du jeu. (Nous les effacerons également avant de les déplacer).

Déplacer de multiples images

Voici la partie où nous allons vraiment changer les choses. Disons que nous désirons déplacer 10 images différentes en même temps à l'écran. Une bonne manière de le faire est d'utiliser les classes Python. Nous allons créer une classe qui représente un objet du jeu. Cet objet aura une fonction pour se déplacer lui-même, nous pourrons alors en créer autant que nous le voulons. Les fonctions pour dessiner et déplacer cet objet nécessitent de travailler d'une manière où ils se déplacent seulement d'une image (ou d'un pas) à la fois. Voici le code de python pour créer notre classe :

In [ ]:
class GameObject:
    def __init__(self, image, height, speed):
        self.speed = speed
        self.image = image
        self.pos = image.get_rect().move(0, height)
    def move(self):
        self.pos = self.pos.move(0, self.speed)
        if self.pos.right > 600:
            self.pos.left = 0

Nous avons donc deux fonctions dans notre classe. La méthode $\texttt{__init__()}$ construit notre objet. Elle le positionne et définit sa vitesse. La méthode $\texttt{move()}$ bouge l'objet d'un pas. S'il va trop loin, elle déplace l'objet en arrière vers la gauche.

Positionner le tout

Maintenant avec notre nouvelle classe, nous pouvons assembler l'intégralité du jeu. Voici à quoi ressemblerait la fonction principale de notre programme :

In [ ]:
screen = pygame.display.set_mode((640, 480))
player = pygame.image.load('player.bmp').convert()
background = pygame.image.load('background.bmp').convert()
screen.blit(background, (0, 0))
objects = []
for x in range(10):          #create 10 objects
    o = GameObject(player, x*40, x)
    objects.append(o)
while 1:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            sys.exit()
    for o in objects:
        screen.blit(background, o.pos, o.pos)
    for o in objects:
        o.move()
        screen.blit(o.image, o.pos)
    pygame.display.update()
    pygame.time.delay(100)

C'est le code dont nous avons besoin pour animer 10 objets à l'écran. Le seul point qui ait besoin d'explication, ce sont les deux boucles que nous utilisons pour effacer tous les objets et dessiner tous les objets. De façon à faire les choses proprement, nous avons besoin d'effacer tous les objets avant de redessiner chacun d'eux. Dans notre exemple nous n'avons pas de problème, mais quand les objets se recouvrent, l'utilisation de deux boucles comme celles-ci devient nécessaire. Autrement l'effacement de l'ancienne position d'un objet pourrait effacer la nouvelle position d'un objet affiché avant.

Le mot de la fin

Alors quelle sera la prochaine étape sur la route de votre apprentissage ? D'abord, jouer un peu avec cet exemple. La version complète de cet exemple est disponible dans le répertoire exemples de Pygame, sous le nom $\texttt{moveit.py}$. Jetez un coup d'oeil sur le code et jouez avec, lancez-le et apprenez-le.

Il y a plusieurs choses que vous pouvez faire avec, comme utiliser plus d'un type d'objet. Trouvez une façon pour supprimer proprement les objets quand vous ne désirez plus les afficher. Pour faire une mise à jour, utilisez la méthode $\texttt{display.update()}$ pour passer une liste de zones d'écran qui ont changé.

Il existe beaucoup d'autres tutoriaux et exemples pour Pygame qui peuvent vous aider en toutes circonstances. Alors maintenant, pour retenir en apprenant, retenez en lisant. :-)

Enfin, vous êtes libre de vous inscrire sur la mailing-list de Pygame ou dans un salon de discussion et poser toutes les questions que vous voulez à ce sujet. Il y a toujours quelqu'un pour vous aider.

Pour finir, prenez du plaisir, c'est pour ça que les jeux sont faits !