Concevez des jeux avec Pygame

Chapitre 1 : Dessiner des formes et des trajectoires avec Pygame

Sean M. Tracey

Traducteur

GALODE Alexandre

Alors que nous sommes des millions à prendre grand plaisir à améliorer nos scores à nos jeux vidéo favoris, finalement peu d'entre nous laissent paraître le désir de concevoir soi-même le jeu de ses rêves. Cela est loin d'être facile, mais apprendre à coder son propre jeu est infiniment plus satisfaisant qu'achever n'importe quel niveau.

Aussi, ce livre a pour but de vous apprendre l'essentiel afin que vous puissiez concevoir votre propre jeu, y compris sur Raspberry Pi(1), avec Python et Pygame.

En toute franchise, vous pourriez lire des douzaines de livres sur le sujet et ne pas en savoir encore suffisamment pour mener votre jeu à terme. Malgré toute la bonne volonté que vous pourriez y mettre, rien ne remplacera jamais la pratique.

Concevoir un jeu est une méthode agréable et amusante pour apprendre à coder, aussi j'espère que ce livre saura vous aider à aborder une nouvelle aventure.

Russel BARNES (Éditeur, Raspberry Pi)

Commentez

- Titre : Concevez des jeux avec Pygame

- Auteur : Sean M. Tracey

- Traducteur : GALODE Alexandre

- Parution : 28 septembre 2016

- Public visé :

- Licence : Le contenu de cet article est rédigé par Russel BARNES et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé. Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright ® 2013 Developpez.com.

Sommaire

- I. Dessiner des formes et des trajectoires

- II. Analyse de Hello.py

- III. Ajouter plus de formes

- IV. Dessiner des cercles

- V. Formes quelconques

- VI. Source et remerciements

I - Dessiner des formes et des trajectoires

NDLR : Ce livre a été rédigé avec une très grande ambition : faire découvrir la programmation des jeux vidéo aux plus débutants grâce à Python. Toutefois, afin de débuter dans la programmation Python avec de bonnes bases et découvrir ses bonnes pratiques, notamment la PEP20, nous vous recommandons de commencer par un des cours disponibles ICI.

Dans ce livre, nous allons apprendre à concevoir des jeux avec Pygame sur Raspberry Pi. Nous étudierons les images, les animations, la gestion du clavier et de la souris, la manipulation de l'audio et des lois de la physique. Chaque chapitre abordera un thème différent, nous permettant ainsi de comprendre les jeux auxquels nous jouons, et à terme, de créer un jeu de A à Z, avec pour seule limite notre imagination.

Ce livre n'est pas à destination des grands débutants, mais presque : il vous faudra maîtriser un minimum les notions basiques de Python, telles la manipulation de fichier ou encore la création de classes. Si vous n'avez pas encore préparé votre Pi et que vous êtes un peu perdu à ce sujet, je vous invite à effectuer quelques recherches sur le net. Vous y trouverez rapidement de l'aide. Vous pouvez, par exemple, aller jeter un coup d'œil sur http://www.raspberrypi.org/resources.

Rendez-vous également sur la page Raspberry Pi de Developpez.com.

Dans ce premier chapitre, nous dessinerons et colorierons différentes formes dans une fenêtre. Cela sera loin de valoir Grand Theft Auto V, mais constitue la première étape indispensable.

Pour commencer, ouvrez votre IDE préféré, créez un nouveau fichier et insérez le code qui suit. Sauvegardez le tout dans un fichier « hello.py ». Ouvrez un terminal, et saisissez python hello.py. Si tout se passe bien, une nouvelle fenêtre apparaît, affichant un carré rouge sur fond noir dans le coin supérieur gauche de la fenêtre.

1. import pygame

2. pygame.init()

3. window = pygame.display.set_mode((500, 400))

4. while True:

5. pygame.draw.rect(window, (255, 0, 0), (0, 0, 50, 30))

6. pygame.display.update()

Félicitations, vous venez de créer votre premier programme Pygame. Continuons.

