pratica

Criando Telas de Menu e Game Over

Aprenda sobre criando telas de menu e game over

50 min
Aula 4 de 5

🎮 Criando Telas de Menu e Game Over

Olá, futuro Game Developer! 👋 Nesta aula prática, vamos dar um salto na qualidade dos nossos jogos, adicionando elementos essenciais para uma experiência de usuário mais completa e profissional: telas de menu e de Game Over.

Até agora, nossos jogos começam imediatamente e, quando acabam, simplesmente param. Mas e se quiséssemos dar ao jogador a opção de iniciar o jogo, ver instruções, ou jogar novamente após uma derrota? É exatamente isso que aprenderemos a fazer hoje!

🎯 O que vamos aprender:

  • Gerenciar diferentes "estados" do jogo (Menu, Jogando, Game Over).
  • Desenhar texto e "botões" interativos na tela.
  • Detectar cliques do mouse para navegar entre os estados.
  • Reiniciar o jogo de forma limpa.

Vamos colocar a mão na massa e transformar nossos protótipos em jogos mais robustos! 🛠️


1. 🧠 Gerenciando Estados do Jogo

A chave para ter telas diferentes é gerenciar o estado atual do jogo. Pense nisso como os diferentes "modos" em que seu jogo pode estar. Por exemplo:

  • MENU: O jogador está na tela inicial, pronto para começar.
  • PLAYING: O jogo está acontecendo, com o jogador controlando o personagem.
  • GAME_OVER: O jogo terminou, e o jogador vê a pontuação final e opções.

Podemos usar uma variável simples para guardar o estado atual do nosso jogo.

# No início do seu código
game_state = 'MENU' # O jogo começa no estado de menu

E então, dentro das nossas funções draw() e update(), usaremos if/elif para decidir o que fazer com base no game_state.


2. 🎨 Desenhando Telas de Menu e Game Over

A função draw() é onde toda a mágica visual acontece. Vamos usá-la para desenhar elementos diferentes dependendo do game_state.

Exemplo: Desenhando um Menu Simples

Para o menu, precisaremos de um título e um botão "Iniciar Jogo".

def draw():
    screen.clear() # Limpa a tela a cada frame
 
    if game_state == 'MENU':
        screen.draw.text("MEU JOGO INCRÍVEL", center=(WIDTH / 2, HEIGHT / 3), color="white", fontsize=60)
        # Desenha um "botão" retangular
        screen.draw.filled_rect(Rect((WIDTH / 2 - 100, HEIGHT / 2), (200, 50)), color="green")
        screen.draw.text("Iniciar Jogo", center=(WIDTH / 2, HEIGHT / 2 + 25), color="white", fontsize=30)
    elif game_state == 'PLAYING':
        # Aqui desenhamos os elementos do jogo (jogador, inimigos, etc.)
        player.draw()
        screen.draw.text(f"Pontos: {score}", topleft=(10, 10), color="white", fontsize=30)
    elif game_state == 'GAME_OVER':
        screen.draw.text("GAME OVER!", center=(WIDTH / 2, HEIGHT / 3), color="red", fontsize=60)
        screen.draw.text(f"Sua Pontuação: {score}", center=(WIDTH / 2, HEIGHT / 2 - 30), color="white", fontsize=40)
        # Botão "Jogar Novamente"
        screen.draw.filled_rect(Rect((WIDTH / 2 - 120, HEIGHT / 2 + 20), (240, 50)), color="blue")
        screen.draw.text("Jogar Novamente", center=(WIDTH / 2, HEIGHT / 2 + 45), color="white", fontsize=30)

Observações:

  • screen.draw.text(): Permite desenhar texto na tela. Você pode especificar a posição (center, topleft, etc.), cor e tamanho da fonte.
  • screen.draw.filled_rect(): Desenha um retângulo preenchido. Usamos Rect para definir a posição e tamanho do nosso "botão".
  • Rect((x, y), (width, height)): Cria um objeto retângulo. (x, y) é o canto superior esquerdo, (width, height) são as dimensões.

3. 🖱️ Interagindo com o Mouse: on_mouse_down()

Para que nossos botões funcionem, precisamos detectar quando o jogador clica neles. A função on_mouse_down(pos) do Pygame Zero é perfeita para isso. Ela é chamada sempre que o mouse é clicado, e pos é uma tupla (x, y) com as coordenadas do clique.

def on_mouse_down(pos):
    global game_state, score, player # Precisamos acessar e modificar essas variáveis globais
 
    if game_state == 'MENU':
        # Define a área do botão "Iniciar Jogo"
        start_button_rect = Rect((WIDTH / 2 - 100, HEIGHT / 2), (200, 50))
        if start_button_rect.collidepoint(pos): # Verifica se o clique foi dentro do botão
            game_state = 'PLAYING'
            reset_game() # Reinicia o jogo quando começar
    elif game_state == 'GAME_OVER':
        # Define a área do botão "Jogar Novamente"
        restart_button_rect = Rect((WIDTH / 2 - 120, HEIGHT / 2 + 20), (240, 50))
        if restart_button_rect.collidepoint(pos):
            game_state = 'PLAYING'
            reset_game() # Reinicia o jogo
 
