python pour débutant
- Test & Code Podcast déplacé à testandcode.com
- Comment utiliser np.arange () – Real Python
- Réflexions sur l'édition collaborative dans WordPress • WPShout
- Épisode 143 Optimisation des performances de l'application Web Python
- Explorer le clustering K-means et créer un carnet de notes avec des pandas – Le vrai podcast Python
Lorsque j'ai commencé à apprendre la programmation informatique à la fin du dernier millénaire, cela tenait à 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 comme ça que j’ai découvert pygame
et appris à l'utiliser pour écrire des jeux et d'autres programmes graphiques. À l'époque, je voulais vraiment un livre d'introduction sur pygame
.
À la fin de cet article, vous pourrez:
- Dessiner des objets sur votre écran
- Jouer des effets sonores et de la musique
- Gérer les entrées de l'utilisateur
- Implémenter des boucles d'événements
- Décrire en quoi la programmation de jeux diffère de la programmation Python procédurale standard
Cette introduction suppose que vous maîtrisez les bases de l’écriture de programmes Python, y compris les fonctions définies par l’utilisateur, les importations, les boucles et les conditions. Vous devez également savoir comment ouvrir des fichiers sur votre plate-forme. Une compréhension de base de 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 dans cet article à suivre:
Contexte et configuration
pygame
est un wrapper Python pour la bibliothèque SDL, qui signifie Couche DirectMedia simple. SDL fournit un accès multiplate-forme aux composants matériels multimédia sous-jacents de votre système, tels que le son, la vidéo, la souris, le clavier et la manette de jeu. pygame
a commencé sa vie en remplacement du projet bloqué PySDL. La nature multiplate-forme de SDL et de pygame
signifie que vous pouvez écrire des jeux et des programmes multimédia riches en Python pour chaque plate-forme qui les prend en charge!
À installer pygame
sur votre plate-forme, utilisez le pépin
commander:
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 guide de mise en route décrit certains problèmes connus et certaines mises en garde concernant toutes les plateformes.
Programme PyGame de base
Avant de passer aux détails, jetons un coup d’œil à un pygame
programme. Ce programme crée une fenêtre, remplit l’arrière-plan de blanc et trace un cercle bleu au milieu:
1 # Programme simple pygame
2
3 # Importer et initialiser la bibliothèque pygame
4 importation pygame
5 pygame.init()
6
sept # Configurer la fenêtre de dessin
8 écran = pygame.afficher.mode réglages([[[[500, 500])
9
dix # Exécuter jusqu'à ce que l'utilisateur demande à quitter
11 fonctionnement = Vrai
12 tandis que fonctionnement:
13
14 # L'utilisateur at-il cliqué sur le bouton de fermeture de la fenêtre?
15 pour un événement dans pygame.un événement.obtenir():
16 si un événement.type == pygame.QUITTER:
17 fonctionnement = Faux
18
19 # Remplir le fond avec du blanc
20 écran.remplir((255, 255, 255))
21
22 # Dessine un cercle bleu uni au centre
23 pygame.dessiner.cercle(écran, (0, 0, 255), (250, 250), 75)
24
25 # Retournez l'écran
26 pygame.afficher.retourner()
27
28 # Terminé! Il est temps d'arrêter.
29 pygame.quitter()
Lorsque vous exécutez ce programme, vous verrez une fenêtre qui ressemble à ceci:
Découpons ce code section par section:
-
Lignes 4 et 5 importer et initialiser le
pygame
bibliothèque. Sans ces lignes, il n'y a pas depygame
. -
Ligne 8 configure la fenêtre d’affichage de votre programme. Vous fournissez une liste ou un tuple spécifiant la largeur et la hauteur de la fenêtre à créer. Ce programme utilise une liste pour créer une fenêtre carrée de 500 pixels de chaque côté.
-
Lignes 11 et 12 mettre en place un boucle de jeu pour contrôler quand le programme se termine. Vous couvrirez les boucles de jeu plus tard dans ce tutoriel.
-
Lignes 15 à 17 numériser et manipuler événements dans la boucle de jeu. Vous pourrez aussi assister aux événements un peu plus tard. Dans ce cas, le seul événement traité est
pygame.QUIT
, qui se produit lorsque l’utilisateur clique sur le bouton de fermeture de la fenêtre. -
Ligne 20 remplit la fenêtre d'une couleur unie.
screen.fill ()
accepte une liste ou un tuple spécifiant les valeurs RVB de la couleur. Puisque(255, 255, 255)
a été fourni, la fenêtre est remplie de blanc. -
Ligne 23 dessine 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 du centre du cercle75
: le rayon du cercle à dessiner en pixels
-
Ligne 26 met à jour le contenu de l'affichage à l'écran. Sans cet appel, rien ne s'affiche dans la fenêtre!
-
Ligne 29 sorties
pygame
. Cela ne se produit qu'une fois la boucle terminée.
C'est le pygame
version de «Hello, World». Maintenant, approfondissons un peu les concepts derrière ce code.
Concepts PyGame
Comme pygame
et la bibliothèque SDL sont portables sur différentes plates-formes et périphériques. Elles doivent toutes deux définir et utiliser des abstractions pour différentes réalités matérielles. Comprendre ces concepts et ces abstractions vous aidera à concevoir et à développer vos propres jeux.
Initialisation et Modules
le pygame
La bibliothèque est composée d’un certain nombre de constructions Python, qui incluent plusieurs modules. Ces modules fournissent un accès abstrait à un matériel spécifique de votre système, ainsi que des méthodes uniformes d'utilisation de ce matériel. Par exemple, afficher
permet un accès uniforme à votre affichage vidéo, tout en manette
permet un contrôle abstrait de votre joystick.
Après avoir importé le pygame
bibliothèque dans l'exemple ci-dessus, la première chose que vous avez faite a été d'initialiser PyGame en utilisant pygame.init ()
. Cette fonction appelle le séparé init ()
fonctions de tous les inclus pygame
modules. Étant donné que ces modules sont des abstractions pour du matériel spécifique, cette étape d'initialisation est nécessaire pour que vous puissiez utiliser le même code sous Linux, Windows et Mac.
Affichages et surfaces
En plus des modules, pygame
comprend également plusieurs Python Des classes, qui encapsule des concepts non dépendants du matériel. L'un d'entre eux est le Surface
qui, à la base, définit une zone rectangulaire sur laquelle vous pouvez dessiner. Surface
les objets sont utilisés dans de nombreux contextes pygame
. Plus tard, vous verrez comment charger une image dans un Surface
et l'afficher à l'écran.
Dans pygame
, tout est visualisé sur un seul utilisateur créé afficher
, qui peut être une fenêtre ou un plein écran. L’affichage est créé avec .mode réglages()
, qui retourne un Surface
représentant la partie visible de la fenêtre. C'est ça Surface
que vous passez dans des fonctions de dessin comme pygame.draw.circle ()
et le contenu de cette Surface
sont poussés à l'écran lorsque vous appelez pygame.display.flip ()
.
Images et Rects
Votre base pygame
programme a dessiné une forme directement sur le Surface
, mais vous pouvez également utiliser des images sur le disque. le image
Ce module vous permet de charger et d’enregistrer des images dans divers formats populaires. Les images sont chargées dans Surface
objets, qui peuvent ensuite être manipulés et affichés de nombreuses façons.
Comme mentionné ci-dessus, Surface
les objets sont représentés par des rectangles, comme de nombreux autres objets pygame
, tels que des images et des fenêtres. Les rectangles sont tellement utilisés qu’il existe une spéciale Rect
classe juste pour les manipuler. Vous utiliserez Rect
des objets et des images dans votre jeu pour attirer les joueurs et les ennemis, et pour gérer les collisions entre eux.
Ok, c’est assez de théorie. Créons et écrivons un jeu!
Conception du jeu de base
Avant de commencer à écrire du code, il est toujours judicieux d’avoir une conception en place. Comme il s’agit d’un didacticiel, concevons également un gameplay de base:
- Le but du jeu est d'éviter les obstacles entrants:
- Le joueur commence sur le côté gauche de l'écran.
- Les obstacles entrent au hasard de la droite et se déplacent à gauche en ligne droite.
- Le joueur peut se déplacer à gauche, à droite, en haut ou en bas pour éviter les obstacles.
- Le joueur ne peut pas quitter l'écran.
- Le jeu se termine lorsque le joueur est heurté par un obstacle ou lorsque l'utilisateur ferme la fenêtre.
Quand il décrivait des projets logiciels, un ancien de mes collègues disait: «Vous ne savez pas ce que vous faites avant de savoir ce que vous ne faites pas.» Dans cet esprit, voici certaines choses qui ne seront pas couvert dans ce tutoriel:
- Pas de vies multiples
- Pas de notation
- Aucune capacité d'attaque de joueur
- Aucun niveau avancé
- Pas de boss
Vous êtes libre d'essayer d'ajouter ces fonctionnalités, ainsi que d'autres, à votre propre programme.
Commençons!
Importation et initialisation de PyGame
Après avoir importé pygame
, vous devrez également l’initialiser. Ceci permet pygame
pour connecter ses abstractions à votre matériel spécifique:
1 # Importer le module pygame
2 importation pygame
3
4 # Importez pygame.locals pour un accès plus facile aux coordonnées de clé
5 # Mis à jour pour se conformer aux normes flake8 et black
6 de pygame.locals importation (
sept K_UP,
8 K_DOWN,
9 K_LEFT,
dix K_RIGHT,
11 K_ESCAPE,
12 TOUCHE BAS,
13 QUITTER,
14 )
15
16 # Initialize pygame
17 pygame.init()
le pygame
La bibliothèque définit beaucoup de choses en plus des modules et des classes. Il définit également certaines constantes locales pour des éléments tels que 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.
. En important des constantes spécifiques de pygame.locals
, vous pouvez utiliser la syntaxe
au lieu. Cela vous évitera des frappes au clavier et améliorera la lisibilité globale.
Configuration de l'affichage
Maintenant vous avez besoin de quelque chose Créez un écran pour qu'il soit la toile globale:
1 # Importer le module pygame
2 importation pygame
3
4 # Importez pygame.locals pour un accès plus facile aux coordonnées de clé
5 # Mis à jour pour se conformer aux normes flake8 et black
6 de pygame.locals importation (
sept K_UP,
8 K_DOWN,
9 K_LEFT,
dix K_RIGHT,
11 K_ESCAPE,
12 TOUCHE BAS,
13 QUITTER,
14 )
15
16 # Initialize pygame
17 pygame.init()
18
19 # Définir des constantes pour la largeur et la hauteur de l'écran
20 SCREEN_WIDTH = 800
21 SCREEN_HEIGHT = 600
22
23 # Créer l'objet d'écran
24 # La taille est déterminée par les constantes SCREEN_WIDTH et SCREEN_HEIGHT.
25 écran = pygame.afficher.mode réglages((SCREEN_WIDTH, SCREEN_HEIGHT))
Vous créez l'écran à utiliser en appelant pygame.display.set_mode ()
et passer un tuple ou une liste avec la largeur et la hauteur désirées. Dans ce cas, la fenêtre est 800×600, telle que définie par les constantes SCREEN_WIDTH
et SCREEN_HEIGHT
sur les lignes 20 et 21. Ceci retourne un Surface
qui représente les dimensions intérieures de la fenêtre. C'est 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 s’ouvrira brièvement, puis disparaîtra immédiatement à la fermeture du programme. Ne clignez pas des yeux ou vous risquez de le manquer! Dans la section suivante, vous allez vous concentrer sur la boucle de jeu principale pour vous assurer que votre programme ne se ferme que lorsque la saisie est correcte.
Mise en place de la boucle de jeu
Chaque jeu, de Pong à Fortnite, utilise une boucle de jeu pour contrôler le jeu. La boucle de jeu fait quatre choses très importantes:
- Traite la saisie de l'utilisateur
- Met à jour l'état de tous les objets du jeu
- Met à jour l'affichage et la sortie audio
- Maintient la vitesse du jeu
Chaque cycle de la boucle de jeu est appelé un Cadre, et plus vite vous pourrez faire les choses à chaque cycle, plus votre jeu sera rapide. Les cadres continuent de se produire jusqu'à ce qu'une condition de sortie du jeu soit remplie. Dans votre conception, deux conditions peuvent terminer la boucle de jeu:
- Le joueur se heurte à un obstacle. (Vous couvrirez la détection de collision plus tard.)
- Le joueur ferme la fenêtre.
La première chose que fait la boucle de jeu est de traiter les entrées de l’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. Vous faites cela en utilisant le pygame
système d'événements.
É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 des informations. Toutes les entrées utilisateur ont pour résultat la génération d’un événement. Les événements peuvent survenir à tout moment et ont souvent (mais pas toujours) leur origine en dehors du programme. Tous les événements dans pygame
sont placés dans la file d’événements, qui peut ensuite être consultée et manipulée. Traiter des événements est appelé manipulation eux, et le code pour le faire est appelé un gestionnaire d'événements.
Chaque événement dans pygame
a un événement type associé avec. Pour votre jeu, les types d’événements sur lesquels vous allez vous concentrer sont les appuis sur les touches et la fermeture des fenêtres. Les événements Keypress ont le type d'événement TOUCHE BAS
, et l'événement de fermeture de la fenêtre a le type QUITTER
. Différents types d'événements peuvent également être associés à d'autres données. Par exemple, le TOUCHE BAS
type d'événement a également une variable appelée clé
pour indiquer quelle touche a été appuyée.
Vous accédez à la liste de tous les événements actifs de 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 pour maintenir la boucle principale active
28 fonctionnement = Vrai
29
30 # Boucle principale
31 tandis que fonctionnement:
32 # Regardez chaque événement dans la file d'attente
33 pour un événement dans pygame.un événement.obtenir():
34 # L'utilisateur a-t-il appuyé sur une touche?
35 si un événement.type == TOUCHE BAS:
36 # Était-ce la touche d'échappement? Si oui, arrêtez la boucle.
37 si un événement.clé == K_ESCAPE:
38 fonctionnement = Faux
39
40 # L'utilisateur at-il cliqué sur le bouton de fermeture de la fenêtre? Si oui, arrêtez la boucle.
41 elif un événement.type == QUITTER:
42 fonctionnement = Faux
Examinons de plus près cette boucle de jeu:
-
Ligne 28 configure une variable de contrôle pour la boucle de jeu. Pour sortir de la boucle et du jeu, vous définissez
en cours d'exécution = False
. La boucle de jeu commence à la ligne 29. -
Ligne 31 démarre le gestionnaire d'événements en parcourant tous les événements actuellement dans la file d'attente. En l’absence d’événements, la liste est vide et le gestionnaire ne fait rien.
-
Lignes 35 à 38 vérifier si le courant
type d'événement
est unTOUCHE BAS
un événement. Si tel est le cas, le programme vérifie quelle touche a été actionnée en regardant leevent.key
attribut. Si la clé est la Esc touche, indiquée parK_ESCAPE
puis quitte la boucle de jeu en réglanten cours d'exécution = False
. -
Lignes 41 et 42 faire une vérification similaire pour le type d'événement appelé
QUITTER
. Cet événement ne se produit que 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 que vous l'exécutez, une fenêtre apparaît avec un écran vide ou noir:
La fenêtre ne disparaît que lorsque vous appuyez sur le bouton Esc clé, ou autrement déclencher une QUITTER
événement en fermant la fenêtre.
Dessin sur l'écran
Dans l'exemple de programme, vous avez dessiné sur l'écran à l'aide de deux commandes:
screen.fill ()
pour remplir le fondpygame.draw.circle ()
dessiner un cercle
Vous allez maintenant découvrir une troisième façon de dessiner à l’écran: utiliser un Surface
.
Rappelons qu'un Surface
est un objet rectangulaire sur lequel vous pouvez dessiner, comme une feuille de papier vierge. le écran
objet est un Surface
, et vous pouvez créer votre propre Surface
objets séparés de l'écran d'affichage. Voyons comment cela fonctionne:
44 # Remplir l'écran avec du blanc
45 écran.remplir((255, 255, 255))
46
47 # Créer une surface et passer dans un tuple contenant sa longueur et sa largeur
48 le surf = pygame.Surface((50, 50))
49
50 # Donne une couleur à la surface pour la séparer de l'arrière-plan
51 le surf.remplir((0, 0, 0))
52 rect = le surf.get_rect()
Une fois l’écran blanc rempli à la ligne 45, un nouveau Surface
est créé à la ligne 48. Cette Surface
50 pixels de large, 50 pixels de haut, et affecté à le surf
. À ce stade, vous le traitez comme le écran
. Alors en ligne, vous le remplissez de noir. Vous pouvez également accéder à son sous-jacent Rect
en utilisant .get_rect ()
. Ceci est stocké comme rect
pour une utilisation ultérieure.
En utilisant .blit ()
et .flip ()
Je viens de créer un nouveau Surface
n’est pas suffisant pour le voir à l’écran. Pour ce faire, vous devez éviter les Surface
sur un autre Surface
. Le terme blit
représente Bloc de transfert, et .blit ()
comment vous copiez le contenu d’un Surface
à un autre. Vous pouvez seulement .blit ()
D'un Surface
à un autre, mais puisque l'écran n'est qu'un autre Surface
, ce n'est pas un problème. Voici comment vous dessinez le surf
sur l'écran:
54 # Cette ligne dit "Dessine le surf sur l'écran au centre"
55 écran.blit(le surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
56 pygame.afficher.retourner()
le .blit ()
L’appel à la ligne 55 prend deux arguments:
- le
Surface
dessiner - L'emplacement où le dessiner sur la source
Surface
Les coordonnées (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)
dire à votre programme de placer le surf
exactement au centre de l’écran, mais cela ne ressemble pas vraiment à ça:
La raison pour laquelle l’image est décentrée, c’est que .blit ()
met le coin supérieur gauche de le surf
à l'emplacement indiqué. Si tu veux le surf
pour être centré, vous devrez faire des calculs pour le déplacer vers le haut et vers la gauche. Vous pouvez le faire en soustrayant la largeur et la hauteur de le surf
à partir de la largeur et de la hauteur de l'écran, en les divisant par 2 pour localiser le centre, puis en transmettant ces nombres comme arguments à screen.blit ()
:
54 # Placez le centre de surf au centre de l'écran
55 surf_center = (
56 (SCREEN_WIDTH-le surf.get_width())/2,
57 (SCREEN_HEIGHT-le surf.get_height())/2
58 )
59
60 # Dessine le surf aux nouvelles coordonnées
61 écran.blit(le surf, surf_center)
62 pygame.afficher.retourner()
Remarquez l'appel à pygame.display.flip ()
après l'appel à blit ()
. Ceci met à jour l’ensemble de l’écran avec tout ce qui a été dessiné depuis le dernier retournement. Sans l'appel à .flip ()
, rien n'est montré.
Sprites
Dans votre conception de jeu, le joueur commence à gauche et les obstacles arrivent par la droite. Vous pouvez représenter tous les obstacles avec Surface
objets 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 aussi? Et si vous voulez que vos images soient animées? Vous pouvez gérer toutes ces situations et plus avec des sprites.
En termes de programmation, un lutin est une représentation 2D de quelque chose à l'écran. En gros, c’est une image. pygame
fournit un Lutin
classe, conçue pour contenir une ou plusieurs représentations graphiques de tout objet du jeu que vous souhaitez afficher à l'écran. Pour l'utiliser, vous créez une nouvelle classe qui s'étend Lutin
. Cela vous permet d'utiliser ses méthodes intégrées.
Joueurs
Voici comment vous utilisez Lutin
objets avec le jeu en cours pour définir le joueur. Insérer ce code après la ligne 18:
20 # Définir un objet Player en étendant pygame.sprite.Sprite
21 # La surface dessinée à l'écran est maintenant un attribut de 'joueur'
22 classe Joueur(pygame.lutin.Lutin):
23 def __init__(soi):
24 super(Joueur, soi).__init__()
25 soi.le surf = pygame.Surface((75, 25))
26 soi.le surf.remplir((255, 255, 255))
27 soi.rect = soi.le surf.get_rect()
Vous définissez d'abord Joueur
en étendant pygame.sprite.Sprite
à la ligne 22. Ensuite .__ init __ ()
les usages .super()
appeler le .__ init __ ()
méthode de Lutin
. Pour plus d'informations sur les raisons pour lesquelles cela est nécessaire, lisez Supercharge Your Classes With Python super ().
Ensuite, vous définissez et initialisez .le surf
pour tenir l'image à afficher, qui est actuellement une case 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:
1 # Importer le module pygame
2 importation pygame
3
4 # Importez pygame.locals pour un accès plus facile aux coordonnées de clé
5 # Mis à jour pour se conformer aux normes flake8 et black
6 de pygame.locals importation (
sept K_UP,
8 K_DOWN,
9 K_LEFT,
dix K_RIGHT,
11 K_ESCAPE,
12 TOUCHE BAS,
13 QUITTER,
14 )
15
16 # Définir des constantes pour la largeur et la hauteur de l'écran
17 SCREEN_WIDTH = 800
18 SCREEN_HEIGHT = 600
19
20 # Définir un objet joueur en étendant pygame.sprite.Sprite
21 # La surface dessinée à l'écran est maintenant un attribut de 'joueur'
22 classe Joueur(pygame.lutin.Lutin):
23 def __init__(soi):
24 super(Joueur, soi).__init__()
25 soi.le surf = pygame.Surface((75, 25))
26 soi.le surf.remplir((255, 255, 255))
27 soi.rect = soi.le surf.get_rect()
28
29 # Initialize pygame
30 pygame.init()
31
32 # Créer l'objet d'écran
33 # La taille est déterminée par les constantes SCREEN_WIDTH et SCREEN_HEIGHT.
34 écran = pygame.afficher.mode réglages((SCREEN_WIDTH, SCREEN_HEIGHT))
35
36 # Instancier le joueur. Pour l'instant, ce n'est qu'un rectangle.
37 joueur = Joueur()
38
39 # Variable pour maintenir la boucle principale active
40 fonctionnement = Vrai
41
42 # Boucle principale
43 tandis que fonctionnement:
44 # pour la boucle dans la file d'attente des événements
45 pour un événement dans pygame.un événement.obtenir():
46 # Vérifier l’événement KEYDOWN
47 si un événement.type == TOUCHE BAS:
48 # Si la touche Esc est enfoncée, quitte la boucle principale
49 si un événement.clé == K_ESCAPE:
50 fonctionnement = Faux
51 # Vérifier l’événement QUIT. Si QUITTER, définissez running sur false.
52 elif un événement.type == QUITTER:
53 fonctionnement = Faux
54
55 # Remplir l'écran avec du noir
56 écran.remplir((0, 0, 0))
57
58 # Dessine le joueur sur l'écran
59 écran.blit(joueur.le surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
60
61 # Mettre à jour l'affichage
62 pygame.afficher.retourner()
Exécutez ce code. Vous verrez un rectangle blanc à peu près au milieu de l'écran:
Que se passerait-il si vous changiez la ligne 59 en screen.blit (player.surf, player.rect)
? Essayez et voyez:
55 # Remplir l'écran avec du noir
56 écran.remplir((0, 0, 0))
57
58 # Dessine le joueur sur l'écran
59 écran.blit(joueur.le surf, joueur.rect)
60
61 # Mettre à jour l'affichage
62 pygame.afficher.retourner()
Quand vous passez un Rect
à .blit ()
, il utilise les coordonnées du coin supérieur gauche pour dessiner la surface. Vous utiliserez cela plus tard pour faire bouger votre joueur!
Entrée utilisateur
Jusqu’à présent, vous avez appris à configurer pygame
et dessinez 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 ça pygame.event.get ()
renvoie une liste des événements dans la file d'événements que vous analysez TOUCHE BAS
types d'événements. Eh bien, ce n’est pas la seule façon de lire les pressions de touche. pygame
fournit également pygame.event.get_pressed ()
, qui retourne un dictionnaire contenant tout le courant TOUCHE BAS
événements dans la file d'attente.
Mettez ceci dans votre boucle de jeu juste après la boucle de gestion d'événement. Ceci retourne un dictionnaire contenant les touches appuyées au début de chaque image:
54 # Obtenir le jeu de touches enfoncé et vérifier la saisie de l'utilisateur
55 touches pressées = pygame.clé.get_pressed()
Ensuite, vous écrivez une méthode dans Joueur
d'accepter ce dictionnaire. Cela définira le comportement de l'image-objet en fonction des touches sur lesquelles vous appuyez. Voici à quoi cela pourrait ressembler:
29 # Déplace l'image-objet en fonction des touches de l'utilisateur
30 def mise à jour(soi, touches pressées):
31 si touches pressées[[[[K_UP]:
32 soi.rect.move_ip(0, -5)
33 si touches pressées[[[[K_DOWN]:
34 soi.rect.move_ip(0, 5)
35 si touches pressées[[[[K_LEFT]:
36 soi.rect.move_ip(-5, 0)
37 si touches pressées[[[[K_RIGHT]:
38 soi.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 du dictionnaire pour cette clé est Vrai
, cette touche est enfoncée et vous déplacez le joueur .rect
dans le bon sens. Ici vous utilisez .move_ip ()
, Qui veut dire se déplacer en place, pour déplacer le courant Rect
.
Ensuite, vous pouvez appeler .mise à jour()
chaque image pour déplacer l’image-joueur en réponse aux pressions sur les touches. Ajouter cet appel juste après l'appel à .get_pressed ()
:
52 # Boucle principale
53 tandis que fonctionnement:
54 # pour la boucle dans la file d'attente des événements
55 pour un événement dans pygame.un événement.obtenir():
56 # Vérifier l’événement KEYDOWN
57 si un événement.type == TOUCHE BAS:
58 # Si la touche Esc est enfoncée, quitte la boucle principale
59 si un événement.clé == K_ESCAPE:
60 fonctionnement = Faux
61 # Vérifier l’événement QUIT. Si QUITTER, définissez running sur false.
62 elif un événement.type == QUITTER:
63 fonctionnement = Faux
64
65 # Obtenir toutes les touches actuellement appuyées
66 touches pressées = pygame.clé.get_pressed()
67
68 # Mettre à jour le sprite du joueur en fonction des touches de l'utilisateur
69 joueur.mise à jour(touches pressées)
70
71 # Remplir l'écran avec du noir
72 écran.remplir((0, 0, 0))
Maintenant, vous pouvez déplacer votre lecteur rectangle autour de l'écran avec les touches fléchées:
Vous remarquerez peut-être deux petits problèmes:
- Le rectangle du joueur peut se déplacer très rapidement si une touche est maintenue enfoncée. Vous travaillerez sur cela plus tard.
- Le rectangle du joueur peut sortir de l'écran. Laissons-le résoudre maintenant.
Pour que le lecteur reste à l'écran, vous devez ajouter une logique pour détecter si le rect
va sortir de l'écran. Pour ce faire, vous vérifiez si le rect
les coordonnées ont dépassé les limites de l’écran. Si tel est le cas, vous demandez au programme de le déplacer vers le bord:
25 # Déplace l'image-objet en fonction des touches de l'utilisateur
26 def mise à jour(soi, touches pressées):
27 si touches pressées[[[[K_UP]:
28 soi.rect.move_ip(0, -5)
29 si touches pressées[[[[K_DOWN]:
30 soi.rect.move_ip(0, 5)
31 si touches pressées[[[[K_LEFT]:
32 soi.rect.move_ip(-5, 0)
33 si touches pressées[[[[K_RIGHT]:
34 soi.rect.move_ip(5, 0)
35
36 # Garder le joueur sur l'écran
37 si soi.rect.la gauche < 0:
38 soi.rect.la gauche = 0
39 si soi.rect.droite > SCREEN_WIDTH:
40 soi.rect.droite = SCREEN_WIDTH
41 si soi.rect.Haut <= 0:
42 soi.rect.Haut = 0
43 si soi.rect.bas > = SCREEN_HEIGHT:
44 soi.rect.bas = SCREEN_HEIGHT
Ici, au lieu d'utiliser .bouge toi()
, il vous suffit de modifier les coordonnées correspondantes de .Haut
, .bas
, .la gauche
, ou .droite
directement. Testez cela et vous constaterez que le rectangle du lecteur ne peut plus quitter 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 vous en créerez beaucoup pour votre joueur. Tout d'abord, importez le Aléatoire
bibliothèque:
4 # Importer au hasard des nombres aléatoires
5 importation Aléatoire
Créez ensuite une nouvelle classe de sprite appelée Ennemi
en suivant le même schéma que vous avez utilisé pour Joueur
:
55 # Définit l'objet ennemi en étendant pygame.sprite.Sprite
56 # La surface que vous dessinez sur l'écran est maintenant un attribut d'ennemi
57 classe Ennemi(pygame.lutin.Lutin):
58 def __init__(soi):
59 super(Ennemi, soi).__init__()
60 soi.le surf = pygame.Surface((20, dix))
61 soi.le surf.remplir((255, 255, 255))
62 soi.rect = soi.le surf.get_rect(
63 centre=(
64 Aléatoire.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
65 Aléatoire.randint(0, SCREEN_HEIGHT),
66 )
67 )
68 soi.la vitesse = Aléatoire.randint(5, 20)
69
70 # Déplace le sprite en fonction de la vitesse
71 # Supprime le sprite quand il passe le bord gauche de l'écran
72 def mise à jour(soi):
73 soi.rect.move_ip(-soi.la vitesse, 0)
74 si soi.rect.droite < 0:
75 soi.tuer()
Il y a quatre différences notables entre Ennemi
et Joueur
:
-
Sur les lignes 62 à 67, vous mettez à jour
rect
être un emplacement aléatoire le long du bord droit de l'écran. Le centre du rectangle est juste en dehors de l'écran. Il est situé entre 20 et 100 pixels du bord droit et entre les bords supérieur et inférieur. -
On line 68, you define
.speed
as a random number between 5 and 20. This specifies how fast this enemy moves towards the player. -
On lines 73 to 76, you define
.update()
. It takes no arguments since enemies move automatically. Instead,.update()
moves the enemy toward the left side of the screen at the.speed
defined when it was created. -
On line 74, you check whether the enemy has moved off-screen. To make sure the
Ennemi
is fully off the screen and won’t just disappear while it’s still visible, you check that the right side of the.rect
has gone past the left side of the screen. Once the enemy is off-screen, you call.kill()
to prevent it from being processed further.
So, what does .kill()
do? To figure this out, you have to know about Sprite Groups.
Sprite Groups
Another super useful class that pygame
provides is the Sprite Group
. This is an object that holds a group of Sprite
objects. So why use it? Can’t you just track your Sprite
objects in a list instead? Well, you can, but the advantage of using a Group
lies in the methods it exposes. These methods help to detect whether any Ennemi
has collided with the Player
, which makes updates much easier.
Let’s see how to create sprite groups. You’ll create two different Group
objects:
- La première
Group
will hold everySprite
in the game. - La deuxième
Group
will hold just theEnnemi
objects.
Here’s what that looks like in code:
82 # Create the 'player'
83 joueur = Player()
84
85 # Create groups to hold enemy sprites and all sprites
86 # - enemies is used for collision detection and position updates
87 # - all_sprites is used for rendering
88 ennemis = pygame.lutin.Group()
89 all_sprites = pygame.lutin.Group()
90 all_sprites.ajouter(joueur)
91
92 # Variable to keep the main loop running
93 fonctionnement = True
When you call .kill()
, le Sprite
is removed from every Group
to which it belongs. This removes the references to the Sprite
as well, which allows Python’s garbage collector to reclaim the memory as necessary.
Now that you have an all_sprites
group, you can change how objects are drawn. Instead of calling .blit()
on just Player
, you can iterate over everything in all_sprites
:
117 # Fill the screen with black
118 écran.remplir((0, 0, 0))
119
120 # Draw all sprites
121 pour entité dans all_sprites:
122 écran.blit(entité.le surf, entité.rect)
123
124 # Flip everything to the display
125 pygame.afficher.flip()
Now, anything put into all_sprites
will be drawn with every frame, whether it’s an enemy or the player.
There’s just one problem… You don’t have any enemies! You could create a bunch of enemies at the beginning of the game, but the game would quickly become boring when they all left the screen a few seconds later. Instead, let’s explore how to keep a steady supply of enemies coming as the game progresses.
Custom Events
The design calls for enemies to appear at regular intervals. This means that at set intervals, you need to do two things:
- Create a new
Ennemi
. - Add it to
all_sprites
etennemis
.
You already have code that handles random events. The event loop is designed to look for random events occurring every frame and deal with them appropriately. Luckily, pygame
doesn’t restrict you to using only the event types it has defined. You can define your own events to handle as you see fit.
Let’s see how to create a custom event that’s generated every few seconds. You can create a custom event by naming it:
78 # Create the screen object
79 # The size is determined by the constant SCREEN_WIDTH and SCREEN_HEIGHT
80 écran = pygame.afficher.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
81
82 # Create a custom event for adding a new enemy
83 ADDENEMY = pygame.USEREVENT + 1
84 pygame.temps.set_timer(ADDENEMY, 250)
85
86 # Instantiate player. Right now, this is just a rectangle.
87 joueur = Player()
pygame
defines events internally as integers, so you need to define a new event with a unique integer. The last event pygame
reserves is called USEREVENT
, so defining ADDENEMY = pygame.USEREVENT + 1
on line 83 ensures it’s unique.
Next, you need to insert this new event into the event queue at regular intervals throughout the game. C’est là que le temps
module comes in. Line 84 fires the new ADDENEMY
event every 250 milliseconds, or four times per second. You call .set_timer()
outside the game loop since you only need one timer, but it will fire throughout the entire game.
Add the code to handle your new event:
100 # Main loop
101 tandis que fonctionnement:
102 # Look at every event in the queue
103 pour un événement dans pygame.un événement.obtenir():
104 # Did the user hit a key?
105 si un événement.type == KEYDOWN:
106 # Was it the Escape key? If so, stop the loop.
107 si un événement.clé == K_ESCAPE:
108 fonctionnement = False
109
110 # Did the user click the window close button? If so, stop the loop.
111 elif un événement.type == QUIT:
112 fonctionnement = False
113
114 # Add a new enemy?
115 elif un événement.type == ADDENEMY:
116 # Create the new enemy and add it to sprite groups
117 new_enemy = Ennemi()
118 ennemis.ajouter(new_enemy)
119 all_sprites.ajouter(new_enemy)
120
121 # Get the set of keys pressed and check for user input
122 pressed_keys = pygame.clé.get_pressed()
123 joueur.mise à jour(pressed_keys)
124
125 # Update enemy position
126 ennemis.mise à jour()
Whenever the event handler sees the new ADDENEMY
event on line 115, it creates an Ennemi
and adds it to ennemis
et all_sprites
. Since Ennemi
est dans all_sprites
, it will get drawn every frame. You also need to call enemies.update()
on line 126, which updates everything in ennemis
, to ensure they move properly:
However, that’s not the only reason there’s a group for just ennemis
.
Collision Detection
Your game design calls for the game to end whenever an enemy collides with the player. Checking for collisions is a basic technique of game programming, and usually requires some non-trivial math to determine whether two sprites will overlap each other.
This is where a framework like pygame
comes in handy! Writing collision detection code is tedious, but pygame
has a LOT of collision detection methods available for you to use.
For this tutorial, you’ll use a method called .spritecollideany()
, which is read as “sprite collide any.” This method accepts a Sprite
et un Group
as parameters. It looks at every object in the Group
and checks if its .rect
intersects with the .rect
du Sprite
. If so, then it returns True
. Otherwise, it returns False
. This is perfect for this game since you need to check if the single joueur
collides with one of a Group
de ennemis
.
Here’s what that looks like in code:
130 # Draw all sprites
131 pour entité dans all_sprites:
132 écran.blit(entité.le surf, entité.rect)
133
134 # Check if any enemies have collided with the player
135 si pygame.lutin.spritecollideany(joueur, ennemis):
136 # If so, then remove the player and stop the loop
137 joueur.tuer()
138 fonctionnement = False
Line 135 tests whether joueur
has collided with any of the objects in ennemis
. If so, then player.kill()
is called to remove it from every group to which it belongs. Since the only objects being rendered are in all_sprites
, le joueur
will no longer be rendered. Once the player has been killed, you need to exit the game as well, so you set running = False
to break out of the game loop on line 138.
At this point, you’ve got the basic elements of a game in place:
Now, let’s dress it up a bit, make it more playable, and add some advanced capabilities to help it stand out.
Sprite Images
Alright, you have a game, but let’s be honest… It’s kind of ugly. The player and enemies are just white blocks on a black background. That was state-of-the-art when Pong was new, but it just doesn’t cut it anymore. Let’s replace all those boring white rectangles with some cooler images that will make the game feel like an actual game.
Earlier, you learned that images on disk can be loaded into a Surface
with some help from the image
module. For this tutorial, we made a little jet for the player and some missiles for the enemies. You’re welcome to use this art, draw your own, or download some free game art assets to use. You can click the link below to download the art used in this tutorial:
Altering the Object Constructors
Before you use images to represent the player and enemy sprites, you need to make some changes to their constructors. The code below replaces the code used previously:
sept # Import pygame.locals for easier access to key coordinates
8 # Updated to conform to flake8 and black standards
9 # from pygame.locals import *
dix de pygame.locals importation (
11 RLEACCEL,
12 K_UP,
13 K_DOWN,
14 K_LEFT,
15 K_RIGHT,
16 K_ESCAPE,
17 KEYDOWN,
18 QUIT,
19 )
20
21 # Define constants for the screen width and height
22 SCREEN_WIDTH = 800
23 SCREEN_HEIGHT = 600
24
25
26 # Define the Player object by extending pygame.sprite.Sprite
27 # Instead of a surface, use an image for a better-looking sprite
28 classe Player(pygame.lutin.Sprite):
29 def __init__(soi):
30 super(Player, soi).__init__()
31 soi.image = pygame.image.charge("jet.png").convertir()
32 soi.image.set_colorkey((255, 255, 255), RLEACCEL)
33 soi.rect = soi.image.get_rect()
Let’s unpack line 31 a bit. pygame.image.load()
loads an image from the disk. You pass it a path to the file. It returns a Surface
, et le .convert()
call optimizes the Surface
, making future .blit()
calls faster.
Line 32 uses .set_colorkey()
to indicate the color pygame
will render as transparent. In this case, you choose white, because that’s the background color of the jet image. The RLEACCEL constant is an optional parameter that helps pygame
render more quickly on non-accelerated displays. This is added to the pygame.locals
import statement on line 11.
Nothing else needs to change. The image is still a Surface
, except now it has a picture painted on it. You still use it in the same way.
Here’s what similar changes to the Ennemi
look like:
59 # Define the enemy object by extending pygame.sprite.Sprite
60 # Instead of a surface, use an image for a better-looking sprite
61 classe Ennemi(pygame.lutin.Sprite):
62 def __init__(soi):
63 super(Ennemi, soi).__init__()
64 soi.le surf = pygame.image.charge("missile.png").convertir()
65 soi.le surf.set_colorkey((255, 255, 255), RLEACCEL)
66 # The starting position is randomly generated, as is the speed
67 soi.rect = soi.le surf.get_rect(
68 centre=(
69 Aléatoire.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
70 Aléatoire.randint(0, SCREEN_HEIGHT),
71 )
72 )
73 soi.la vitesse = Aléatoire.randint(5, 20)
Running the program now should show that this is the same game you had before, except now you’ve added some nice graphics les peaux with images. But why stop at just making the player and enemy sprites look nice? Let’s add a few clouds going past to give the impression of a jet flying through the sky.
Adding Background Images
For background clouds, you use the same principles as you did for Player
et Ennemi
:
- Create the
Cloud
class. - Add an image of a cloud to it.
- Create a method
.update()
that moves thenuage
toward the left side of the screen. - Create a custom event and handler to create new
nuage
objects at a set time interval. - Add the newly created
nuage
objects to a newGroup
appelédes nuages
. - Update and draw the
des nuages
in your game loop.
Here’s what Cloud
looks like:
83 # Define the cloud object by extending pygame.sprite.Sprite
84 # Use an image for a better-looking sprite
85 classe Cloud(pygame.lutin.Sprite):
86 def __init__(soi):
87 super(Cloud, soi).__init__()
88 soi.le surf = pygame.image.charge("cloud.png").convertir()
89 soi.le surf.set_colorkey((0, 0, 0), RLEACCEL)
90 # The starting position is randomly generated
91 soi.rect = soi.le surf.get_rect(
92 centre=(
93 Aléatoire.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
94 Aléatoire.randint(0, SCREEN_HEIGHT),
95 )
96
97 # Move the cloud based on a constant speed
98 # Remove the cloud when it passes the left edge of the screen
99 def mise à jour(soi):
100 soi.rect.move_ip(-5, 0)
101 si soi.rect.droite < 0:
102 soi.tuer()
That should all look very familiar. It’s pretty much the same as Ennemi
.
To have clouds appear at certain intervals, you’ll use event creation code similar to what you used to create new enemies. Put it right below the enemy creation event:
116 # Create custom events for adding a new enemy and a cloud
117 ADDENEMY = pygame.USEREVENT + 1
118 pygame.temps.set_timer(ADDENEMY, 250)
119 ADDCLOUD = pygame.USEREVENT + 2
120 pygame.temps.set_timer(ADDCLOUD, 1000)
This says to wait 1000 milliseconds, or one second, before creating the next nuage
.
Next, create a new Group
to hold each newly created nuage
:
125 # Create groups to hold enemy sprites, cloud sprites, and all sprites
126 # - enemies is used for collision detection and position updates
127 # - clouds is used for position updates
128 # - all_sprites is used for rendering
129 ennemis = pygame.lutin.Group()
130 des nuages = pygame.lutin.Group()
131 all_sprites = pygame.lutin.Group()
132 all_sprites.ajouter(joueur)
Next, add a handler for the new ADDCLOUD
event in the event handler:
137 # Main loop
138 tandis que fonctionnement:
139 # Look at every event in the queue
140 pour un événement dans pygame.un événement.obtenir():
141 # Did the user hit a key?
142 si un événement.type == KEYDOWN:
143 # Was it the Escape key? If so, then stop the loop.
144 si un événement.clé == K_ESCAPE:
145 fonctionnement = False
146
147 # Did the user click the window close button? If so, stop the loop.
148 elif un événement.type == QUIT:
149 fonctionnement = False
150
151 # Add a new enemy?
152 elif un événement.type == ADDENEMY:
153 # Create the new enemy and add it to sprite groups
154 new_enemy = Ennemi()
155 ennemis.ajouter(new_enemy)
156 all_sprites.ajouter(new_enemy)
157
158 # Add a new cloud?
159 elif un événement.type == ADDCLOUD:
160 # Create the new cloud and add it to sprite groups
161 new_cloud = Cloud()
162 des nuages.ajouter(new_cloud)
163 all_sprites.ajouter(new_cloud)
Finally, make sure the des nuages
are updated every frame:
167 # Update the position of enemies and clouds
168 ennemis.mise à jour()
169 des nuages.mise à jour()
170
171 # Fill the screen with sky blue
172 écran.remplir((135, 206, 250))
Line 172 updates the original screen.fill()
to fill the screen with a pleasant sky blue color. You can change this color to something else. Maybe you want an alien world with a purple sky, a toxic wasteland in neon green, or the surface of Mars in red!
Note that each new Cloud
et Ennemi
are added to all_sprites
aussi bien que des nuages
et ennemis
. This is done because each group is used for a separate purpose:
- Rendering is done using
all_sprites
. - Position updates are done using
des nuages
etennemis
. - Collision detection is done using
ennemis
.
You create multiple groups so that you can change the way sprites move or behave without impacting the movement or behavior of other sprites.
Game Speed
While testing the game you may have noticed that the enemies move a little fast. If not, then that’s okay, as different machines will see different results at this point.
The reason for this is that the game loop processes frames as fast as the processor and environment will allow. Since all the sprites move once per frame, they can move hundreds of times each second. The number of frames handled each second is called the cadence, and getting this right is the difference between a playable game and a forgettable one.
Normally, you want as high a frame rate as possible, but for this game, you need to slow it down a bit for the game to be playable. Fortunately, the module temps
contient un L'horloge
which is designed exactly for this purpose.
En utilisant L'horloge
to establish a playable frame rate requires just two lines of code. The first creates a new L'horloge
before the game loop begins:
106 # Setup the clock for a decent framerate
107 l'horloge = pygame.temps.L'horloge()
The second calls .tick()
informer pygame
that the program has reached the end of the frame:
188 # Flip everything to the display
189 pygame.afficher.flip()
190
191 # Ensure program maintains a rate of 30 frames per second
192 l'horloge.tick(30)
The argument passed to .tick()
establishes the desired frame rate. To do this, .tick()
calculates the number of milliseconds each frame should take, based on the desired frame rate. Then, it compares that number to the number of milliseconds that have passed since the last time .tick()
was called. If not enough time has passed, then .tick()
delays processing to ensure that it never exceeds the specified frame rate.
Passing in a smaller frame rate will result in more time in each frame for calculations, while a larger frame rate provides smoother (and possibly faster) gameplay:
Play around with this number to see what feels best for you!
Sound Effects
So far, you’ve focused on gameplay and the visual aspects of your game. Now let’s explore giving your game some auditory flavor as well. pygame
fournit mixer
to handle all sound-related activities. You’ll use this module’s classes and methods to provide background music and sound effects for various actions.
The name mixer
refers to the fact that the module mixes various sounds into a cohesive whole. Using the la musique
sub-module, you can stream individual sound files in a variety of formats, such as MP3, Ogg, and Mod. You can also use Du son
to hold a single sound effect to be played, in either Ogg or uncompressed WAV formats. All playback happens in the background, so when you play a Du son
, the method returns immediately as the sound plays.
Remarque: le pygame
documentation states that MP3 support is limited, and unsupported formats can cause system crashes. The sounds referenced in this article have been tested, and we recommend testing any sounds thoroughly before releasing your game.
As with most things pygame
, using mixer
starts with an initialization step. Luckily, this is already handled by pygame.init()
. You only need to call pygame.mixer.init()
if you want to change the defaults:
106 # Setup for sounds. Defaults are good.
107 pygame.mixer.init()
108
109 # Initialize pygame
110 pygame.init()
111
112 # Set up the clock for a decent framerate
113 l'horloge = pygame.temps.L'horloge()
pygame.mixer.init()
accepts a number of arguments, but the defaults work fine in most cases. Note that if you want to change the defaults, you need to call pygame.mixer.init()
before calling pygame.init()
. Otherwise, the defaults will be in effect regardless of your changes.
After the system is initialized, you can get your sounds and background music setup:
135 # Load and play background music
136 # Sound source: http://ccmixter.org/files/Apoxode/59262
137 # License: https://creativecommons.org/licenses/by/3.0/
138 pygame.mixer.la musique.charge("Apoxode_-_Electric_1.mp3")
139 pygame.mixer.la musique.jouer(boucles=-1)
140
141 # Load all sound files
142 # Sound sources: Jon Fincher
143 move_up_sound = pygame.mixer.Du son("Rising_putter.ogg")
144 move_down_sound = pygame.mixer.Du son("Falling_putter.ogg")
145 collision_sound = pygame.mixer.Du son("Collision.ogg")
Lines 138 and 139 load a background sound clip and begin playing it. You can tell the sound clip to loop and never end by setting the named parameter loops=-1
.
Lines 143 to 145 load three sounds you’ll use for various sound effects. The first two are rising and falling sounds, which are played when the player moves up or down. The last is the sound used whenever there is a collision. You can add other sounds as well, such as a sound for whenever an Ennemi
is created, or a final sound for when the game ends.
So, how do you use the sound effects? You want to play each sound when a certain event occurs. For example, when the ship moves up, you want to play move_up_sound
. Therefore, you add a call to .play()
whenever you handle that event. In the design, that means adding the following calls to .update()
pour Player
:
26 # Define the Player object by extending pygame.sprite.Sprite
27 # Instead of a surface, use an image for a better-looking sprite
28 classe Player(pygame.lutin.Sprite):
29 def __init__(soi):
30 super(Player, soi).__init__()
31 soi.le surf = pygame.image.charge("jet.png").convertir()
32 soi.le surf.set_colorkey((255, 255, 255), RLEACCEL)
33 soi.rect = soi.le surf.get_rect()
34
35 # Move the sprite based on keypresses
36 def mise à jour(soi, pressed_keys):
37 si pressed_keys[[[[K_UP]:
38 soi.rect.move_ip(0, -5)
39 move_up_sound.jouer()
40 si pressed_keys[[[[K_DOWN]:
41 soi.rect.move_ip(0, 5)
42 move_down_sound.jouer()
For a collision between the player and an enemy, you play the sound for when collisions are detected:
201 # Check if any enemies have collided with the player
202 si pygame.lutin.spritecollideany(joueur, ennemis):
203 # If so, then remove the player
204 joueur.tuer()
205
206 # Stop any moving sounds and play the collision sound
207 move_up_sound.Arrêtez()
208 move_down_sound.Arrêtez()
209 collision_sound.jouer()
210
211 # Stop the loop
212 fonctionnement = False
Here, you stop any other sound effects first, because in a collision the player is no longer moving. Then you play the collision sound and continue execution from there.
Finally, when the game is over, all sounds should stop. This is true whether the game ends due to a collision or the user exits manually. To do this, add the following lines at the end of the program after the loop:
220 # All done! Stop and quit the mixer.
221 pygame.mixer.la musique.Arrêtez()
222 pygame.mixer.quitter()
Technically, these last few lines are not required, as the program ends right after this. However, if you decide later on to add an intro screen or an exit screen to your game, then there may be more code running after the game ends.
That’s it! Test it again, and you should see something like this:
A Note on Sources
You may have noticed the comment on lines 136-137 when the background music was loaded, listing the source of the music and a link to the Creative Commons license. This was done because the creator of that sound required it. The license requirements stated that in order to use the sound, both proper attribution and a link to the license must be provided.
Here are some sources for music, sound, and art that you can search for useful content:
As you make your games and use downloaded content such as art, music, or code from other sources, please be sure that you are complying with the licensing terms of those sources.
Conclusion
Throughout this tutorial, you’ve learned how game programming with pygame
differs from standard procedural programming. You’ve also learned how to:
- Implement event loops
- Draw items on the screen
- Play sound effects and music
- Handle user input
To do this, you used a subset of the pygame
modules, including the afficher
, mixer
et la musique
, temps
, image
, un événement
, et clé
modules. You also used several pygame
classes, including Rect
, Surface
, Du son
, et Sprite
. But these only scratch the surface of what pygame
can do! Check out the official pygame
documentation for a full list of available modules and classes.
You can find all of the code, graphics, and sound files for this article by clicking the link below:
Feel free to leave comments below as well. Happy Pythoning!
[ad_2]