Accueil

Traduction

Tutoriel Python - sommaire

Tutoriel Python - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Pygame : formes, textes, sons et souris

Dans ce chapitre je vais présenter les modules draw, font, mixer & mouse qui respectivement gèrent le dessin, le texte, le son et la souris.
Je vais aussi évoquer les transformations d'une image.

La module draw

Le module pygame.draw permet de dessiner des formes géométriques dans la fenêtre de jeu.

Dessiner des formes pleines

#pygame_draw.py
#dessiner des formes pleines avec pygame draw

import pygame 
pygame.init()

blanc =(255,255,255)
rouge = (255, 0, 0)
bleu = (0, 0, 255) 
vert = (0,255,0)
jaune =(255,255,0)
X = 400
Y = 400
dimensions = (X,Y)
cote = 50
rayon = 30
rx = 100
ry =50
points = [(200, 200), (300, 200), (250, 300), (150, 300)] 

 
fenetre = pygame.display.set_mode(dimensions)
pygame.display.set_caption("dessiner des formes")
fenetre.fill(blanc)

rectangle = pygame.draw.rect(fenetre, rouge, (50,50, cote, cote))
cercle = pygame.draw.circle(fenetre,vert, (50,150),rayon)
ellipse =pygame.draw.ellipse(fenetre, bleu, (50,200,rx,ry))
parallelo =pygame.draw.polygon(fenetre,jaune,points)
pygame.draw.lines(fenetre,rouge, False, points)
pygame.display.flip()

print(f"type de rectangle : {type(rectangle)}")
print(f"type de cercle : {type(cercle)}")
print(f"type de ellipse : {type(ellipse)}")
print(f"type de parallelo : {type(parallelo)}")
boucle_jeu = True
#------ boucle de jeu-----
while boucle_jeu :
	for event in pygame.event.get(): 
		if event.type == pygame.QUIT: 
			boucle_jeu = False
# --------------
 

Le rendu

Le graphique

Le shell

Les formes dessinées sont des objets de type rect.
Je n'en dis pas plus pour l'instant mais sachez que la notion d'objet de type rect (instances de la classe Rect()) est très importante.

Dessiner les contours

Dans le script précédent nous avons rempli des formes.
Cette fois je vous montre comment dessiner des contours de formes

Le code

#pygame2_draw2.py
# dessiner contours de formes
import pygame
pygame.init()
cote = 50
rayon = 30
rx = 100
ry =50
points = [(200, 200), (300, 200), (250, 300), (150, 300)] 
 
fenetre = pygame.display.set_mode((400,400))
pygame.display.set_caption('Dessiner des formes')
fenetre.fill('white')
pygame.draw.rect(fenetre, 'red', (50,50, cote, cote),2)
pygame.draw.circle(fenetre,'green', (50,150),rayon,2)
pygame.draw.ellipse(fenetre, 'blue', (50,200,rx,ry),3)
pygame.draw.polygon(fenetre,'yellow',points)
pygame.draw.polygon(fenetre,'orange',points,5)
pygame.display.flip()
 
boucle_jeu = True
#-----------boucle de jeu-------------
while boucle_jeu :
	for event in pygame.event.get(): 
		if event.type == pygame.QUIT: 
			boucle_jeu = False
 
#---------------

Le rendu

Dans ce script je vous indique que vous pouvez utiliser les noms anglais des couleurs plutôt qu'un code RGB.

Notez qu'il y a deux instructions pratiquement identiques (pygame.draw.polygone(...) :

pygame.draw.polygon(fenetre,'yellow',points)
pygame.draw.polygon(fenetre,'orange',points,5)

la première ligne colorie le fond et la deuxième instruction dessine le contour vert de 5 pixels d'épaisseur.
Donc pour dessiner un contour il faut rajouter un paramètre précisant l'épaisseur du contour.
De façon générale, pour dessiner une forme remplie et bordurée il faut deux instructions.

La gestion du texte

Le module font de Pygame permet de créer des textes ; afficher le score obtenu par exemple.

Un texte qui défile verticalement dans la fenêtre

Le texte "Règles du jeu" se déplace de haut en bas puis de bas en haut alternativement sans jamais sortir de la fenêtre.

Le code

#pygame_texte.py
# gestion du texte
import pygame
pygame.init() 
fenetre = pygame.display.set_mode((400,400)) 
pygame.display.set_caption("Le module font") 
style= pygame.font.SysFont("Arial", 35, 1, 1) 
texte = style.render("Règles du jeu", 1, 'navy')
Y =35
delta = 2
clock = pygame.time.Clock()

boucle_jeu = True
# ---------------boucle de jeu---------------
while boucle_jeu :
    
       for event in pygame.event.get(): 
             if event.type == pygame.QUIT: 
                   boucle_jeu = False
       fenetre.fill('skyblue')
       fenetre.blit(texte,(50,Y))
       pygame.display.flip()
       Y+=delta
       if Y>=360:
              delta = -2
       if Y <=40:
              delta = 2
       clock.tick(16)