# Função para reiniciar o jogo
def reset_game():
    global player, score
    player.pos = (WIDTH / 2, HEIGHT / 2) # Posição inicial do jogador
    score = 0 # Zera a pontuação
    # Adicione aqui qualquer outra variável que precise ser reiniciada

Explicação:

  • global game_state, score, player: Declaramos que estamos usando as versões globais dessas variáveis, não criando novas locais.
  • Rect.collidepoint(pos): Este é um método muito útil de um objeto Rect que verifica se um ponto (pos) está dentro dos limites do retângulo.
  • reset_game(): É uma boa prática criar uma função separada para reiniciar todas as variáveis do jogo para seus valores iniciais. Isso evita repetição de código.

4. 🕹️ Atualizando o Jogo: update()

A função update() deve conter a lógica do jogo (movimento de personagens, colisão, etc.) e só deve ser executada quando o jogo estiver no estado PLAYING.

def update(dt):
    global game_state, score
 
    if game_state == 'PLAYING':
        # Lógica do jogo (movimento do jogador, inimigos, etc.)
        # Exemplo simples: o jogador se move para a direita
        player.x += 200 * dt
 
        # Condição de Game Over (ex: jogador sai da tela)
        if player.left > WIDTH:
            game_state = 'GAME_OVER'
            print("Game Over!")
        
        # Exemplo de aumento de pontuação
        score += 1

🚀 Código de Exemplo Completo

Vamos juntar tudo em um exemplo completo. Neste jogo simples, um quadrado (player) se move para a direita. Se ele sair da tela, é "Game Over". Você pode clicar para iniciar e reiniciar.

# game_with_menus.py
 
import pgzrun # Importa o Pygame Zero
 
# --- Configurações da Tela ---
WIDTH = 800
HEIGHT = 600
TITLE = "Meu Jogo com Menus"
 
# --- Variáveis Globais do Jogo ---
game_state = 'MENU' # 'MENU', 'PLAYING', 'GAME_OVER'
player = Actor('player_square') # Usaremos um quadrado simples como jogador
score = 0
 
# --- Funções de Inicialização e Reinício ---
 
def reset_game():
    """Reinicia todas as variáveis do jogo para seus valores iniciais."""
    global player, score
    player.pos = (WIDTH / 4, HEIGHT / 2) # Posição inicial do jogador
    player.image = 'player_square' # Garante que a imagem está correta
    score = 0
    print("Jogo reiniciado!")
 
# --- Funções do Pygame Zero ---
 
def draw():
    """Desenha todos os elementos na tela, baseado no estado do jogo."""
    screen.clear() # Limpa a tela a cada frame (fundo preto)
 
    if game_state == 'MENU':
        screen.draw.text(TITLE, center=(WIDTH / 2, HEIGHT / 3), color="white", fontsize=60)
        
        # Desenha o botão "Iniciar Jogo"
        start_button_rect = Rect((WIDTH / 2 - 100, HEIGHT / 2), (200, 50))
        screen.draw.filled_rect(start_button_rect, color="green")
        screen.draw.text("Iniciar Jogo", center=(WIDTH / 2, HEIGHT / 2 + 25), color="white", fontsize=30)
        
    elif game_state == 'PLAYING':
        player.draw()
        screen.draw.text(f"Pontos: {score}", topleft=(10, 10), color="white", fontsize=30)
        
    elif game_state == 'GAME_OVER':
        screen.draw.text("GAME OVER!", center=(WIDTH / 2, HEIGHT / 3), color="red", fontsize=60)
        screen.draw.text(f"Sua Pontuação: {score}", center=(WIDTH / 2, HEIGHT / 2 - 30), color="white", fontsize=40)
        
        # Desenha o botão "Jogar Novamente"
        restart_button_rect = Rect((WIDTH / 2 - 120, HEIGHT / 2 + 20), (240, 50))
        screen.draw.filled_rect(restart_button_rect, color="blue")
        screen.draw.text("Jogar Novamente", center=(WIDTH / 2, HEIGHT / 2 + 45), color="white", fontsize=30)
 
def update(dt):
    """Atualiza a lógica do jogo, apenas quando o jogo está no estado PLAYING."""
    global game_state, score
 
    if game_state == 'PLAYING':
        # Movimento simples do jogador para a direita
        player.x += 150 * dt # dt é o tempo desde o último frame, para movimento suave
 
        # Condição de Game Over: jogador sai da tela pela direita
        if player.left > WIDTH:
            game_state = 'GAME_OVER'
            print("Game Over!")
        
        # Aumenta a pontuação a cada frame
        score += 1 # Poderíamos fazer com base em eventos ou tempo real
 