II - Analyse de Hello.py

Les deux premières lignes de notre premier programme sont très simples : elles permettent d'avertir Python que l'on souhaite utiliser Pygame. La ligne import pygame importe le code de la bibliothèque Pygame dans votre script, et de cette façon, vous n'aurez pas à saisir tout le code vous-mêmes. Pygame procure toutes les facilités indispensables à la création de jeux ou d'applications interactives. pygame.init() permet d'initialiser Pygame qui devient prêt à l'emploi.

Maintenant, regardons la troisième ligne de plus près.

1. window = pygame.display.set_mode((500, 400))

Les méthodes du sous-module pygame.display vont permettre de donner l'aspect de la fenêtre au lancement. La méthode set_mode fixe les dimensions de la fenêtre. Notez ici que la largeur apparaît toujours avant la hauteur : (largeur, hauteur). window est la variable qui désigne l'instance de cette fenêtre et pourra être utilisée plus tard dans le code pour dessiner à l'intérieur.

La méthode set_mode du module d'affichage de Pygame est responsable de l'affichage de la fenêtre et des surfaces (terme informel pour désigner les pixels que nous manipulerons). Nous lui passons un tuple (dans ce cas une liste de nombres) afin de lui préciser la dimension souhaitée pour la fenêtre. Dans notre exemple, nous désirons une fenêtre de 500 pixels de largeur et 400 pixels de hauteur. Si nous passons des valeurs plus importantes, la fenêtre sera plus grande, et inversement.

Un tuple est comme une liste, mais contrairement à ces dernières, leur contenu ne peut être modifié (valeurs dites immuables).

Les quelques lignes suivantes servent à dessiner des formes dans la fenêtre. Normalement, quand un programme se lance, il exécute le code, puis à la fin du programme, il se ferme. Cela est parfait, sauf si vous désirez ajouter de l'interaction ou de l'animation au sein de votre programme, ce qui est exactement le but désiré dans le cadre d'un jeu vidéo.

Aussi afin d'éviter que le programme ne se ferme seul, nous ajoutons une boucle infinie. Cette boucle ne se finira donc jamais, car True est une condition toujours vraie par définition, aussi le programme restera ouvert aussi longtemps que nous ne forcerons pas sa fermeture.

La première chose que nous faisons dans notre boucle est de dessiner un rectangle. Un rectangle est la forme la plus simple à dessiner avec Pygame :

1. pygame.draw.rect(window, (255, 0, 0), (0, 0, 50, 30))

Les paramètres permettent d'indiquer où nous désirons dessiner, puis avec quelle couleur, et enfin les dimensions désirées.

Dans notre programme « hello.py », nous avons demandé à Pygame de dessiner un rectangle dans notre fenêtre. Ensuite, nous stipulons à Pygame de quelle couleur nous désirons colorer notre rectangle, en lui passant un tuple avec les composantes (rouge, vert, bleu) représentant la quantité de rouge, vert et bleu qui sont les trois couleurs primaires ; 255 correspondant au maximum d'intensité de la couleur.

Ici, nous lui demandons la couleur (255, 0, 0) ce qui correspond à du rouge pur. Si nous lui avions demandé du (255, 0, 255), le rectangle aurait été violet. Si nous lui avions demandé du (100, 100, 100), le rectangle aurait été gris foncé, car toutes les valeurs sont identiques.

Enfin, nous indiquons à Pygame où placer le rectangle et quelle taille il doit avoir. Cette dernière étape s'effectue en passant un tuple comprenant quatre nombres. Le premier nombre est la position, en X, du coin supérieur gauche du rectangle. Le second nombre est la position, en Y, du coin supérieur gauche du rectangle. Le troisième nombre est la largeur en pixels du rectangle, et le dernier nombre la hauteur.

Ainsi, si nous désirons que notre rectangle commence de la position (50, 100) avec 20 pixels en largeur, et 80 pixels en hauteur, nous écrirons la ligne :

