Vous pouvez me contacter via Facebook pour questions & suggestions :
Page Facebook relative à mon site
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.
Le module pygame.draw permet de dessiner des formes géométriques dans la fenêtre de jeu.
#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
# --------------
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.
Dans le script précédent nous avons rempli des formes.
Cette fois je vous montre comment dessiner des contours de formes
#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
#---------------
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.
Le module font de Pygame permet de créer des textes ; afficher le score obtenu par exemple.
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.
#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.
Notez la FRS (fréquence de rafraichissemen par seconde) qui est de 16.
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.
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.
# 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.
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.
# 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.
Attention les différents sons peuvent se chevaucher car ils sont diffusés sur le même canal.
Vous connaissez Paint et bien sachez que ce n'est pas difficile de réalise avec Python-pygame un programme équivalent.
Avant d'aborder le logiciel de dessin il faut savoir récupérer les coordonnées du pointeur de souris.
# 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
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.
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.
# 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".
Essayez de dessiner un polygone.
(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)
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.
#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.
Ci-dessous le fichier .png obtenu lorsque j'ai appuyé sur la touche S.
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.
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.
#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.
... degre = 360 # dans la boucle de jeu : degre-=2 if degre ==0 : degre =360 ...
La rotation du logo se fait dans l'autre sens.