PyGame: une introduction à la programmation de jeux en Python

PyGame: une introduction à la programmation de jeux en Python

Lorsque j’ai commencé à apprendre la programmation informatique à la fin du dernier millénaire, elle était motivée par mon désir d’écrire des jeux informatiques. J’ai essayé de comprendre comment écrire des jeux dans toutes les langues et sur toutes les plateformes que j’ai apprises, y compris Python. C’est ainsi que j’ai découvert + pygame + et appris à l’utiliser pour écrire des jeux et d’autres programmes graphiques. À l’époque, je voulais vraiment une introduction sur + pygame +.

*À la fin de cet article, vous pourrez:*
  • Dessinez des éléments sur votre écran

  • Jouer des effets sonores et de la musique

  • Gérer l’entrée utilisateur

  • Implémenter des boucles d’événements

  • Décrire en quoi la programmation de jeu diffère de la programmation Python procédurale standard

Cette introduction suppose que vous avez une basic compréhension de l’écriture de programmes Python, y compris les fonctions définies par l’utilisateur, https://realpython.com/courses/python-imports -101/[imports], https://realpython.com/courses/mastering- while-loops/[loops] et conditionals. Vous devez également être familiarisé avec how pour ouvrir des fichiers sur votre plate-forme. Une compréhension basic du Python orienté objet est également utile. + pygame + fonctionne avec la plupart des versions de Python, mais Python 3.6 est recommandé et utilisé tout au long de cet article.

Vous pouvez obtenir tout le code de cet article à suivre:

*Clone Repo:* https://realpython.com/bonus/pygame/[Cliquez ici pour cloner le référentiel que vous utiliserez] pour savoir comment utiliser PyGame dans ce didacticiel.

Contexte et configuration

+ pygame + est un wrapper Python pour la bibliothèque SDL, qui signifie Simple DirectMedia Layer . SDL fournit un accès multiplateforme aux composants matériels multimédias sous-jacents de votre système, tels que le son, la vidéo, la souris, le clavier et le joystick. + pygame + a commencé sa vie en remplacement du PySDL projet bloqué. La nature multiplateforme de SDL et de + pygame + signifie que vous pouvez écrire des jeux et des programmes multimédia Python riches pour chaque plate-forme qui les prend en charge!

Pour installer + pygame + sur votre plateforme, utilisez la commande + pip + appropriée:

$ pip install pygame

Vous pouvez vérifier l’installation en chargeant l’un des exemples fournis avec la bibliothèque:

$ python3 -m pygame.examples.aliens

Si une fenêtre de jeu apparaît, alors + pygame + est installé correctement! Si vous rencontrez des problèmes, le Getting Started guide décrit certains problèmes connus et mises en garde pour toutes les plates-formes.

Programme PyGame de base

Avant de passer aux détails, examinons un programme de base + pygame +. Ce programme crée une fenêtre, remplit l’arrière-plan de blanc et dessine un cercle bleu au milieu:

 1 # Simple pygame program
 2
 3 # Import and initialize the pygame library
 4 import pygame
 5 pygame.init()
 6
 7 # Set up the drawing window
 8 screen = pygame.display.set_mode([500, 500])
 9
10 # Run until the user asks to quit
11 running = True
12 while running:
13
14     # Did the user click the window close button?
15     for event in pygame.event.get():
16         if event.type == pygame.QUIT:
17             running = False
18
19     # Fill the background with white
20     screen.fill((255, 255, 255))
21
22     # Draw a solid blue circle in the center
23     pygame.draw.circle(screen, (0, 0, 255), (250, 250), 75)
24
25     # Flip the display
26     pygame.display.flip()
27
28 # Done! Time to quit.
29 pygame.quit()

Lorsque vous exécutez ce programme, vous verrez une fenêtre qui ressemble à ceci:

Un programme Pygame simple

