Pygame: Crie seu Primeiro Jogo em Python
Crie seu primeiro videogame em Python com Pygame: game loop, sprites, colisões, sons, texto e pontuação, com o código completo de um jogo de pegar objetos.
InSkillCoach
Pygame : Créer votre Premier Jeu en Python
Pygame é a biblioteca mais acessível para criar jogos 2D em Python. Ela cuida da exibição, do som, do teclado, do mouse e das colisões, e ainda assim é simples o bastante para que um iniciante construa um jogo completo em poucas horas. Neste guia, você vai aprender os blocos fundamentais do Pygame e depois combiná-los em um pequeno jogo completo de pegar objetos, cujo código integral é fornecido e comentado.
Instalação
O Pygame é instalado com o pip:
pip install pygame
# Vérification : lance un jeu d'exemple fourni avec la bibliothèque
python -m pygame.examples.aliens
Se a janela do jogo de exemplo abrir, está tudo pronto.
A janela e o game loop
Todo jogo se baseia na mesma estrutura: um loop infinito que, a cada volta, processa os eventos (teclado, mouse, fechamento), atualiza o estado do jogo e depois redesenha a tela.
import pygame
# Initialisation de tous les modules Pygame
pygame.init()
# Création de la fenêtre (largeur, hauteur)
ecran = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Mon premier jeu")
# Horloge pour contrôler la vitesse du jeu
horloge = pygame.time.Clock()
en_cours = True
while en_cours:
# 1. ÉVÉNEMENTS : traiter les entrées de l'utilisateur
for event in pygame.event.get():
if event.type == pygame.QUIT: # clic sur la croix de la fenêtre
en_cours = False
# 2. UPDATE : mettre à jour la logique du jeu (positions, score...)
# 3. DRAW : tout redessiner
ecran.fill((30, 30, 60)) # fond bleu nuit (R, G, B)
pygame.display.flip() # afficher le résultat à l'écran
# 4. Limiter le jeu à 60 images par seconde
horloge.tick(60)
pygame.quit()
Dois pontos essenciais:
pygame.display.flip()exibe na tela tudo o que foi desenhado durante a volta do loop. Sem essa chamada, nada aparece.horloge.tick(60)faz o programa esperar o tempo necessário para que o loop rode 60 vezes por segundo. Sem ele, o jogo rodaria em uma velocidade diferente em cada máquina.
Desenhar formas e imagens
O Pygame oferece primitivas de desenho e carregamento de imagens:
# Formes géométriques
pygame.draw.rect(ecran, (255, 0, 0), (100, 100, 50, 80)) # rectangle rouge
pygame.draw.circle(ecran, (0, 255, 0), (400, 300), 40) # cercle vert
pygame.draw.line(ecran, (255, 255, 255), (0, 0), (800, 600), 3) # ligne blanche
# Chargement et affichage d'une image
# convert_alpha() accélère l'affichage et conserve la transparence PNG
joueur_img = pygame.image.load("joueur.png").convert_alpha()
ecran.blit(joueur_img, (200, 150)) # blit = copier l'image à une position
# Redimensionner une image
joueur_img = pygame.transform.scale(joueur_img, (64, 64))
O sistema de coordenadas parte do canto superior esquerdo: x aumenta para a direita e y aumenta para baixo.
Gerenciar teclado e mouse
Existem duas abordagens complementares:
# Approche 1 : les événements (parfaits pour les actions ponctuelles)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
print("Saut !") # déclenché une seule fois par appui
if event.type == pygame.MOUSEBUTTONDOWN:
print(f"Clic en {event.pos}") # position (x, y) du clic
# Approche 2 : l'état des touches (parfait pour le déplacement continu)
touches = pygame.key.get_pressed()
if touches[pygame.K_LEFT]:
x -= 5 # tant que la flèche gauche est maintenue
if touches[pygame.K_RIGHT]:
x += 5
# Position actuelle de la souris
souris_x, souris_y = pygame.mouse.get_pos()
Guarde a regra: evento para uma ação instantânea (tiro, pulo, pausa) e get_pressed() para um movimento fluido.
Sprites e grupos
Um sprite é um objeto do jogo que combina uma imagem (self.image) e uma posição (self.rect). Os grupos permitem atualizar e desenhar dezenas de sprites em uma única linha:
import pygame
class Joueur(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# Image : ici un simple carré bleu de 50x50 pixels
self.image = pygame.Surface((50, 50))
self.image.fill((50, 150, 255))
# Le rect stocke la position et sert aux collisions
self.rect = self.image.get_rect(center=(400, 550))
self.vitesse = 7
def update(self):
"""Appelée à chaque image : déplace le joueur au clavier."""
touches = pygame.key.get_pressed()
if touches[pygame.K_LEFT]:
self.rect.x -= self.vitesse
if touches[pygame.K_RIGHT]:
self.rect.x += self.vitesse
# Empêcher de sortir de l'écran
self.rect.clamp_ip(pygame.Rect(0, 0, 800, 600))
# Utilisation avec un groupe
tous_les_sprites = pygame.sprite.Group()
tous_les_sprites.add(Joueur())
# Dans la boucle de jeu :
tous_les_sprites.update() # appelle update() de chaque sprite
tous_les_sprites.draw(ecran) # dessine chaque sprite à son rect
Colisões
O Pygame oferece vários níveis de detecção:
# Entre deux rectangles
if joueur.rect.colliderect(ennemi.rect):
print("Touché !")
# Entre un sprite et un groupe
# dokill=True : les sprites touchés sont retirés du groupe
objets_touches = pygame.sprite.spritecollide(joueur, groupe_objets, dokill=True)
for objet in objets_touches:
score += 1
# Entre deux groupes (renvoie un dictionnaire)
collisions = pygame.sprite.groupcollide(groupe_tirs, groupe_ennemis, True, True)
Sons
# Le mixer doit être initialisé (pygame.init() le fait automatiquement)
son_bonus = pygame.mixer.Sound("bonus.wav") # effet court, chargé en mémoire
son_bonus.set_volume(0.5) # volume de 0.0 à 1.0
son_bonus.play()
# Musique de fond (lue en continu depuis le fichier)
pygame.mixer.music.load("musique.ogg")
pygame.mixer.music.play(-1) # -1 = boucle infinie
Texto e pontuação
O texto é desenhado em três etapas: criar uma fonte, gerar uma imagem do texto (render) e depois exibi-la (blit):
# None = police par défaut, 36 = taille en points
police = pygame.font.Font(None, 36)
score = 12
# render(texte, antialiasing, couleur)
texte_score = police.render(f"Score : {score}", True, (255, 255, 255))
ecran.blit(texte_score, (10, 10))
Um jogo completo: o pega-objetos
Vamos juntar tudo em um jogo jogável: maçãs caem do topo da tela e você move uma cesta com as setas para pegá-las. Cada maçã pega rende um ponto, e cada maçã perdida custa uma vida. O código é autônomo (nenhuma imagem externa: tudo é desenhado com formas).
import random
import pygame
# ---------- Étape 1 : constantes et initialisation ----------
LARGEUR, HAUTEUR = 800, 600
FPS = 60
pygame.init()
ecran = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption("Attrape-Pommes")
horloge = pygame.time.Clock()
police = pygame.font.Font(None, 36)
# ---------- Étape 2 : les sprites ----------
class Panier(pygame.sprite.Sprite):
"""Le panier contrôlé par le joueur, en bas de l'écran."""
def __init__(self):
super().__init__()
self.image = pygame.Surface((100, 25))
self.image.fill((160, 100, 40)) # marron
self.rect = self.image.get_rect(midbottom=(LARGEUR // 2, HAUTEUR - 10))
self.vitesse = 9
def update(self):
touches = pygame.key.get_pressed()
if touches[pygame.K_LEFT]:
self.rect.x -= self.vitesse
if touches[pygame.K_RIGHT]:
self.rect.x += self.vitesse
self.rect.clamp_ip(ecran.get_rect()) # rester dans l'écran
class Pomme(pygame.sprite.Sprite):
"""Une pomme qui tombe du haut de l'écran à vitesse aléatoire."""
def __init__(self):
super().__init__()
self.image = pygame.Surface((28, 28), pygame.SRCALPHA)
pygame.draw.circle(self.image, (220, 40, 40), (14, 14), 14)
self.rect = self.image.get_rect(
midtop=(random.randint(20, LARGEUR - 20), -30)
)
self.vitesse = random.randint(3, 7)
def update(self):
self.rect.y += self.vitesse
# ---------- Étape 3 : état du jeu ----------
panier = Panier()
tous_les_sprites = pygame.sprite.Group(panier)
pommes = pygame.sprite.Group()
score = 0
vies = 3
# Événement personnalisé : faire apparaître une pomme toutes les 800 ms
APPARITION_POMME = pygame.USEREVENT + 1
pygame.time.set_timer(APPARITION_POMME, 800)
# ---------- Étape 4 : boucle de jeu ----------
en_cours = True
while en_cours:
# Événements
for event in pygame.event.get():
if event.type == pygame.QUIT:
en_cours = False
if event.type == APPARITION_POMME and vies > 0:
pomme = Pomme()
pommes.add(pomme)
tous_les_sprites.add(pomme)
if vies > 0:
# Update
tous_les_sprites.update()
# Pommes attrapées : +1 point chacune
attrapees = pygame.sprite.spritecollide(panier, pommes, dokill=True)
score += len(attrapees)
# Pommes manquées (sorties de l'écran) : -1 vie chacune
for pomme in list(pommes):
if pomme.rect.top > HAUTEUR:
pomme.kill() # retire le sprite de tous ses groupes
vies -= 1
# Draw
ecran.fill((25, 35, 55))
tous_les_sprites.draw(ecran)
texte = police.render(f"Score : {score} Vies : {vies}", True, (255, 255, 255))
ecran.blit(texte, (10, 10))
if vies <= 0:
fin = police.render("PARTIE TERMINÉE - Fermez la fenêtre", True, (255, 80, 80))
rect_fin = fin.get_rect(center=(LARGEUR // 2, HAUTEUR // 2))
ecran.blit(fin, rect_fin)
pygame.display.flip()
horloge.tick(FPS)
pygame.quit()
Salve esse código em attrape_pommes.py e execute-o: o jogo já é jogável imediatamente. Algumas ideias de melhoria para você praticar: acelerar as maçãs com o passar do tempo, adicionar um som a cada maçã pega, salvar a melhor pontuação em um arquivo ou substituir as formas por imagens de verdade.
Boas práticas
- Respeite a estrutura eventos / update / draw: nunca desenhe na fase de lógica e não modifique o estado na fase de desenho.
- Use sempre
clock.tick(FPS)para ter a mesma velocidade em todas as máquinas. - Chame
convert()ouconvert_alpha()depois de cadapygame.image.load(): a exibição fica bem mais rápida. - Uma classe de sprite por tipo de objeto: o código continua legível e os grupos cuidam das atualizações e do desenho.
- Use
sprite.kill()para remover corretamente um sprite de todos os seus grupos, em vez de gerenciar listas manualmente. - Agrupe as constantes (dimensões, cores, velocidades) no topo do arquivo: balancear o jogo se torna trivial.
Conclusão
Agora você conhece todos os mecanismos fundamentais do Pygame: o game loop cadenciado pelo relógio, o desenho de formas e imagens, o gerenciamento do teclado, os sprites organizados em grupos, as colisões, o som e a exibição da pontuação. O jogo de pegar objetos reúne todos esses elementos em menos de 120 linhas; ele é uma base sólida que você pode enriquecer à vontade.
Para continuar, explore a documentação oficial do Pygame e proponha-se um desafio clássico: recriar Pong, Snake ou um jogo de quebra-tijolos. É construindo pequenos jogos completos que se progride mais rápido.
Sobre InSkillCoach
Especialista em treinamento e tecnologias
Coach especializado em tecnologias avançadas e IA, apoiado pela GNeurone Inc.
Certificações:
- AWS Certified Solutions Architect – Professional
- Certificações Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão