TP - Chapitre 5 : Programmation de jeux avec Python

N.B. Niveau : Première Générale, enseignement de spécialité NSI (Numérique et Sciences Informatiques)

Chapitre 5 - Jeux vidéo avec le module Pygame

Python Pygame

Dans le cadre des projets, si vous êtes intéressés par la création de jeux vidéo en 2D, il existe le module Pygame de Python.

Attention : le choix de ce type de projet demande un investissement initial important, et cela ne doit pas empiéter sur les autres disciplines...

Les envahisseurs de l'espace !

Python Pygame

Créer l'image du vaisseau

- Avec Paint ou Photofiltre, créer le sprite du vaisseau avec fond transparent
- Enregistrer le fichier au format png portant le nom vaisseau.png dans un dossier de vos documents où se trouveront tous les fichiers nécessaires au lancement du programme.

Avec photofiltre : Menu fichier - nouveau,
Voici une idée simple de vaisseau :

vaisseau

Faire bouger le vaisseau

#########################################
# Programme écrit par Prénom Nom Classe #
#########################################
import pygame,sys
from pygame.locals import *

pygame.init()
pygame.font.init()
fenetre_jeu=pygame.display.set_mode((450,560)) # Taille fenêtre du jeu en pixels
pygame.display.set_caption('SpaceInvader') # titre de la fenêtre

#############################
# Déclaration des variables #
#############################
Gauche = False
Droite = False
Texty = pygame.font.Font('SUPERPOI_R.TTF', 10)
Obj_texte = Texty.render('les envahisseurs', 0, (0,0,255))
clock = pygame.time.Clock()
vaisseau = pygame.image.load('vaisseau.png')
rectangle_vaisseau = pygame.Rect(20,500,31,32)

#####################################
# Fonction de détection des Touches #
#####################################
def detecte_touches():
""" Cette fonction permet de détecter les touches enfoncées ou relâchées
de quitter le jeu ou de permettre le déplacement du vaisseau"""

global Gauche,Droite

for event in pygame.event.get():
if event.type==QUIT: # Traite l'évènement fermer la fenêtre avec la souris
pygame.quit()
sys.exit()
if event.type== KEYDOWN: # Traiter les évènements du clavier
if event.key==K_ESCAPE:
pygame.quit()
sys.exit()
if event.key==K_RIGHT:
Droite = True
if event.key==K_LEFT:
Gauche = True

if event.type== KEYUP:
if event.key==K_RIGHT:
Droite = False
if event.key==K_LEFT:
Gauche = False

#####################
# BOUCLE PRINCIPALE #
#####################
while True:
fenetre_jeu.fill (0x00001A) # Remplir l'arrieère plan avec la couleur RVB Bleu foncé
fenetre_jeu.blit(Obj_texte,(50,20)) # Placer le texte
fenetre_jeu.blit(vaisseau,rectangle_vaisseau) # placer l'image

detecte_touches()

# Déplacement du vaisseau d'un pixel
if Gauche and rectangle_vaisseau.left > 10 : rectangle_vaisseau.left -= 1
if Droite and rectangle_vaisseau.right < 440 : rectangle_vaisseau.right += 1

pygame.display.update() # rafraichir l'affichage de la fenêtre jeu
clock.tick(30) # Vitesse du jeu : 30 FPS
- Enregistez le programme dans le répertoire du jeu

- Téléchargez la police par un clic droit sur le lien suivant : Police_Superpoi et "enregistrer la cible du lien sous..." dans le répertoire du jeu

- Accélérer le déplacement du vaisseau en augmentant le pas d'incrémentation de plusieurs pixels.

Ajout du lancement des missiles

- Déclarer la variable missiles=[]. Cette varible contiendra une liste des coordonnées des missiles.

- Chaque nouveau missile devra démarrer à la coordonnée x du vaisseau+12 pixels et y du vaisseau.

- Dans la fonction detecte_touches(): ajouter l'agorithme permettant d'ajouter les coordonnées du vaisseau dès que la touche espace est enfoncée.
Si la touche K_SPACE est enfoncée alors 
   ajouter à la liste missiles un nouveau missle
l'ajout d'un missile se fait par la l'instruction : missiles.append(pygame.Rect(rectangle_vaisseau.left+12,rectangle_vaisseau.top,6,16))

- Au-dessus de la boucle principale, ajouter les lignes suivantes :
def deplace_missiles():
""" Cette fonction permet de changer les coordonnées des missiles contenu dans la liste missiles"""
for missile in missiles: # pour chaque missiles existant
missile.top=missile.top-10 # soustraire 10 à la coordonnée du point haut
pygame.draw.rect(fenetre_jeu,0xFF0000,missile) # dessinner un rectangle de couleur rouge
if missile.top<=100: # si le missiles arrive en haut de l'écran
missiles.remove(missile) # supprimer le missiles de la liste

A la fin du programme, avant pygame.display.update(), appeler la fonction deplace_missiles()

Ajout des aliens

- Les coordonnées des aliens seront également représentées par des rectangles, stockés dans une liste nommée aliens.

- Dans la section de déclaration des variables, déclarer la liste vide : aliens=[] 

- Importer la librairie random en début de programme : import random

- Créer la fonction niveau(n) qui génère une liste aléatoire contenant les coordonnées des rectangles.
def niveau(n):
"""Cette fonction génère des coordonnées de retangles aléatoirement"""
if n==1:
for
i in range(100,500,50):
aliens.append(pygame.Rect(i,random.randint(100,200),31,24))

- Avant la boucle principale, appeler la fonction niveau(1)

- Implanter la fonction placer_aliens(), permettant de dessiner des rectangles aliens