Décomposons ce code section par section:

  • Lignes 4 et 5 importez et initialisez la bibliothèque + pygame +. Sans ces lignes, il n’y a pas de «+ pygame +».

  • La ligne 8 configure la fenêtre d’affichage de votre programme. Vous fournissez une liste ou un tuple qui spécifie la largeur et la hauteur de la fenêtre à créer. Ce programme utilise une liste pour créer une fenêtre carrée avec 500 pixels de chaque côté.

  • Les lignes 11 et 12 configurent une boucle de jeu pour contrôler la fin du programme. Vous couvrirez les boucles de jeu plus loin dans ce didacticiel.

  • Lignes 15 à 17 analyser et gérer les événements dans la boucle de jeu. Vous arriverez également aux événements un peu plus tard. Dans ce cas, le seul événement géré est + pygame.QUIT +, qui se produit lorsque l’utilisateur clique sur le bouton de fermeture de la fenêtre.

  • La ligne 20 remplit la fenêtre d’une couleur unie. + screen.fill () + accepte une liste ou un tuple spécifiant les valeurs RVB pour la couleur. Puisque + (255, 255, 255) + a été fourni, la fenêtre est remplie de blanc.

  • La ligne 23 trace un cercle dans la fenêtre, en utilisant les paramètres suivants:

  • + écran +: la fenêtre sur laquelle dessiner

  • + (0, 0, 255) +: un tuple contenant des valeurs de couleur RVB

  • + (250, 250) +: un tuple spécifiant les coordonnées centrales du cercle

  • + 75 +: le rayon du cercle à dessiner en pixels

  • Ligne 26 met à jour le contenu de l’affichage à l’écran. Sans cet appel, rien n’apparaît dans la fenêtre!

  • La ligne 29 quitte + pygame +. Cela ne se produit qu’une fois la boucle terminée.

C’est la version + pygame + de "Hello, World". Examinons maintenant un peu plus en profondeur les concepts derrière ce code.

Concepts de PyGame

Comme + pygame + et la bibliothèque SDL sont portables sur différentes plates-formes et appareils, ils doivent tous deux définir et travailler avec des abstractions pour diverses réalités matérielles. Comprendre ces concepts et abstractions vous aidera à concevoir et à développer vos propres jeux.

Initialisation et modules

La bibliothèque + pygame + est composé d’un certain nombre de constructions Python, qui comprennent plusieurs modules différents. Ces modules fournissent un accès abstrait à du matériel spécifique sur votre système, ainsi que des méthodes uniformes pour travailler avec ce matériel. Par exemple, + display + permet un accès uniforme à votre affichage vidéo, tandis que + joystick + permet un contrôle abstrait de votre joystick.

Après avoir importé la bibliothèque + pygame + dans l’exemple ci-dessus, la première chose que vous avez faite a été initialize PyGame en utilisant + pygame.init () + . Cette fonction https://www.pygame.org/docs/ref/pygame.html#pygame.init[calls les fonctions + init () + distinctes de tous les modules + pygame + inclus. Étant donné que ces modules sont des abstractions pour du matériel spécifique, cette étape d’initialisation est requise pour que vous puissiez travailler avec le même code sur Linux, Windows et Mac.

Écrans et surfaces

En plus des modules, + pygame + inclut également plusieurs classes Python *, qui encapsulent des concepts non dépendants du matériel. L’un d’entre eux est le https://www.pygame.org/docs/ref/surface.html [+ Surface +] qui, à sa base, définit une zone rectangulaire sur laquelle vous pouvez dessiner. Les objets + Surface + sont utilisés dans de nombreux contextes dans + pygame +. Plus tard, vous verrez comment charger une image dans une "+ Surface +" et l’afficher à l’écran.

Dans + pygame +, tout est affiché sur un seul https://www.pygame.org/docs/ref/display.html [+ display +] créé par l’utilisateur, qui peut être une fenêtre ou un plein écran. L’affichage est créé en utilisant https://www.pygame.org/docs/ref/display.html#pygame.display.set_mode [+ .set_mode () +], qui renvoie un + Surface + représentant la partie visible de la fenêtre. C’est ce + Surface + que vous passez dans des fonctions de dessin comme https://www.pygame.org/docs/ref/draw.html#pygame.draw.circle [+ pygame.draw.circle () +] , et le contenu de cette + Surface + 'est poussé vers l’écran lorsque vous appelez https://www.pygame.org/docs/ref/display.html#pygame.display.flip [ + pygame.display.flip ( ) + `].

Images et Rects

Votre programme de base + pygame + 'a dessiné une forme directement sur la surface + de l’écran, mais vous pouvez également travailler avec des images sur le disque. Le https://www.pygame.org/docs/ref/image.html [module + `+ image +] vous permet de https://www.pygame.org/docs/ref/image.html#pygame.image. charger [charger] et save des images dans une variété de formats populaires. Les images sont chargées dans des objets + Surface +, qui peuvent ensuite être manipulés et affichés de nombreuses façons.

Comme mentionné ci-dessus, les objets + Surface + sont représentés par des rectangles, tout comme de nombreux autres objets dans + pygame +, tels que les images et les fenêtres. Les rectangles sont tellement utilisés qu’il existe une special + Rect + class juste pour les gérer. Vous utiliserez des objets et des images «+ Rect +» dans votre jeu pour attirer les joueurs et les ennemis, et pour gérer les collisions entre eux.

D’accord, c’est assez de théorie. Concevons et écrivons un jeu!

Conception de jeu de base

Avant de commencer à écrire du code, c’est toujours une bonne idée d’avoir une conception en place. Comme il s’agit d’un jeu tutoriel, concevons également un gameplay de base:

  • Le but du jeu est d’éviter les obstacles entrants:

  • Le joueur démarre sur le côté gauche de l’écran.

  • Les obstacles entrent aléatoirement de la droite et se déplacent vers la gauche en ligne droite.

  • Le joueur peut se déplacer vers la gauche, la droite, le haut ou le bas pour éviter les obstacles.

  • Le joueur ne peut pas quitter l’écran.

  • Le jeu se termine soit lorsque le joueur est heurté par un obstacle, soit lorsque l’utilisateur ferme la fenêtre.

Quand il décrivait des projets logiciels, un mier collègue avait l’habitude de dire: «Vous ne savez pas ce que vous faites tant que vous ne savez pas ce que vous faites» t faire. " Dans cet esprit, voici quelques éléments qui ne seront pas traités dans ce didacticiel:

  • Pas de vies multiples

  • Pas de tenue de score

  • Aucune capacité d’attaque des joueurs

  • Aucun niveau avancé *Pas de boss

Vous êtes libre d’essayer d’ajouter ces fonctionnalités et d’autres à votre propre programme.

Commençons!

Importation et initialisation de PyGame

Après avoir importé + pygame +, vous devrez également l’initialiser. Cela permet à + ​​pygame + de connecter ses abstractions à votre matériel spécifique:

 1 # Import the pygame module
 2 import pygame
 3
 4 # Import pygame.locals for easier access to key coordinates
 5 # Updated to conform to flake8 and black standards
 6 from pygame.locals import (
 7     K_UP,
 8     K_DOWN,
 9     K_LEFT,
10     K_RIGHT,
11     K_ESCAPE,
12     KEYDOWN,
13     QUIT,
14 )
15
16 # Initialize pygame
17 pygame.init()

La bibliothèque + pygame + définit beaucoup de choses en plus des modules et des classes. Il définit également quelques local constants pour des choses comme les frappes au clavier, les mouvements de la souris et les attributs d’affichage. Vous référencez ces constantes en utilisant la syntaxe + pygame. <CONSTANT> +. En important des constantes spécifiques de + pygame.locals +, vous pouvez utiliser la syntaxe + <CONSTANT> + à la place. Cela vous fera économiser quelques touches et améliorera la lisibilité globale.

Configuration de l’affichage

Maintenant, vous avez besoin de quelque chose sur lequel s’appuyer! Créez un screen pour être la toile globale:

 1 # Import the pygame module
 2 import pygame
 3
 4 # Import pygame.locals for easier access to key coordinates
 5 # Updated to conform to flake8 and black standards
 6 from pygame.locals import (
 7     K_UP,
 8     K_DOWN,
 9     K_LEFT,
10     K_RIGHT,
11     K_ESCAPE,
12     KEYDOWN,
13     QUIT,
14 )
15
16 # Initialize pygame
17 pygame.init()
18
19 # Define constants for the screen width and height
20 SCREEN_WIDTH = 800
21 SCREEN_HEIGHT = 600
22
23 # Create the screen object
24 # The size is determined by the constant SCREEN_WIDTH and SCREEN_HEIGHT
25 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