# ------------------

style= pygame.font.SysFont("Arial", 35, 1, 1) : création d'un style de police "Arial", de taille 35px, gras et italique.
On peut remplacer chaque 1 par True ; deux zéros (ou deux False) pour ni gras, ni italique.

texte = style.render("Règles du jeu", 1, 'navy') : création du texte "Règles du jeu" utilisant le style défini dans la variable style avec l'anticrénelage et couleur de texte 'navy'.
fenetre.blit(texte,(50,Y)) : affichage du texte dans la fenêtre de jeu avec les coordonnées 50,Y
Pour que le texte ne sorte jamais de la fenêtre il faut que delta soit tantôt égal à +2 ou -2 afin que Y soit tantôt incrémenté ou décrémenté de 2.

Le rendu

Notez la FRS (fréquence de rafraichissemen par seconde) qui est de 16.

Gestion du son

Un jeu vidéo c'est en général une ambiance sonore avec des effets sons lors des collisions.
Il faut utiliser le module mixer de pygame pour créer et manipuler des objets audio.

Fond sonore

Je vous propose une animation avec une ambiance sonore : la musique d'Odysée de l'espace.
Vous pouvez diminuer ou augmenter le volume sonore. Vous pouvez aussi mettre fin à l'ambiance sonore.

Le code

# pygame_sons.py
import pygame

# ambiance sonore 
pygame.init() 
pygame.mixer.init() 
fenetre = pygame.display.set_mode((500, 400)) 
fenetre.fill('skyblue') 
style= pygame.font.SysFont("Arial", 20, 0, 0) 
texte1 = style.render \
("Appuyez sur la touche 'space' pour arrêter le fond sonore ", 1, 'navy')
texte2 = style.render \
("Appuyez sur UP pour augmenter le volume ", 1, 'navy')
texte3 = style.render \
("Appuyez sur DOWN pour diminuer le volume ", 1, 'navy')
pygame.display.set_caption("jeu avec son") 
ambiance = pygame.mixer.Sound("images_sons/odyssee.mp3") 
ambiance.play(20) 
fenetre.blit(texte1,(20,50))
fenetre.blit(texte2,(20,100))
fenetre.blit(texte3,(20,150))
pygame.display.flip()

encore = True
#------boucle de jeu---------------
while encore: 
    for event in pygame.event.get(): 
       if event.type == pygame.QUIT: 
           encore = False 
       if event.type == pygame.KEYDOWN: 
            if event.key == pygame.K_DOWN: 
               volume = ambiance.get_volume() - 0.1
               ambiance.set_volume(volume)
               print(volume)
            if event.key == pygame.K_UP: 
               volume = ambiance.get_volume() + 0.1
               ambiance.set_volume(volume)
               print(volume)
            if event.key == pygame.K_SPACE:
               ambiance.stop()
#----------------

Dans la fenêtre on affiche les consignes au joueur sous forme de trois textes.

La fonction init() permet d’initialiser le module mixer. Elle est nécessaire pour pouvoir utiliser le module.
ambiance = pygame.mixer.Sound("images_sons/odyssee.mp3") : un objet audio nommé "ambiance" est créé
ambiance.play(20) : lecture 20 fois du fichier audio.
Le volume de son est compris entre 1 et 0. La fonction get_volume() appliquée à l'objet audio retourne le volume courant.
La fonction set_volume() permet de faire varier la volume du son.
La fonction stop() met fin à la lecture du fichier audio.

Dans ce script certaines instructions sont écrites sur deux lignes.
Le "\" est un symbole spécial qui indique à l'interpréteur que l'instruction continue à ligne suivante.

Le rendu

Effets sonores

Les effets sonores sont de courts fichiers audio qui sont lus suite à un évènements.
Dans le programme qui suit il suffit d'appuyer sur les touches X,C ou V pour déclencher un son bref et à chaque fois différent.

Le code

# pygame_sons2.py
import pygame

pygame.init() 
pygame.mixer.init() 
fenetre = pygame.display.set_mode((500, 400)) 
fenetre.fill('skyblue') 
style= pygame.font.SysFont("Arial", 20, 0, 0) 

pygame.display.set_caption("jeu avec effets sons") 

son1 = pygame.mixer.Sound("images_sons/choc1.mp3") 
son2 = pygame.mixer.Sound("images_sons/alarme1.mp3") 
son3 = pygame.mixer.Sound("images_sons/alarme2.mp3")

style= pygame.font.SysFont("Arial", 20, 0, 0) 
texte1 = style.render("Appuyez sur la touche X ", 1, 'navy')
texte2 = style.render("OU sur la touche C ", 1, 'navy')
texte3 = style.render("OU sur la touche V ", 1, 'navy')

