Gerando Meteoros Automaticamente - Chuva de Meteoros

30/04/2026
iniciante pygame python 2d guia série

No capítulo anterior, criamos um meteoro e implementamos sua rotação. Mas ele ainda paira congelado na tela, sozinho e inofensivo.

Um único meteoro estático não faz jogo. Vamos transformar isso em uma chuva real: vários meteoros gerados automaticamente, caindo em ritmo contínuo.

Ao longo deste capítulo você aprenderá a:

Para criar essa chuva de meteoros, primeiro precisamos automatizar a criação deles. Em vez de montar cada meteoro manualmente, vamos ensinar o jogo a gerar novos meteoros sempre que necessário.

Criando Função de Geração de Meteoros


Até aqui usamos diversas funções fornecidas pelo Python e Pygame como:

Agora vamos criar a nossa própria função.

Uma função é um bloco de código que recebe uma tarefa específica. Em vez de repetir as mesmas instruções várias vezes, podemos agrupá-las em uma função e executá-las sempre que necessário.

Pense em uma função como uma receita. Você escreve os passos uma única vez e pode executá-los sempre que precisar.

Vamos criar a função criar_meteoro(). Ela será responsável por montar a estrutura de cada meteoro — a mesma que construímos no capítulo anterior.

def criar_meteoro():
    meteoro_img = pygame.image.load("img/meteoro.png")
    meteoro = {
        "imagem": meteoro_img,
        "x": random.randint(0, janela.get_width()),
        "y": -100,
        "velocidade": 2,
        "rotacao": 0,
        "dir_rotacao": random.randint(-1, 1)
    }
    return meteoro

Toda função criada em Python começa com a palavra-chave def, seguida do nome da função e dos parênteses. Tudo que estiver indentado abaixo dela fará parte da função.

A palavra-chave return encerra a execução da função e envia o valor indicado para quem a chamou.

Quando escrevemos meteoro = criar_meteoro(), o Python executa a função e deposita o dicionário retornado dentro da variável meteoro.

A função criar_meteoro() cria um novo meteoro e nos retorna a sua estrutura. Assim podemos acessar seus valores normalmente.

Note que a posição x do meteoro foi alterada para um número aleatório entre 0 e janela.get_width().

Também alteramos sua posição y para -100 deixando o meteoro na parte de cima fora da tela.

Mas como vamos ter vários meteoros ao mesmo tempo. Ainda precisamos de uma estrutura para armazená-los: as listas.

Criando Vários Meteoros


Trabalhamos com dicionários desde o capítulo 2 para estruturar a nave e o meteoro.

As listas funcionam de forma complementar: em vez de organizar dados por nome de chave, elas armazenam os valores em sequência. O que as torna ideais para guardar uma coleção de itens do mesmo tipo, como vários meteoros.

Em dicionários identificamos as informações usando as chaves criadas para cada valor.

meteoro = {
  "velocidade": 2
}
meteoro["velocidade"] #> Obtem a velocidade do meteoro

Nas listas os valores possuem um índice. A contagem dos valores começa pelo índice 0.

meteoros = ["meteoro_1", "meteoro_2", "meteoro_3"]
meteoros[1] #> Obtem o segundo meteoro da lista

Vamos criar uma lista para armazenar todos os meteoros. Dentro dessa lista vamos adicionar 3 meteoros temporariamente.

meteoros = [criar_meteoro(), criar_meteoro(), criar_meteoro()]

Agora vamos ver como podemos desenhar e mover esse meteoros usado essa lista.

Atualizando Lista de Meteoros


Depois de armazenar vários meteoros na lista, precisamos executar a mesma lógica para cada um deles.

Para isso vamos percorrer todos os itens usando um loop for.

for meteoro in meteoros:
    meteoro["y"] += meteoro["velocidade"]

    meteoro["rotacao"] += meteoro["dir_rotacao"]

    imagem_rotacionada = pygame.transform.rotate(meteoro["imagem"], meteoro["rotacao"])
    retangulo_rotacionado = imagem_rotacionada.get_rect(center = (meteoro["x"], meteoro["y"]))
    janela.blit(imagem_rotacionada, retangulo_rotacionado)

Dentro do loop, movemos o meteoro para baixo incrementando sua posição y com sua velocidade.

Também movemos a lógica criada para desenhar o meteoro no capítulo anterior para dentro do loop.

Ao executar o jogo você verá 3 meteoros caindo em direção a nave.

Temos apenas três meteoros e mais nenhum é gerado depois. Vamos fazer com que um novo meteoro seja gerado em um intervalo de tempo.