Vous créez l’écran à utiliser en appelant + pygame.display.set_mode () + et en passant un tuple ou une liste avec la largeur et la hauteur souhaitées. Dans ce cas, la fenêtre est 800x600, telle que définie par les constantes + SCREEN_WIDTH + 'et + SCREEN_HEIGHT + sur les lignes 20 et 21. Cela renvoie un `+ Surface + qui représente les dimensions intérieures de la fenêtre. Il s’agit de la partie de la fenêtre que vous pouvez contrôler, tandis que le système d’exploitation contrôle les bordures de la fenêtre et la barre de titre.

Si vous exécutez ce programme maintenant, une fenêtre apparaîtra brièvement, puis disparaîtra immédiatement à la fermeture du programme. Ne cligne pas des yeux ou tu pourrais le manquer! Dans la section suivante, vous vous concentrerez sur la boucle de jeu principale pour vous assurer que votre programme ne se termine que lorsque vous avez reçu la bonne entrée.

Configuration de la boucle de jeu

Chaque jeu de Pong à Fortnite utilise une game loop pour contrôler le gameplay. La boucle de jeu fait quatre choses très importantes:

  1. Traite l’entrée utilisateur

  2. Met à jour l’état de tous les objets du jeu

  3. Met à jour l’affichage et la sortie audio

  4. Maintient la vitesse du jeu

Chaque cycle de la boucle de jeu est appelé un* cadre *, et plus vite vous pouvez faire les choses à chaque cycle, plus vite votre jeu se déroulera. Les images continuent de se produire jusqu’à ce que certaines conditions pour quitter le jeu soient remplies. Dans votre conception, deux conditions peuvent mettre fin à la boucle du jeu:

  1. Le joueur entre en collision avec un obstacle. (Vous couvrirez la détection de collision plus tard.)

  2. Le joueur ferme la fenêtre.

La première chose que fait la boucle de jeu est de traiter les entrées utilisateur pour permettre au joueur de se déplacer sur l’écran. Par conséquent, vous avez besoin d’un moyen de capturer et de traiter une variété d’entrées. Pour ce faire, vous utilisez le système d’événements + pygame +.

Événements de traitement

Les pressions sur les touches, les mouvements de la souris et même les mouvements du joystick sont quelques-unes des façons dont un utilisateur peut fournir une entrée. Toutes les entrées utilisateur entraînent la génération d’un event. Les événements peuvent se produire à tout moment et proviennent souvent (mais pas toujours) en dehors du programme. Tous les événements dans + pygame + sont placés dans la file d’attente d’événements, qui peut ensuite être consultée et manipulée. Traiter les événements est appelé les gérer , et le code pour le faire est appelé un gestionnaire d’événements .

Chaque événement dans + pygame + est associé à un type d’événement. Pour votre jeu, les types d’événements sur lesquels vous vous concentrerez sont les touches et la fermeture des fenêtres. Les événements de pression de touche ont le type d’événement «+ KEYDOWN », et l'événement de fermeture de fenêtre a le type « QUIT ». Différents types d'événements peuvent également être associés à d'autres données. Par exemple, le type d'événement ` KEYDOWN ` a également une variable appelée ` touche +` pour indiquer quelle touche a été enfoncée.

Vous accédez à la liste de tous les événements actifs dans la file d’attente en appelant + pygame.event.get () +. Vous parcourez ensuite cette liste, inspectez chaque type d’événement et répondez en conséquence:

27 # Variable to keep the main loop running
28 running = True
29
30 # Main loop
31 while running:
32     # Look at every event in the queue
33     for event in pygame.event.get():
34         # Did the user hit a key?
35         if event.type == KEYDOWN:
36             # Was it the Escape key? If so, stop the loop.
37             if event.key == K_ESCAPE:
38                 running = False
39
40         # Did the user click the window close button? If so, stop the loop.
41         elif event.type == QUIT:
42             running = False

