Criando Jogos com Pygame em Python

Aprenda a criar jogos 2D com Pygame em Python. Tutorial pratico com sprites, colisoes, sons e um jogo completo passo a passo.

5 min de leitura Equipe Python Brasil

Desenvolver jogos e uma das formas mais divertidas de aprender programacao. O Pygame e a biblioteca mais popular para criacao de jogos 2D em Python, oferecendo controle sobre graficos, sons, entrada do teclado e muito mais. Neste tutorial, vamos construir um jogo completo do zero.

Instalacao e Estrutura Basica

Instale o Pygame com pip:

pip install pygame

Todo jogo em Pygame segue uma estrutura basica: inicializacao, loop principal e finalizacao.

import pygame
import sys

# Inicializacao
pygame.init()

# Configuracoes da tela
LARGURA = 800
ALTURA = 600
FPS = 60

tela = pygame.display.set_mode((LARGURA, ALTURA))
pygame.display.set_caption("Meu Primeiro Jogo")
relogio = pygame.time.Clock()

# Cores
PRETO = (0, 0, 0)
BRANCO = (255, 255, 255)
AZUL = (0, 100, 200)
VERMELHO = (200, 50, 50)

# Loop principal
rodando = True
while rodando:
    # Eventos
    for evento in pygame.event.get():
        if evento.type == pygame.QUIT:
            rodando = False

    # Atualizacao da tela
    tela.fill(PRETO)
    pygame.draw.rect(tela, AZUL, (350, 250, 100, 100))
    pygame.display.flip()
    relogio.tick(FPS)

pygame.quit()
sys.exit()

Esse codigo cria uma janela com um quadrado azul. O loop principal roda a 60 frames por segundo, processando eventos, atualizando o estado e desenhando na tela.

Criando o Jogador com Sprites

Sprites sao objetos visuais do jogo. O Pygame oferece a classe pygame.sprite.Sprite como base:

class Jogador(pygame.sprite.Sprite):
    def __init__(self, x: int, y: int):
        super().__init__()
        self.image = pygame.Surface((50, 50))
        self.image.fill(AZUL)
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.velocidade = 5
        self.vida = 3
        self.pontos = 0

    def update(self):
        """Movimentacao com as setas do teclado."""
        teclas = pygame.key.get_pressed()
        if teclas[pygame.K_LEFT] and self.rect.left > 0:
            self.rect.x -= self.velocidade
        if teclas[pygame.K_RIGHT] and self.rect.right < LARGURA:
            self.rect.x += self.velocidade
        if teclas[pygame.K_UP] and self.rect.top > 0:
            self.rect.y -= self.velocidade
        if teclas[pygame.K_DOWN] and self.rect.bottom < ALTURA:
            self.rect.y += self.velocidade

    def desenhar_vida(self, superficie: pygame.Surface):
        """Desenha indicadores de vida na tela."""
        for i in range(self.vida):
            pygame.draw.rect(superficie, VERMELHO, (10 + i * 30, 10, 25, 25))

Inimigos e Coletaveis

Vamos criar inimigos que se movem pela tela e itens coletaveis:

import random