fenetre.blit(texte1,(20,50))
fenetre.blit(texte2,(20,100))
fenetre.blit(texte3,(20,150))
pygame.display.flip()
         
encore =True
#---------------------
while encore: 
    for event in pygame.event.get(): 
       if event.type == pygame.QUIT: 
           encore = False 
       if event.type == pygame.KEYDOWN: 
           if event.key == pygame.K_ESCAPE: 
               encore = False 
           if event.key == pygame.K_x: 
               son1.play()
           if event.key == pygame.K_c: 
               son2.play() 
           if event.key == pygame.K_v: 
               son3.play() 
#----------------

On utilise les mêmes fonctions du module mixer que dans l'exemple précédent.
Mais cette fois le fichier audio ne doit être lu qu'une fois donc emploi de la méthode play() sans argument.

Le rendu

Attention les différents sons peuvent se chevaucher car ils sont diffusés sur le même canal.

Créer un logiciel de dessin avec Pygame

Vous connaissez Paint et bien sachez que ce n'est pas difficile de réalise avec Python-pygame un programme équivalent.

Récupérer la position du pointeur de la souris

Avant d'aborder le logiciel de dessin il faut savoir récupérer les coordonnées du pointeur de souris.

Le code

# pygame_pointeur.py

import pygame, sys 
pygame.init()
dimensions = 400, 400
fenetre = pygame.display.set_mode(dimensions)
pygame.display.set_caption("gestion de la souris")
noir =(0,0,0)
blanc = (255, 255, 255)
fenetre.fill(blanc)
pygame.display.flip()
suite = True

#---------------boucle de jeu--------------
while suite: 
 
      for event in pygame.event.get(): 
         if event.type == pygame.QUIT: 
           sys.exit()   
         if event.type == pygame.MOUSEBUTTONDOWN: 
             pointeur = pygame.mouse.get_pos()
             print("position du pointeur : ", pointeur)
         if event.type == pygame.MOUSEBUTTONUP: 
             pointeur = pygame.mouse.get_pos()
             print("position du pointeur : ", pointeur)

Ce programme affiche les coordonnées X,Y du pointeur de souris lors de l'appui puis du relachement sur le bouton gauche de la souris. Il faut utiliser le module mouse et plus précisément la fonction get_pos().

Quelques instructions à bien comprendre :
if event.type == pygame.MOUSEBUTTONDOWN : si appui sur le bouton gauche de la souris
pointeur = pygame.mouse.get_pos() : la variable "pointeur" récupère sous forme d'un tuple les coordonnées X & Y du pointeur
if event.type == pygame.MOUSEBUTTONUP : si relachemenent de l'appui

Le rendu

Affichage dans le shell :

position du pointeur :  (62, 33)
position du pointeur :  (205, 40)
position du pointeur :  (224, 45)
position du pointeur :  (222, 128)
position du pointeur :  (210, 123)
position du pointeur :  (83, 112)
position du pointeur :  (83, 112)
position du pointeur :  (88, 157)
position du pointeur :  (238, 163)
position du pointeur :  (238, 163)
position du pointeur :  (254, 115)
position du pointeur :  (254, 115)
position du pointeur :  (120, 62)
position du pointeur :  (120, 62)

Vous obtenez à chaque fois la position du pointeur de souris sous forme d'un tuple.

Logiciel de dessin - version 1

Nous allons utiliser le module pygame.mouse et plus précisément la fonction get_pos() qui retourne la position du pointeur sous forme d'un tuple.

Le code

# pygame_logiciel_dessin.py
# Logiciel de dessin - version 1

import pygame, sys 
pygame.init() 
 
fenetre = pygame.display.set_mode((400,400)) 
pygame.display.set_caption("programme de dessin - version 1") 
fenetre.fill('white')
epaisseur = 2

#-----------boucle de jeu---------------
while 1:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
             sys.exit()
       
        if event.type == pygame.MOUSEBUTTONDOWN: 
           debut_ligne = pygame.mouse.get_pos()
           print(debut_ligne)
        if event.type == pygame.MOUSEBUTTONUP:
          fin_ligne = pygame.mouse.get_pos()
          print(fin_ligne)
          pygame.draw.line(fenetre, 'black', debut_ligne, fin_ligne, epaisseur)
    pygame.display.flip()
   

Les instructions print() sont provisoires.
pygame.draw.line(fenetre, 'black', debut_ligne, fin_ligne, epaisseur) : une droite est tracée entre les coordonnées stockées dans "debut_ligne" et celles stockées dans "fin_ligne".

Le rendu

Essayez de dessiner un polygone.

Le shell
(63, 52)
(193, 51)
(193, 51)
(197, 144)
(197, 144)
(100, 146)
(101, 148)
(110, 231)
(114, 229)
(203, 223)
(203, 223)
(194, 159)
(195, 160)
(67, 55)
La fenêtre graphique