Examinons de plus près cette boucle de jeu:

  • La ligne 28 définit une variable de contrôle pour la boucle de jeu. Pour quitter la boucle et le jeu, vous définissez + running = False +. La boucle de jeu commence à la ligne 29.

  • La ligne 31 démarre le gestionnaire d’événements, parcourant chaque événement actuellement dans la file d’attente d’événements. S’il n’y a aucun événement, la liste est vide et le gestionnaire ne fait rien.

  • Lignes 35 à 38 vérifiez si l’événement + event.type + 'actuel est un événement + KEYDOWN + . Si c’est le cas, le programme vérifie quelle touche a été enfoncée en regardant l’attribut `+ event.key +. Si la clé est la touche [.keys] # Esc #, indiquée par + K_ESCAPE +, alors elle quitte la boucle de jeu en définissant + running = False +.

  • Les lignes 41 et 42 effectuent une vérification similaire pour le type d’événement appelé `+ QUIT + '. Cet événement se produit uniquement lorsque l’utilisateur clique sur le bouton de fermeture de la fenêtre. L’utilisateur peut également utiliser toute autre action du système d’exploitation pour fermer la fenêtre.

Lorsque vous ajoutez ces lignes au code précédent et l’exécutez, vous voyez une fenêtre avec un écran vide ou noir:

Une fenêtre Pygame vide mais persistante

La fenêtre ne disparaîtra pas tant que vous n’aurez pas appuyé sur la touche [.keys] # Esc #, ou déclencherez autrement un événement + QUIT + en fermant la fenêtre.

Dessin à l’écran

Dans l’exemple de programme, vous avez dessiné à l’écran à l’aide de deux commandes:

  1. + screen.fill () + pour remplir l’arrière-plan

  2. + pygame.draw.circle () + pour dessiner un cercle

Vous allez maintenant découvrir une troisième façon de dessiner à l’écran: en utilisant un + Surface +.

Rappelons qu’un https://www.pygame.org/docs/ref/surface.html [+ Surface +] est un objet rectangulaire sur lequel vous pouvez dessiner, comme une feuille de papier vierge. L’objet + screen + est un + Surface +, et vous pouvez créer vos propres objets + Surface + séparément de l’écran d’affichage. Voyons comment cela fonctionne:

44 # Fill the screen with white
45 screen.fill((255, 255, 255))
46
47 # Create a surface and pass in a tuple containing its length and width
48 surf = pygame.Surface((50, 50))
49
50 # Give the surface a color to separate it from the background
51 surf.fill((0, 0, 0))
52 rect = surf.get_rect()

Une fois l’écran rempli de blanc à la ligne 45, un nouveau + Surface + est créé à la ligne 48. Ce + Surface + a une largeur de 50 pixels, une hauteur de 50 pixels et est affecté à + ​​surf + '. À ce stade, vous le traitez comme le `+ écran +. Donc en ligne, 51 vous le remplissez de noir. Vous pouvez également accéder à son + Rect + sous-jacent en utilisant + .get_rect () +. Il est stocké sous la forme `+ rect + 'pour une utilisation ultérieure.

Utilisation de + .blit () + et + .flip () +

Il ne suffit pas de créer un nouveau "+ Surface " pour le voir à l'écran. Pour ce faire, vous devez https://www.pygame.org/docs/ref/surface.html#pygame.Surface.blit[blit] le ` Surface ` sur un autre ` Surface `. Le terme ` blit ` signifie *Block Transfer* , et ` .blit () ` est la façon dont vous copiez le contenu d'un ` Surface ` dans un autre. Vous ne pouvez que ` .blit () ` d'un ` Surface ` à un autre, mais comme l'écran n'est qu'un autre ` Surface `, ce n'est pas un problème. Voici comment dessiner ` surf +` à l’écran:

54 # This line says "Draw surf onto the screen at the center"
55 screen.blit(surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
56 pygame.display.flip()

L’appel + .blit () + sur la ligne 55 prend deux arguments:

  1. Le + Surface + pour dessiner

  2. L’emplacement où le dessiner sur la source + Surface +

Les coordonnées + (SCREEN_WIDTH/2, SCREEN_HEIGHT/2) + indiquent à votre programme de placer + surf + au centre exact de l’écran, mais cela ne ressemble pas vraiment à cela:

Blitting une surface sur l’écran

La raison pour laquelle l’image semble décentrée est que + .blit () + place le coin supérieur gauche de + surf + à l’emplacement indiqué. Si vous voulez que "+ surf " soit centré, vous devrez faire quelques calculs pour le déplacer vers le haut et vers la gauche. Vous pouvez le faire en soustrayant la largeur et la hauteur de ` surf ` de la largeur et la hauteur de l'écran, en les divisant par 2 pour localiser le centre, puis en passant ces nombres comme arguments à ` ​​screen.blit () + ' :