1. pygame.draw.rect(window, (255, 0, 0), (50, 100, 20, 80))

Attention, veillez bien à respecter l'ordre des paramètres lors de l'appel d'une fonction Pygame, sous peine de voir votre programme crasher.

La dernière ligne de notre programme « hello.py » est on ne peut plus simple : elle indique à Pygame que nous avons fini de définir des formes et qu'il peut maintenant afficher le rendu en rafraîchissant d'un coup l'affichage dans la fenêtre.

III - Ajouter plus de formes

Nous venons de dessiner avec succès une forme, mais tâchons d'aller un peu plus loin. Nous allons dessiner quelques rectangles sur l'écran et jouer un peu avec leurs paramètres.

Aucun besoin de créer un nouveau fichier, nous repartirons de notre fichier « hello.py ». Nous ne modifierons que le contenu de la boucle.

1. while True:

2. pygame.draw.rect(window, (255, 0, 0), (100, 100, 50, 50))

3. pygame.draw.rect(window, (0, 255, 0), (150, 100, 50, 50))

4. pygame.draw.rect(window, (0, 0, 255), (200, 100, 50, 50))

5. pygame.display.update()

Quand vous dessinez un rectangle, vous avez la possibilité de choisir la largeur du trait. En l'absence de toute consigne, par défaut, la forme sera entièrement remplie.

Maintenant, nous pouvons dessiner trois carrés : un rouge, un bleu et un vert. Cela est très simple, mais ces carrés sont alignés côte à côte. Que se passerait-il s'ils se superposaient ? Modifiez le code de la façon suivante :

1. while True:

2. pygame.draw.rect(window, (255, 0, 0), (0, 0, 50, 50))

3. pygame.draw.rect(window, (0, 255, 0), (40, 0, 50, 50))

4. pygame.draw.rect(window, (0, 0, 255), (80, 0, 50, 50))

5. pygame.display.update()

Cette fois-ci, nous affichons deux rectangles et un carré, mais ce n'est pas ce que nous avons demandé, car les dimensions (50, 50) sont celles d'un carré. Que se passe-t-il ? Nous pouvons voir à l'affichage que les éléments s'empilent dans l'ordre dans lequel ils sont appelés. Ainsi, lorsque l'on dessine notre deuxième forme, la couleur des pixels communs avec la première forme est remplacée par la couleur des pixels de la seconde forme. Pour s'en convaincre, il suffit de modifier le contenu de notre boucle :

1. while True:

2. pygame.draw.rect(window, (255, 0, 0), (0, 0, 50, 50))

3. #pygame.draw.rect(window, (0, 255, 0), #(40, 0, 50, 50))FROM HERE

4. pygame.draw.rect(window, (0, 0, 255), (80, 0, 50, 50))

5. pygame.draw.rect(window, (0, 255, 0), (40, 0, 50, 50)) #TO HERE

6. pygame.display.update()

Maintenant, notre code dessine d'abord un rectangle, puis un carré, et enfin un rectangle. Cela est dû au fait que nous avons en premier dessiné les carrés rouge et bleu avant d'afficher par-dessus le carré vert. Les carrés rouge et bleu sont bien présents en entier, mais nous ne pouvons les voir entièrement, ils ressemblent donc à des rectangles.

Mais Pygame ne se limite pas à nous permettre de dessiner des rectangles : nous pouvons dessiner quantité de formes différentes telles des cercles, des ellipses, et des trajectoires quelconques (constituées de lignes reliant les différents points de la trajectoire).

IV - Dessiner des cercles

Sur le principe, la procédure est proche de celle pour dessiner des rectangles, excepté qu'au lieu de communiquer une largeur et une hauteur, nous passons un rayon et les coordonnées du centre de ce cercle. Aussi, par exemple, si nous désirons dessiner un cercle jaune, au milieu de notre fenêtre avec un diamètre de 40 pixels, il suffit de remplacer le contenu de la boucle de notre programme par le code suivant :

1. while True:

2. #Just like before to help us remember