Logiciel de dessin - version 2

Dessiner c'est bien mais il faut aussi pouvoir effacer des traits qui ne vous conviennent pas. Il faut donc un mode "dessiner" mais aussi un mode "gommer".
De plus il faudrait pouvoir sauvegarder le dessin produit.

Le code

#pygame_logiciel_dessin.py
import pygame, sys 
pygame.init() 
 
fenetre = pygame.display.set_mode((500,500)) 
pygame.display.set_caption("programme de dessin - version 2") 
fenetre.fill('white')
couleur = 'black'
epaisseur = 2
consignes = """
Touche D pour dessiner
Touche G pour gommer
Touche S pour sauvegarder le dessin
"""

print (consignes)

#-----------boucle--------------
while 1:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
             sys.exit()
        if event.type == pygame.KEYDOWN: 
            if event.key == pygame.K_d: 
                couleur = 'black'
                epaisseur = 2
            if event.key == pygame.K_g: 
               couleur = 'white'
               epaisseur =10
            if event.key == pygame.K_s: 
               pygame.image.save(fenetre, "dessin.png") 
        if event.type == pygame.MOUSEBUTTONDOWN: 
           debut_ligne = pygame.mouse.get_pos() 
        if event.type == pygame.MOUSEBUTTONUP:
            fin_ligne = pygame.mouse.get_pos()
            pygame.draw.line(fenetre, couleur, debut_ligne, fin_ligne, epaisseur)
        pygame.display.flip()
#-----------------------------
pygame.quit()

La variable "consignes" est une chaine multiligne donc délimitée par une paire de guillemets triples.

Le bloc pour gommer :

if event.key == pygame.K_g: 
               couleur = 'white'
               epaisseur =10

En fait gommer c'est dessiner avec la même couleur que le fond et avec une grosse épaisseur.

Utilisation du module pygame.image pour sauvegarder le contenu de la fenêtre sous forme d'un fichier png.

Le rendu

Ci-dessous le fichier .png obtenu lorsque j'ai appuyé sur la touche S.

Les transformations

Une image insérée dans la fenêtre de jeu peut être manipulée afin de modifier son aspect d'origine.
Il faut alors utiliser le module pygame.transform.

Le programme

L'image originale (logo de la bibliothèque Pygame) fait 100 par 30.

À chaque passage dans la boucle de jeu j'affiche une rotation de l'original avec un angle de plus en plus grand.

Le code

#pygame_transformation.py
import pygame, sys 
pygame.init()
 
fenetre = pygame.display.set_mode((400,600)) 
pygame.display.set_caption("Transformations") 
bleu = (0, 0, 255) 
fenetre.fill(bleu)
degre = 1
vitesse = 8
clock = pygame.time.Clock()

 #image originale qui fait 100 par 30
image = pygame.image.load("images_sons/logo.png").convert_alpha() 
fenetre.blit(image, (0,0)) 

 # symétrique sur axe Y
symetrie1 = pygame.transform.flip(image, False,True) 
fenetre.blit(symetrie1, (0,100))

# symétrique sur un axe X
symetrie2 = pygame.transform.flip(image, True,False) 
fenetre.blit(symetrie2, (150,100))

#symétrique sur deux axes
symetrie3 = pygame.transform.flip(image, True,True) 
fenetre.blit(symetrie3, (300,100))

# moitié de l'original
miniature  = pygame.transform.scale(image, (image.get_width()/2, image.get_height()/2))
fenetre.blit(miniature,(50,500))

#double de l'original
double = pygame.transform.scale2x(image) 
fenetre.blit(double, (50,400))

pygame.display.flip()
# --------------
while 1: 
    clock.tick(vitesse)
    for event in pygame.event.get(): 
       if event.type == pygame.QUIT: 
             sys.exit() 

    degre+=2
    if degre ==360 :
        degre =0
    rotation = pygame.transform.rotate(image, degre) 
    fenetre.blit(rotation,(200,200))
    pygame.display.flip() 

Pour créer des symétriques il faut utiliser la fonction flip() avec trois arguments ; les deux derniers sont des booléens.
Pour modifier l'échelle il faut utiliser la fonction scale() avec trois arguments. Notez l'emploi des fonctions get_width() & get_height().
Pour simplement doubler la taille il suffit d'utiliser le raccourci scale2x()
Pour modifier la rotation il faut utiliser la fonction rotate().
Toutes les copies de l'original sont statiques donc en dehors de la boucle de jeu sauf la rotation qui doit être actualisée à chaque itération de la boucle de jeu.

Le rendu

Une variante

...
degre = 360
# dans la boucle de jeu : 
degre-=2
if degre ==0 :
	degre =360
...

La rotation du logo se fait dans l'autre sens.