0%
Pygame: Crie seu Primeiro Jogo em Python

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.

I

InSkillCoach

· min

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() ou convert_alpha() depois de cada pygame.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.

InSkillCoach

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+
756
160

Comentários

Os comentários são alimentados pelo GitHub Discussions

Conecte-se com o GitHub para participar da discussão

Link copiado!