Pygame: des exemples pour débuter
La documentation pygame officielle est touffue, difficile à parcourir et pas toujours à jour.
Il est parfois difficile de trouver comment faire certaines choses simples, comme créer une fenêtre bleue et non pas noire.
Il ne faut surtout pas télécharger les sources sur http://pygame.org/download.shtml mais sur bitbucket.org.
Avis tout à fait personnel et partial. pygame est utilisé par des étudiants qui partagent leurs jeux,
- leur code est loin d'être au top
- pourquoi faire simple quand on peut faire compliqué ?
- trop souvent mal ou pas documenté !
Ce qui suis a été testé avec python 3.4.
Sommaire
Ressources
Beaucoup d'exemple datent de 2002 à la création de pygame ! et repris ... repris ...
- Documentation officielle Anglais
- Pygame sur fr.wikibooks.org Français
- [ ]
Installation depuis un PPA
Installation de pygame et kivy pour python 3
Vérifié sur Linux Mint 17 Qiana
sudo add-apt-repository ppa:thopiekar/pygame sudo add-apt-repository ppa:kivy-team/kivy sudo apt-get update sudo apt-get install python3-kivy
Ça n'installe pas pygame !!
sudo apt-get install mercurial sudo pip3 install hg+http://bitbucket.org/pygame/pygame
Installation de pygame et kivy pour python 2.7
sudo apt-get install python-kivy
pygame:
sudo apt-get install mercurial sudo pip install hg+http://bitbucket.org/pygame/pygame
Fichiers
Pourquoi importer pygame.locals ?
Le module pygame.locals contient quelques variables telles que les types d'evénement (QUIT, KEYDOWN, etc.) et touches clavier (K_ESCAPE, K_LEFT, etc.). Avec la syntaxe from pygame.locals import *, on utilise QUIT à la place de pygame.locals.QUIT.
Comme je n'arrive pas à trouver la liste de ces variables, je trouve que c'est du bordel, et on va s'en passer ! Je crée donc je suis dangereux. De toute façon, en python, on préfère l'explicite à l'implicite.
Redimensionnement de la fenêtre
http://www.pygame.org/wiki/WindowResizing?parent=CookBook Ce n'est pas simple car il faut gérer les objets dans la nouvelle fenêtre, donc on ne le fait pas.
Une fenêtre avec un fond bleu
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import pygame
# Before you can do much with pygame, you will need to initialize it
pygame.init()
# Init de clock
clock = pygame.time.Clock()
CIEL = 0, 200, 255 # parenthèses inutiles, l'interpréteur reconnaît un tuple
def main():
fenetre = pygame.display.set_mode((640, 480))
# loop
loop = True
# Création d'une image de la taille de la fenêtre
background = pygame.Surface(fenetre.get_size())
while loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
# Superposition du fond ciel
background.fill(CIEL)
fenetre.blit(background, (0, 0))
# Rafraîchissement de l'écran
pygame.display.flip()
# By calling Clock.tick(10) once per frame, the program will never run
# at more than 10 frames per second
clock.tick(10)
if __name__ == '__main__':
main()
Texte
Liste des polices possibles
print(pygame.font.get_fonts())
Un texte orange sur fond bleu
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import pygame
pygame.init()
clock = pygame.time.Clock()
CIEL = 0, 200, 255
ORANGE = 255, 100, 0
def main():
fenetre = pygame.display.set_mode((640, 480))
loop = True
while loop:
background = pygame.Surface(fenetre.get_size())
background.fill(CIEL)
# Définition de la police
bigText = pygame.font.SysFont('freesans', 36)
# Définition du texte
# render(text, antialias, rgb color tuple)
title_text = bigText.render("Maître Corbeau sur un arbre perché",
True, ORANGE)
# Position: horizontal au centre , vertical = 50
# Le centre du texte est au centre quelque soit le texte
# Le texte est inscrit dans un rectangle
textpos = title_text.get_rect()
# Placement du texte en x et y
textpos.centerx = fenetre.get_rect().centerx
textpos.centery = 50
# Collage du texte sur le fond
background.blit(title_text, textpos)
# Ajout du fond dans la fenêtre
fenetre.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
# Actualisation de l'affichage
pygame.display.flip()
# 10 fps
clock.tick(10)
if __name__ == '__main__':
main()
Des rectangles comme boutons
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import pygame
pygame.init()
clock = pygame.time.Clock()
CIEL = 0, 200, 255
WHITE = 255, 255, 255
GREEN = 0, 255, 0
RED = 255, 0, 0
def main():
fenetre = pygame.display.set_mode((640, 480))
loop = True
green_color = GREEN
white_color = WHITE
while loop:
background = pygame.Surface(fenetre.get_size())
background.fill(CIEL)
# Ajout du fond dans la fenêtre
fenetre.blit(background, (0, 0))
# Draw a rectangle outline
rect_white = pygame.draw.rect(fenetre, white_color, [75, 10, 100, 50],
5)
# Draw a solid rectangle
rect_green = pygame.draw.rect(fenetre, green_color, [250, 10, 100, 50])
# retourne 1 si le curseur est au dessus du rectangle
mouse_xy = pygame.mouse.get_pos()
over_white = rect_white.collidepoint(mouse_xy)
over_green = rect_green.collidepoint(mouse_xy)
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
# si clic, le vert devient rouge
elif event.type == pygame.MOUSEBUTTONDOWN and over_green:
green_color = RED
# le rectangle se cache
elif event.type == pygame.MOUSEBUTTONDOWN and over_white:
white_color = CIEL
# Actualisation de l'affichage
pygame.display.flip()
# 10 fps
clock.tick(10)
if __name__ == '__main__':
main()
Une ébauche d'interface graphique
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# server_gui.py
#############################################################################
# Copyright (C) Labomedia February 2015
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franproplin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#############################################################################
import pygame
import sys
pygame.init()
clock = pygame.time.Clock()
BLACK = 0, 0, 0
WHITE = 255, 255, 255
CIEL = 0, 200, 255
RED = 255, 0, 0
ORANGE = 255, 100, 0
GREEN = 0, 255, 0
class Button:
'''Ajout d'un bouton avec un texte sur img
Astuce: ajouter des espaces dans les textes pour avoir une même largeur
de boutons
dx, dy décalage du bouton par rapport au centre
action si click
Texte noir
'''
def __init__(self, fond, text, color, font, dx, dy):
self.fond = fond
self.text = text
self.color = color
self.font = font
self.dec = dx, dy
self.state = False # enable or not
self.title = self.font.render(self.text, True, BLACK)
textpos = self.title.get_rect()
textpos.centerx = self.fond.get_rect().centerx + self.dec[0]
textpos.centery = self.dec[1]
self.textpos = [textpos[0], textpos[1], textpos[2], textpos[3]]
self.rect = pygame.draw.rect(self.fond, self.color, self.textpos)
self.fond.blit(self.title, self.textpos)
def update_button(self, fond, action=None):
self.fond = fond
mouse_xy = pygame.mouse.get_pos()
over = self.rect.collidepoint(mouse_xy)
if over:
action()
if self.color == RED:
self.color = GREEN
self.state = True
elif self.color == GREEN:
# sauf les + et -, pour que ce soit toujours vert
if len(self.text) > 5: # 5 char avec les espaces
self.color = RED
self.state = False
# à la bonne couleur
self.rect = pygame.draw.rect(self.fond, self.color, self.textpos)
self.fond.blit(self.title, self.textpos)
def display_button(self, fond):
self.fond = fond
self.rect = pygame.draw.rect(self.fond, self.color, self.textpos)
self.fond.blit(self.title, self.textpos)
class Game:
def __init__(self):
self.screen = pygame.display.set_mode((640, 480))
self.level = 1
self.loop = True
# Définition de la police
self.big = pygame.font.SysFont('freesans', 48)
self.small = pygame.font.SysFont('freesans', 36)
self.create_fond()
self.create_button()
def update_textes(self):
self.textes = [ ["Buggy Server", ORANGE, self.big, 0, 50],
["Level", BLACK, self.small, 0, 150],
[str(self.level), BLACK, self.small, 0, 200]]
def create_fond(self):
# Image de la taille de la fenêtre
self.fond = pygame.Surface(self.screen.get_size())
# En bleu
self.fond.fill(CIEL)
def create_button(self):
self.reset_button = Button(self.fond, " Reset ", RED, self.small, 0, 300)
self.start_button = Button(self.fond, " Start ", RED, self.small, 0, 360)
self.quit_button = Button(self.fond, " Quit ", RED, self.small, 0, 420)
self.moins_button = Button(self.fond, " - ", GREEN, self.small, -100, 200)
self.plus_button = Button(self.fond, " + ", GREEN, self.small, 100, 200)
def display_text(self, text, color, font, dx, dy):
'''Ajout d'un texte sur fond. Décalage dx, dy par rapport au centre.
'''
mytext = font.render(text, True, color) # True pour antialiasing
textpos = mytext.get_rect()
textpos.centerx = self.fond.get_rect().centerx + dx
textpos.centery = dy
self.fond.blit(mytext, textpos)
def plus(self):
self.level += 1
if self.level == 6: self.level = 5
def moins(self):
self.level += -1
if self.level == 0: self.level = 1
def infinite_loop(self):
while self.loop:
self.create_fond()
# Boutons
self.reset_button.display_button(self.fond)
self.start_button.display_button(self.fond)
self.quit_button.display_button(self.fond)
self.moins_button.display_button(self.fond)
self.plus_button.display_button(self.fond)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
self.reset_button.update_button(self.fond, action=reset)
self.start_button.update_button(self.fond, action=start)
self.quit_button.update_button(self.fond, action=gamequit)
self.moins_button.update_button(self.fond, action=self.moins)
self.plus_button.update_button(self.fond, action=self.plus)
self.update_textes()
for text in self.textes:
self.display_text(text[0], text[1], text[2],
text[3], text[4])
# Ajout du fond dans la fenêtre
self.screen.blit(self.fond, (0, 0))
# Actualisation de l'affichage
pygame.display.update()
# 10 fps
clock.tick(10)
def reset():
print("reset")
def start():
print("start")
def gamequit():
print("Quit")
pygame.quit()
sys.exit()
if __name__ == '__main__':
game = Game()
game.infinite_loop()
pygame est une bibliothèque de bas niveau
- Que c'est moche !
- Que de lignes pour des choses simples !
Une alternative pour un GUI: kivy
Ressources
Installation
Un server pour le jeu de Buggy
Mais sans la fonction server, cet essai sert juste à tester le GUI, puis à créer une application Android.