54 # Put the center of surf at the center of the display
55 surf_center = (
56     (SCREEN_WIDTH-surf.get_width())/2,
57     (SCREEN_HEIGHT-surf.get_height())/2
58 )
59
60 # Draw surf at the new coordinates
61 screen.blit(surf, surf_center)
62 pygame.display.flip()

Notez l’appel à https://www.pygame.org/docs/ref/display.html#pygame.display.flip [+ pygame.display.flip () +] après l’appel à + ​​blit () + ". Cela met à jour tout l’écran avec tout ce qui a été dessiné depuis le dernier flip. Sans l’appel à `+ ​​.flip () +, rien ne s’affiche.

Sprites

Dans votre conception de jeu, le joueur commence à gauche et les obstacles viennent de droite. Vous pouvez représenter tous les obstacles avec des objets + Surface + pour faciliter le dessin, mais comment savoir où les dessiner? Comment savoir si un obstacle est entré en collision avec le joueur? Que se passe-t-il lorsque l’obstacle s’envole de l’écran? Et si vous voulez dessiner des images d’arrière-plan qui bougent également? Et si vous voulez que vos images soient animées? Vous pouvez gérer toutes ces situations et bien plus avec sprites.

En termes de programmation, un sprite est une représentation 2D de quelque chose à l’écran. C’est essentiellement une image. + pygame + fournit une https://www.pygame.org/docs/ref/sprite.html [+ classe Sprite +], qui est conçue pour contenir une ou plusieurs représentations graphiques de tout objet de jeu que vous souhaitez afficher sur l’écran. Pour l’utiliser, vous créez une nouvelle classe qui étend + Sprite +. Cela vous permet d’utiliser ses méthodes intégrées.

Joueurs

Voici comment vous utilisez les objets + Sprite + avec le jeu en cours pour définir le joueur. Insérez ce code après la ligne 18:

20 # Define a Player object by extending pygame.sprite.Sprite
21 # The surface drawn on the screen is now an attribute of 'player'
22 class Player(pygame.sprite.Sprite):
23     def __init__(self):
24         super(Player, self).__init__()
25         self.surf = pygame.Surface((75, 25))
26         self.surf.fill((255, 255, 255))
27         self.rect = self.surf.get_rect()

Vous définissez d’abord + Player + en étendant + pygame.sprite.Sprite + à la ligne 22. Ensuite, + . init () + utilise + .super () + pour appeler la méthode + . init () + de + Sprite +. Pour plus d’informations sur la raison pour laquelle cela est nécessaire, vous pouvez lire Supercharger vos classes avec Python super ().

Ensuite, vous définissez et initialisez + .surf + pour maintenir l’image à afficher, qui est actuellement une boîte blanche. Vous définissez et initialisez également `+ .rect + ', que vous utiliserez pour dessiner le joueur plus tard. Pour utiliser cette nouvelle classe, vous devez créer un nouvel objet et modifier également le code de dessin. Développez le bloc de code ci-dessous pour tout voir ensemble:

Exécutez ce code. Vous verrez un rectangle blanc à peu près au milieu de l’écran:

Le sprite du joueur dessiné, largeur = 888, hauteur = 737]]

Que pensez-vous qu’il se passerait si vous changiez la ligne 59 en `+ screen.blit (player.surf, player.rect) + '? Essayez-le et voyez:

55 # Fill the screen with black
56 screen.fill((0, 0, 0))
57
58 # Draw the player on the screen
59 screen.blit(player.surf, player.rect)
60
61 # Update the display
62 pygame.display.flip()

Lorsque vous passez un + Rect + à + ​​.blit () +, il utilise les coordonnées du coin supérieur gauche pour dessiner la surface. Vous l’utiliserez plus tard pour faire bouger votre joueur!

Entrée utilisateur

Jusqu’à présent, vous avez appris à configurer + pygame + et à dessiner des objets sur l’écran. Maintenant, le vrai plaisir commence! Vous rendrez le lecteur contrôlable à l’aide du clavier.

Plus tôt, vous avez vu que + pygame.event.get () + renvoie une liste des événements dans la file d’attente d’événements, que vous recherchez pour les types d’événements + KEYDOWN +. Eh bien, ce n’est pas la seule façon de lire les touches. + pygame + fournit également + pygame.event.get_pressed () +, qui renvoie un dictionary contenant tous les événements `+ KEYDOWN + 'en cours dans la file d’attente.

Mettez cela dans votre boucle de jeu juste après la boucle de gestion des événements. Cela renvoie un dictionnaire contenant les touches enfoncées au début de chaque image:

54 # Get the set of keys pressed and check for user input
55 pressed_keys = pygame.key.get_pressed()

Ensuite, vous écrivez une méthode dans + Player + pour accepter ce dictionnaire. Cela définira le comportement de l’image-objet en fonction des touches enfoncées. Voici à quoi cela pourrait ressembler:

29 # Move the sprite based on user keypresses
30 def update(self, pressed_keys):
31     if pressed_keys[K_UP]:
32         self.rect.move_ip(0, -5)
33     if pressed_keys[K_DOWN]:
34         self.rect.move_ip(0, 5)
35     if pressed_keys[K_LEFT]:
36         self.rect.move_ip(-5, 0)
37     if pressed_keys[K_RIGHT]:
38         self.rect.move_ip(5, 0)

+ K_UP +, + K_DOWN +, + K_LEFT + et + K_RIGHT + correspondent aux touches fléchées du clavier. Si l’entrée de dictionnaire pour cette clé est + True +, alors cette clé est enfoncée et vous déplacez le lecteur + .rect + dans la bonne direction. Ici, vous utilisez + .move_ip () +, qui signifie *move in place *, pour déplacer le courant + Rect +.

Ensuite, vous pouvez appeler + .update () + à chaque image pour déplacer l’image-objet du joueur en réponse aux pressions sur les touches. Ajoutez cet appel juste après l’appel à + ​​.get_pressed () +:

52 # Main loop
53 while running:
54     # for loop through the event queue
55     for event in pygame.event.get():
56         # Check for KEYDOWN event
57         if event.type == KEYDOWN:
58             # If the Esc key is pressed, then exit the main loop
59             if event.key == K_ESCAPE:
60                 running = False
61         # Check for QUIT event. If QUIT, then set running to false.
62         elif event.type == QUIT:
63             running = False
64
65     # Get all the keys currently pressed
66     pressed_keys = pygame.key.get_pressed()
67
68     # Update the player sprite based on user keypresses
69     player.update(pressed_keys)
70
71     # Fill the screen with black
72     screen.fill((0, 0, 0))

Vous pouvez maintenant déplacer le rectangle de votre joueur sur l’écran avec les touches fléchées:

Vous pouvez remarquer deux petits problèmes:

  1. Le rectangle du joueur peut se déplacer très rapidement si une touche est maintenue enfoncée. Vous y travaillerez plus tard.

  2. Le rectangle du joueur peut sortir de l’écran. Résolvons celui-là maintenant.

Pour garder le lecteur sur l’écran, vous devez ajouter un peu de logique pour détecter si le `+ rect + 'va sortir de l’écran. Pour ce faire, vous vérifiez si les coordonnées "+ rect +" se sont déplacées au-delà des limites de l’écran. Si c’est le cas, vous demandez au programme de le déplacer vers le bord:

25 # Move the sprite based on user keypresses
26 def update(self, pressed_keys):
27     if pressed_keys[K_UP]:
28         self.rect.move_ip(0, -5)
29     if pressed_keys[K_DOWN]:
30         self.rect.move_ip(0, 5)
31     if pressed_keys[K_LEFT]:
32         self.rect.move_ip(-5, 0)
33     if pressed_keys[K_RIGHT]:
34         self.rect.move_ip(5, 0)
35
36     # Keep player on the screen
37     if self.rect.left < 0:
38         self.rect.left = 0
39     if self.rect.right > SCREEN_WIDTH:
40         self.rect.right = SCREEN_WIDTH
41     if self.rect.top <= 0:
42         self.rect.top = 0
43     if self.rect.bottom >= SCREEN_HEIGHT:
44         self.rect.bottom = SCREEN_HEIGHT

Ici, au lieu d’utiliser + .move () +, vous modifiez simplement les coordonnées correspondantes de + .top +, + .bottom +, + .left + ou + .right + directement. Testez cela et vous constaterez que le rectangle du lecteur ne peut plus sortir de l’écran.

Ajoutons maintenant quelques ennemis!

Ennemis

Qu’est-ce qu’un jeu sans ennemis? Vous utiliserez les techniques que vous avez déjà apprises pour créer une classe ennemie de base, puis en créer beaucoup pour que votre joueur l’évite. Tout d’abord, importez la bibliothèque + random +:

 4 # Import random for random numbers
 5 import random

Créez ensuite une nouvelle classe de sprites appelée + Enemy +, en suivant le même modèle que vous avez utilisé pour + Player +:

55 # Define the enemy object by extending pygame.sprite.Sprite
56 # The surface you draw on the screen is now an attribute of 'enemy'
57 class Enemy(pygame.sprite.Sprite):
58     def __init__(self):
59         super(Enemy, self).__init__()
60         self.surf = pygame.Surface((20, 10))
61         self.surf.fill((255, 255, 255))
62         self.rect = self.surf.get_rect(
63             center=(
64                 random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
65                 random.randint(0, SCREEN_HEIGHT),
66             )
67         )
68         self.speed = random.randint(5, 20)
69
70     # Move the sprite based on speed
71     # Remove the sprite when it passes the left edge of the screen
72     def update(self):
73         self.rect.move_ip(-self.speed, 0)
74         if self.rect.right < 0:
75             self.kill()

Il existe quatre différences notables entre + Enemy + et + Player +:

  1. Sur les lignes 62 à 67 , vous mettez à jour + rect + pour être un emplacement aléatoire le long du bord droit de l’écran. Le centre du rectangle est juste à côté de l’écran. Il est situé à une position située entre 20 et 100 pixels du bord droit et quelque part entre les bords supérieur et inférieur.

  2. À la ligne 68 , vous définissez + .speed + comme un nombre aléatoire entre 5 et 20. Ceci spécifie la vitesse à laquelle cet ennemi se déplace vers le joueur.

  3. Aux lignes 73 à 76 , vous définissez + .update () +. Cela ne prend aucun argument puisque les ennemis se déplacent automatiquement. Au lieu de cela, + .update () + déplace l’ennemi vers le côté gauche de l’écran à la + .speed + définie lors de sa création.

  4. A la ligne 74 , vous vérifiez si l’ennemi s’est déplacé hors écran. Pour vous assurer que le «+ ennemi » est complètement hors de l'écran et ne disparaîtra pas tant qu'il est encore visible, vous vérifiez que le côté droit du « .rect » a dépassé le côté gauche de l'écran. Une fois que l'ennemi est hors écran, vous appelez ` .kill () +` pour l’empêcher d’être traité plus avant.

Alors, que fait + .kill () +? Pour comprendre cela, vous devez connaître les groupes de sprites .

Groupes de sprites

Une autre classe super utile fournie par + pygame + est +Sprite Group + `. Il s’agit d’un objet qui contient un groupe d’objets `+ Sprite +