def placer_aliens():
"""Cette fonction permet de placer les aliens dans la fenêtre de jeu"""
for alien in aliens:
pygame.draw.rect(fenetre_jeu,0x00FFFF,alien)
- Appeler cette fonction dans la boucle principale avant l'appel de la fonction deplace_missiles().

- Ajouter une fonction permettant de détecter les collisions entre les missiles et les aliens.

- La fonction permettant de détecter la collision d'un missile avec un alien se code : missile.colliderect(alien)

- Pour retirer un alien de la liste des aliens : aliens.remove(alien)

- Vous pouvez imaginer comment retirer un missile de la liste des missiles...

- Codez l'algoritme ci-dessous et placez-le avec les autres fonctions.
déclarer la fonction detecte_collision():
pour chaque missile dans la liste des missiles:
pour chaque alien dans la liste des aliens:
si le missile est en collision avec un alien:
retirer l'alien de la liste des aliens
retirer le missile de la liste des missiles
- Appeler la fonction detect_collision() dans la boucle principale avant le placement des aliens dans de la fenêtre jeu.

Remplacement des rectangles aliens par une image

- Enregistrer l'image suivante Envahisseur dans le répertoire courant. (clic droit sur l'image, puis enregistrer l'image sous...)

- Dans la section de déclaration des varibles, charger l'image dans une varible img_aliens. S'inspirer du chargement de l'image du vaisseau.

- Modifier la fonction placer_aliens comme suit :

def placer_aliens(image):
"""Cette fonction permet de placer les aliens dans la fenêtre de jeu"""
for alien in aliens:
fenetre_jeu.blit(image,alien)
- Dans la boucle pricipale modifier l'appel de la fonction placer_aliens() par placer_aliens(img_aliens)

- Modifier la fonction niveau(n) afin de créer 3 rangées de 6 aliens dans le jeu lorsque n=2. Le pas de l'espacement horizontal et vertical est de 50 pixels.

Algorithme :
définir la fonction niveau(n):
.... code actuel à garder puis à compléter par : ...
si n = 2 alors
pour y variant de 100 à 250 avec un pas de 50
pour x variant de 75 à 300 avec un pas de 50
ajouter à la liste des aliens les coordonnées du rectangle (x,y,31,24)



- Avant la boucle principale, remplacer niveau(1) par niveau(2)

annimation des aliens :

invader1 : alien1   invader2 : alien2

- remplacer
la ligne img_aliens=pygame.image.load('invader1.png') par la ligne suivante :
img_aliens=[pygame.image.load('invader1.png'),pygame.image.load('invader2.png')]
img_alien devient une liste contenant 2 images qu'on peut alterner en fonction du temps. Dans le boucle principale l'appel de la fonction placer_aliens(img_aliens) sera remplacée par le code suivant :
i+=1
placer_aliens(img_aliens[(i//15)%2]) # Changement d'image toutes les 0.5 secondes si FPS=30
- Déclarer et initialiser la variable i=0 en début de programme.

Déplacement des aliens

- Déclarer une variable vitesse = 1

- Coder l'algorithme suivant :
définir la fonction deplace_aliens(x,y):
pour chaque alien dans la liste des aliens
alien.left + = x
alien.top + = y
- Appler cette fonction dans la boucle principale avant de placer les aliens : deplace_aliens(vitesse,0)

Lorsque l'abscisse les coordonnées d'un alien sera > 440 ou < 10 on change le sens de déplacement des aliens

- Coder l'algorithme suivant :
définir la fonction change_sens_aliens():
déclarer la variable globale vitesse
pour chaque alien dans la liste des aliens:
si la coordonnée droite de l'alien > 440 ou si la coordonnée gauche de l'alien < 10
vitesse=-vitesse
déplace aliens (0,10)
stop (break)
- Appeler cette fonction avant la ligne pygame.display.update()

Faire tirer des missiles par les aliens

- Déclarer une variables de type liste missiles_aliens=[]

- Déclarer une variable qui définira aléatoirement le temps de tir d'un alien (0.5 secondes à 2 secondes) : tps_tir_alien =  i + random.randint(15,60)

- Dans la boucle principale implanter l'algorithme suiant :
si tps_tir_alien <= i alors
tps_tir_alien =  i + random.randint(15,60)
ajouter_tir_alien()
- La fonction ajouter_tir_alien() se code de la manière suivante :
def ajouter_tir_alien()
choix=random.choice(aliens)
missiles_aliens.append(pygame.Rect(choix.left+12,choix.bottom,6,16))
- Commenter les lignes du code ci-dessus dans votre porgramme.

- Créer une fonction deplace_missiles_aliens() inspirée de deplace_missiles() permettant de déplacer les missiles des aliens vers le bas et les supprimer si leur ordonnée dépasse 500.

- Reste encore à remplacer le missile par une image, annimer le vaisseau avec 2 images, compter le score, détecter les collision entre le vaisseau et les missibles des aliens, gérer la fin du jeu, ajouter des niveaux ...

- Compresser votre dossier jeu et nommez-le avec votre nom et prénom



- Avant le 6 janvier, envoyer votre dossier compressé à l'adresse suivante : http://phassenforder.free.fr/upload/ ou dans devoir de mon bureau numérique.
Attention, ne m'envoyez pas un programme copié sur Internet avec des classes ... ni un programme que vous ne maîtrisez pas. Il faudra le présenter et l'expliquer à la classe le mercredi 8/01/2020 ou le vendredi 10/01/2020.

Cours sur le module Pygame

Deux ouvrages sur Pygame (pour Python version 3) sont consultables et téléchargeables sur le site de Al Sweigart (en anglais) :

inventwithpython.com
inventwithpython.com/chapters (chapters 17 to 20)
inventwithpython.com/pygame/chapters