def on_mouse_down(pos):
    """Lida com cliques do mouse para interação com menus e botões."""
    global game_state
 
    if game_state == 'MENU':
        # Área do botão "Iniciar Jogo"
        start_button_rect = Rect((WIDTH / 2 - 100, HEIGHT / 2), (200, 50))
        if start_button_rect.collidepoint(pos):
            game_state = 'PLAYING'
            reset_game() # Inicia o jogo e reinicia suas variáveis
            
    elif game_state == 'GAME_OVER':
        # Área do botão "Jogar Novamente"
        restart_button_rect = Rect((WIDTH / 2 - 120, HEIGHT / 2 + 20), (240, 50))
        if restart_button_rect.collidepoint(pos):
            game_state = 'PLAYING'
            reset_game() # Reinicia o jogo
 
# --- Inicia o Pygame Zero ---
pgzrun.go()

Para rodar este código:

  1. Salve o código acima como game_with_menus.py.
  2. Crie uma pasta chamada images no mesmo diretório do seu arquivo .py.
  3. Dentro da pasta images, adicione uma imagem quadrada simples (pode ser um quadrado branco, por exemplo) e salve-a como player_square.png. Você pode criar uma imagem de 32x32 pixels, por exemplo, preenchida com uma cor.
    • Dica: Se não tiver uma imagem, pode usar um editor de imagens online simples (como Piskel ou Pixilart) para criar um quadrado e salvar como player_square.png.
  4. Abra o terminal na pasta onde você salvou o arquivo e execute: pgzrun game_with_menus.py

📝 Exercícios e Desafios

Agora é a sua vez de praticar e expandir este conceito! 💪

Tarefas Básicas:

  • Adicionar um botão "Sair" no menu:
    • Crie um novo Rect e texto para um botão "Sair" na tela de MENU.
    • Na função on_mouse_down, se o game_state for MENU e o clique for no botão "Sair", use exit() para fechar o jogo.
  • Melhorar a aparência dos botões:
    • Altere as cores dos botões.
    • Adicione um contorno aos botões usando screen.draw.rect() (desenhando um retângulo sem preenchimento).
    • Experimente diferentes tamanhos de fonte para o texto.
  • Adicionar uma imagem de fundo:
    • No estado MENU e GAME_OVER, desenhe uma imagem de fundo (ex: screen.blit('background_image', (0,0))) antes de desenhar o texto e os botões. Lembre-se de colocar a imagem na pasta images.

Desafios Avançados:

  • Tela de Pausa:
    • Adicione um novo game_state = 'PAUSED'.
    • Quando o jogador estiver em PLAYING, se ele apertar a tecla P (use on_key_down), mude para o estado PAUSED.
    • Na tela de pausa, desenhe a mensagem "JOGO PAUSADO" e um botão "Continuar".
    • Quando o botão "Continuar" for clicado, volte para o estado PLAYING.
    • Importante: Quando em PAUSED, a função update() NÃO deve executar a lógica do jogo!
  • High Score:
    • Crie uma variável global high_score = 0.
    • Quando o jogo for GAME_OVER, verifique se score é maior que high_score. Se for, atualize high_score.
    • Exiba o high_score na tela de GAME_OVER e, opcionalmente, na tela de MENU.
  • Menu de Opções:
    • Adicione um botão "Opções" na tela de MENU.
    • Ao clicar, mude para um novo game_state = 'OPTIONS'.
    • Na tela de opções, você pode desenhar texto como "Volume: [ ]" ou "Dificuldade: [ ]" (sem funcionalidade real ainda, apenas visual).
    • Adicione um botão "Voltar ao Menu" para retornar ao MENU.

📝 Resumo e Próximos Passos

Nesta aula, aprendemos a:

  • Utilizar uma variável de game_state para controlar o fluxo do jogo.
  • Desenhar interfaces de usuário simples, como títulos, mensagens e "botões" usando screen.draw.text() e screen.draw.filled_rect().
  • Implementar interatividade com o mouse usando on_mouse_down() e Rect.collidepoint().
  • Criar uma função reset_game() para garantir que o jogo possa ser reiniciado de forma limpa.

Com esses conceitos, seus jogos se tornam muito mais amigáveis e completos! 🎉

Na próxima aula, vamos explorar como adicionar sons e música aos nossos jogos, elevando ainda mais a imersão e a experiência do jogador! 🎶

© 2025 Escola All Dev. Todos os direitos reservados.

Criando Telas de Menu e Game Over - Game Maker: Python com Pgzero para Crianças | escola.all.dev.br