class Inimigo(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((40, 40))
        self.image.fill(VERMELHO)
        self.rect = self.image.get_rect()
        self.rect.x = random.randint(0, LARGURA - 40)
        self.rect.y = random.randint(-100, -40)
        self.vel_y = random.randint(2, 6)

    def update(self):
        """Move o inimigo para baixo."""
        self.rect.y += self.vel_y
        if self.rect.top > ALTURA:
            self.rect.x = random.randint(0, LARGURA - 40)
            self.rect.y = random.randint(-100, -40)
            self.vel_y = random.randint(2, 6)

class Moeda(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((20, 20))
        pygame.draw.circle(self.image, (255, 215, 0), (10, 10), 10)
        self.image.set_colorkey(PRETO)
        self.rect = self.image.get_rect()
        self.rect.x = random.randint(20, LARGURA - 20)
        self.rect.y = random.randint(-200, -20)
        self.vel_y = random.randint(1, 3)

    def update(self):
        self.rect.y += self.vel_y
        if self.rect.top > ALTURA:
            self.rect.x = random.randint(20, LARGURA - 20)
            self.rect.y = random.randint(-200, -20)

Sistema de Colisao

O Pygame facilita a deteccao de colisoes entre sprites:

def verificar_colisoes(jogador, inimigos, moedas):
    """Verifica colisoes entre jogador, inimigos e moedas."""
    # Colisao com inimigos
    inimigos_atingidos = pygame.sprite.spritecollide(jogador, inimigos, True)
    for inimigo in inimigos_atingidos:
        jogador.vida -= 1
        print(f"Dano! Vida restante: {jogador.vida}")

    # Colisao com moedas
    moedas_coletadas = pygame.sprite.spritecollide(jogador, moedas, True)
    for moeda in moedas_coletadas:
        jogador.pontos += 10
        print(f"Moeda! Pontos: {jogador.pontos}")

    return jogador.vida > 0

Texto e Interface

Mostrar informacoes na tela e essencial para qualquer jogo:

def desenhar_hud(superficie: pygame.Surface, pontos: int, vida: int):
    """Desenha a interface do jogo."""
    fonte = pygame.font.Font(None, 36)

    # Pontuacao
    texto_pontos = fonte.render(f"Pontos: {pontos}", True, BRANCO)
    superficie.blit(texto_pontos, (LARGURA - 200, 10))

    # Vida
    texto_vida = fonte.render(f"Vida: {vida}", True, BRANCO)
    superficie.blit(texto_vida, (10, 10))

def tela_game_over(superficie: pygame.Surface, pontos: int):
    """Exibe a tela de game over."""
    superficie.fill(PRETO)
    fonte_grande = pygame.font.Font(None, 72)
    fonte_media = pygame.font.Font(None, 36)

    texto_fim = fonte_grande.render("Game Over", True, VERMELHO)
    texto_pontos = fonte_media.render(f"Pontuacao Final: {pontos}", True, BRANCO)
    texto_reiniciar = fonte_media.render("Pressione R para reiniciar", True, BRANCO)

    superficie.blit(texto_fim, (LARGURA // 2 - texto_fim.get_width() // 2, 200))
    superficie.blit(texto_pontos, (LARGURA // 2 - texto_pontos.get_width() // 2, 300))
    superficie.blit(texto_reiniciar, (LARGURA // 2 - texto_reiniciar.get_width() // 2, 400))
    pygame.display.flip()

Jogo Completo Integrado

Agora vamos juntar tudo em um loop principal funcional:

def main():
    pygame.init()
    tela = pygame.display.set_mode((LARGURA, ALTURA))
    pygame.display.set_caption("Coletor de Moedas")
    relogio = pygame.time.Clock()

    # Criar sprites
    jogador = Jogador(LARGURA // 2, ALTURA - 60)
    todos_sprites = pygame.sprite.Group(jogador)
    inimigos = pygame.sprite.Group()
    moedas = pygame.sprite.Group()

    # Spawnar inimigos e moedas
    for _ in range(8):
        inimigo = Inimigo()
        todos_sprites.add(inimigo)
        inimigos.add(inimigo)

    for _ in range(5):
        moeda = Moeda()
        todos_sprites.add(moeda)
        moedas.add(moeda)

    game_over = False
    rodando = True

    while rodando:
        for evento in pygame.event.get():
            if evento.type == pygame.QUIT:
                rodando = False
            if evento.type == pygame.KEYDOWN:
                if evento.key == pygame.K_r and game_over:
                    main()
                    return

        if not game_over:
            todos_sprites.update()
            vivo = verificar_colisoes(jogador, inimigos, moedas)

            # Respawnar coletaveis
            while len(moedas) < 5:
                moeda = Moeda()
                todos_sprites.add(moeda)
                moedas.add(moeda)

            while len(inimigos) < 8:
                inimigo = Inimigo()
                todos_sprites.add(inimigo)
                inimigos.add(inimigo)

            if not vivo:
                game_over = True

            tela.fill(PRETO)
            todos_sprites.draw(tela)
            desenhar_hud(tela, jogador.pontos, jogador.vida)
            pygame.display.flip()
        else:
            tela_game_over(tela, jogador.pontos)

        relogio.tick(FPS)

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

Sons e Musica

Adicionar audio torna o jogo muito mais imersivo:

# Inicializar audio
pygame.mixer.init()

# Carregar sons
som_moeda = pygame.mixer.Sound("sons/moeda.wav")
som_dano = pygame.mixer.Sound("sons/dano.wav")

# Musica de fundo
pygame.mixer.music.load("sons/musica_fundo.ogg")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)  # Loop infinito

# Tocar efeito sonoro
som_moeda.play()

Boas Praticas no Desenvolvimento de Jogos

Organizar o codigo e fundamental conforme o jogo cresce. Separe as classes em arquivos distintos: um para o jogador, outro para os inimigos, outro para os itens. Use constantes para valores como velocidade, tamanho da tela e cores. Implemente um sistema de estados para gerenciar menus, gameplay e tela de game over. Otimize o desempenho usando convert() nas imagens carregadas e limitando o numero de sprites ativos.

Teste cada mecanica isoladamente antes de integrar ao jogo principal. Isso facilita a depuracao e permite iterar rapidamente sobre cada funcionalidade.

Conclusao

O Pygame e uma ferramenta poderosa para aprender conceitos de programacao enquanto se diverte criando jogos. Neste tutorial, construimos um jogo completo com sprites, colisoes, pontuacao e sistema de vidas. A partir daqui, voce pode expandir com animacoes, fases, power-ups e muito mais. O importante e comecar simples e ir adicionando complexidade aos poucos.

E

Equipe Python Brasil

Contribuidor do Python Brasil — Aprenda Python em Português