3. #pygame.draw.circle(WHERE TO DRAW, (RED, GREEN, BLUE),\

4. #(X COORDINATE, Y COORDINATE), RADIUS, HEIGHT, WIDTH)

5. pygame.draw.circle(window, (255, 255, 0), (250, 200), 20, 0)

6. pygame.display.update()

Tout comme pour dessiner un rectangle, nous précisons à Pygame sur quelle surface nous désirons dessiner notre cercle, quelle couleur nous désirons, et où il doit se placer. Le rayon est une caractéristique du cercle et doit être spécifié.

Vous avez peut-être remarqué que nous avons saisi un « 0 » après la valeur de notre rayon ; cette valeur sert à déterminer la largeur du trait servant à dessiner notre cercle. Si nous passons la valeur « 0 », le cercle est rempli. Mais si nous passons la valeur « 2 », nous dessinerons un cercle avec un trait de 2 pixels de large, sans remplissage.

1. while True:

2. #Filled

3. pygame.draw.circle(window, (255, 255, 0), (200, 200), 20, 0)

4. #Not filled

5. pygame.draw.circle(window, (255, 255, 0), (300, 200), 20, 2)

6. pygame.display.update()

Et pour les ellipses, me direz-vous ? Nous devons passer les coordonnées (X, Y) du coin supérieur gauche, la largeur et la hauteur du rectangle dans lequel s'inscrit l'ellipse. Concrétisons cela par un exemple :

1. while True:

2. pygame.draw.ellipse(window, (255, 0, 0), (100, 100, 100, 50))

3. pygame.draw.ellipse(window, (0, 255, 0), (100, 150, 80, 40))

4. pygame.draw.ellipse(window, (0, 0, 255), (100, 190, 60, 30))

5. pygame.display.update()

Exécutez ce code. Vous pouvez maintenant voir trois ellipses : une rouge, une verte, et une bleue ; chacune de taille différente. Si vous désirez voir comment ces ellipses ont été dessinées, vous pouvez dessiner des rectangles dans lesquels s'inscrivent les ellipses. Vous verrez alors qu'ils s'imbriquent parfaitement. Comme vous l'avez peut-être deviné, vous pouvez dessiner des cercles, via la méthode pygame.draw.ellipse en communiquant une hauteur et une largeur identiques.

1. while True:

2. pygame.draw.rect(window, (255, 0, 0), (100, 100, 100, 50), 2)

3. pygame.draw.ellipse(window, (255, 0, 0), (100, 100, 100, 50))

4. pygame.draw.rect(window, (0, 255, 0), (100, 150, 80, 40), 2)

5. pygame.draw.ellipse(window, (0, 255, 0), (100, 150, 80, 40))

6. pygame.draw.rect(window, (0, 0, 255), (100, 190, 60, 30), 2)

7. pygame.draw.ellipse(window, (0, 0, 255), (100, 190, 60, 30))

8. #Circle

9. pygame.draw.ellipse(window, (0, 0, 255), (100, 250, 40, 40))

10. pygame.display.update()

V - Formes quelconques

Nous venons de voir comment dessiner des rectangles, des carrés, et des cercles. Mais comment faire si nous désirons dessiner un triangle, un pentagone, un hexagone, ou encore un octogone ? Malheureusement, il n'y a pas de fonctions dédiées, mais nous pouvons néanmoins utiliser les trajectoires.

Les trajectoires nous permettent de dessiner des formes irrégulières en définissant des points dans l'espace, en les reliant entre eux par des lignes, et remplissant l'espace que nous avons créé entre eux.

Dans la mesure où nous montons d'un cran en complexité, je vous invite à créer un nouveau fichier « path.py ». Voici le premier code à saisir :

1. import pygame

2. pygame.init()

3. window = pygame.display.set_mode((500, 400))

4. while True:

5. pygame.display.update()

Chaque trajectoire est dessinée avec un ensemble de lignes connectées entre elles, mais, avant de les connecter, dessinons quelques lignes seules afin de nous familiariser avec. Cela est possible grâce à pygame.draw.line(). Éditez « path.py » de la façon suivante :

1. while True:

2. pygame.draw.line(window, (255, 255, 255), (0, 0), (499, 399), 1)

3. pygame.display.update()

Si vous exécutez ce code maintenant, vous verrez une ligne d'un pixel de large, allant du coin supérieur gauche au coin inférieur droit de notre fenêtre Pygame. Les paramètres que nous avons passés respectent la même logique que pour les rectangles ou les ellipses.

Ainsi, nous avons commencé par stipuler à Pygame où nous désirions dessiner notre forme, puis nous avons choisi une couleur. Après, les choses changent un peu. L'argument suivant est un tuple contenant les coordonnées (X, Y) du point de départ de notre ligne. L'argument qui suit est un tuple contenant les coordonnées (X, Y) du point final de notre ligne.

C'est entre ces deux points que notre ligne sera dessinée. Le dernier argument, enfin, correspond à l'épaisseur désirée de notre ligne, en pixels.

Via ce système, nous pouvons donc désormais créer des formes diverses en définissant des points dans notre fenêtre.

Partant de cela, dessinons un triangle :

1. while True:

2. pygame.draw.line(window, (255, 255, 255), (50, 50), (75, 75), True)

3. pygame.draw.line(window, (255, 255, 255), (75, 75), (25, 75), True)

4. pygame.draw.line(window, (255, 255, 255), (25, 75), (50, 50), True)

5. pygame.display.update()

À l'exécution de ce code, vous pouvez voir un triangle blanc d'un pixel d'épaisseur. Nous pouvons constater également que nous répétons de multiples fois la même information. Nous pouvons donc optimiser notre code via pygame.draw.lines(). Alors que pygame.draw.line() ne nous permet de ne dessiner qu'une seule ligne à la fois, pygame.draw.lines() nous permet de dessiner tout un lot de lignes. Chaque tuple de coordonnées (X, Y) sera alors joint au suivant, et ainsi de suite.

Ainsi, le code suivant produira le même résultat que le précédent, exception faite que le code sera plus concis. Notez au passage que nous n'aurons pas à clore le triangle, Pygame s'en chargeant pour nous. Juste avant de communiquer à Pygame les coordonnées de nos points, nous avons la possibilité de passer un paramètre à True ou False qui permet de stipuler à Pygame s'il doit fermer la forme, ou non, à notre place. Je vous invite à saisir False et d'exécuter à nouveau le code afin de mieux comprendre le résultat.

1. while True:

2. pygame.draw.line(window, (255, 255, 255), True, ((50, 50), (75, 75), (25, 75)), 1)

3. pygame.display.update()

1. while True:

2. #pygame.draw.lines(WHERE TO DRAW, COLOUR, \

3. # CLOSE THE SHAPE FOR US?, THE POINTSTO DRAW, LINE WIDTH)

4. pygame.draw.lines(window, (255, 255, 255), True, ((50, 50), (75, 75), (63, 100), (38, 100), (25, 75)), 1)

5. pygame.display.update()

Avec ce dernier code, vous dessinerez votre propre pentagone. Si vous le désirez, à la place, dessinez un hexagone, un octogone, il vous suffit de modifier le nombre de points. Pourquoi n'utiliseriez-vous pas maintenant Pygame pour faire un peu de « pixel art » ?

VI - Source et remerciements

Cet article est une traduction adaptée du livre « Make Games With Python » de Sean M. Tracey, du magazine The MagPi, disponible ICI. Ce livre est placé sous licence Creative Commons BY-NC-SA.

Nous remercions les membres de la Rédaction de Developpez pour le travail de traduction et de relecture qu'ils ont effectué, en particulier :

- LittleWhite

- f-leb

(1)NDLR À l'origine, ce tutoriel est un livre à destination exclusive du Raspberry Pi. Le sujet est cependant aisément extensible à n'importe quel PC pouvant faire tourner Python et Pygame.