Gerando Meteoros Automaticamente


Temos uma função para criar um meteoro e uma lista para armazená-los.

Agora só falta gerar os meteoros de forma automática. Para isso vamos usar o sistema de eventos do Pygame.

Com a base do sistema de eventos já estabelecida — usamos pygame.QUIT para detectar o fechamento da janela — agora vamos um passo alem.

Vamos criar o nosso próprio evento personalizado. O Pygame reserva o identificador pygame.USEREVENT justamente para isso.

criar_novo_meteoro = pygame.USEREVENT + 1
pygame.time.set_timer(criar_novo_meteoro, 1500)

Aqui criamos um novo evento chamado criar_novo_meteoro e adicionamos um temporizador para que o evento seja acionado a cada 1,5 segundo.

Ao usar pygame.USEREVENT + 1 evita conflitos quando você criar vários eventos personalizados.

Dentro do gerenciamento de eventos no game loop, vamos fazer com que um novo meteoro seja adicionado à lista quando o evento for executado.

Para isso usamos um loop for, apresentado no primeiro capítulo:

for evento in pygame.event.get():
    ...

    if evento.type == criar_novo_meteoro:
        meteoro = criar_meteoro()
        meteoros.append(meteoro)

Listas em Python possuem métodos nativos para manipular seus valores. append() é um deles — ele adiciona um novo elemento ao final da lista.

Agora podemos deixar a lista de meteoros vazia.

meteoros = []

Ao executar o jogo, você verá que os meteoros serão gerados continuamente, criando uma chuva de meteoros.

O que Aprendemos até Agora?


Aqui você criou uma chuva de meteoros funcional, adicionando um perigo real para a nave, que será obrigada a se mover e desviar dos obstáculos.

Neste capítulo você:

Código Completo


import pygame
import random

pygame.init()
janela = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()

nave_img = pygame.image.load("img/nave.png")
nave = {
    "imagem": nave_img,
    "x": janela.get_width() // 2 - nave_img.get_width() // 2,
    "y": janela.get_height() // 2 - nave_img.get_height() // 2,
    "velocidade": 5,
}

def criar_meteoro():
    meteoro_img = pygame.image.load("img/meteoro.png")
    meteoro = {
        "imagem": meteoro_img,
        "x": random.randint(0, janela.get_width()),
        "y": -100,
        "largura": meteoro_img.get_width(),
        "altura": meteoro_img.get_height(),
        "velocidade": 2,
        "rotacao": 0,
        "dir_rotacao": random.randint(-1, 1),
    }
    return meteoro

meteoros = []

criar_novo_meteoro = pygame.USEREVENT + 1
pygame.time.set_timer(criar_novo_meteoro, 1500)

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

        if evento.type == criar_novo_meteoro:
            meteoro = criar_meteoro()
            meteoros.append(meteoro)

    teclas = pygame.key.get_pressed()

    if teclas[pygame.K_w]:
        nave["y"] -= nave["velocidade"]
    if teclas[pygame.K_s]:
        nave["y"] += nave["velocidade"]
    if teclas[pygame.K_a]:
        nave["x"] -= nave["velocidade"]
    if teclas[pygame.K_d]:
        nave["x"] += nave["velocidade"]

    if nave["x"] <= 0:
        nave["x"] = 0
    elif nave["x"] + nave["imagem"].get_width() >= janela.get_width():
        nave["x"] = janela.get_width() - nave["imagem"].get_width()

    if nave["y"] <= 0:
        nave["y"] = 0
    elif nave["y"] + nave["imagem"].get_height() >= janela.get_height():
        nave["y"] = janela.get_height() - nave["imagem"].get_height()

    janela.fill("black")

    janela.blit(nave["imagem"], (nave["x"], nave["y"]))

    for meteoro in meteoros:
        meteoro["y"] += meteoro["velocidade"]

        meteoro["rotacao"] += meteoro["dir_rotacao"]

        imagem_rotacionada = pygame.transform.rotate(meteoro["imagem"], meteoro["rotacao"])
        retangulo_rotacionado = imagem_rotacionada.get_rect(center = (meteoro["x"], meteoro["y"]))
        janela.blit(imagem_rotacionada, retangulo_rotacionado)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Próximo Passo: Implementando Colisões


A chuva de meteoros está funcionando. Mas o jogo não sabe que eles existem de verdade. Um meteoro pode atravessar a nave inteira sem consequência.

No próximo capítulo vamos mudar isso: vamos ensinar o Pygame a detectar o momento exato em que dois objetos se tocam, encerrando o jogo quando a nave for atingida.