Seja muito bem-vindo à Academy Code Christ!
| 🌍 Este site está disponível em vários idiomas. Fique à vontade para usar o tradutor no topo da página e aprender no seu idioma. |
Se você já domina o básico do Python, o próximo passo emocionante é aprender a lidar com multimídia: imagens, sons e colisões em tempo real.
Hoje, na Academy Code Christ, vamos construir um jogo de ação completo onde você controla um arqueiro que deve proteger o céu!
📝 O que aprenderemos hoje?
● Gerenciamento de Assets: Como carregar imagens e sons externos.
● Sistema de Som: Usar o mixer do Pygame para disparos e colisões.
● Lógica de Listas: Controlar múltiplas flechas e inimigos simultaneamente.
● Colisões Dinâmicas: Detectar o exato momento em que a flecha atinge o alvo.
🛠️ Preparação dos Arquivos
Para este
jogo rodar, você precisará dos seguintes arquivos na mesma pasta do seu código:
1. Imagens: céu.jpg, arqueiro.png, flecha.png e balão2.png.
céu.jpg → Para esse jogo eu usei as imagens do Pixabay
Escolhi essa 👉 imagem 👇 Retirei esse anzol no Paint
Mesmo com essa falha no meio deu certo
balão2.png. → Também peguei no Pixabay. Também "lá ele" tirei o fundo no iloveimg.com
2. Sons: Crie uma pasta chamada sond e coloque disparo.wav, colisao com jogador.wav, etc.
Veja como ficou no Python
disparo.wav → Também peguei no Pixabay, só que você tem quer selecionar a opção → Efeitos Sonoros e digitar: Disparo 👉 Link aqui onde peguei
💻 O Código Completo do Jogo
Aqui está
a estrutura profissional para o seu jogo:
import
pygame
import
random
#
Inicializando o pygame
pygame.init()
#
Configurações da tela
tamanho_tela
= (800, 600)
tela =
pygame.display.set_mode(tamanho_tela)
pygame.display.set_caption("Jogo
de Tiro com Arco")
# Cores
BRANCO =
(255, 255, 255)
PRETO =
(0, 0, 0)
VERMELHO =
(255, 0, 0)
# Carregar
a imagem de fundo
fundo =
pygame.image.load("céu.jpg") #
Coloque o caminho da sua imagem de fundo
fundo =
pygame.transform.scale(fundo, (800, 600))
# Ajuste para o tamanho da tela (800x600)
# Carregar
sons
pygame.mixer.init() # Inicializa o mixer de som
som_disparo
= pygame.mixer.Sound("sond/disparo.wav") # Som do disparo
som_colisao_inimigo
= pygame.mixer.Sound("sond/flecha colidindo com o balão.mp3") # Som da colisão com o balão
som_colisao_jogador
= pygame.mixer.Sound("sond/colisao com jogador.wav") # Som da colisão com o jogador
# Classe
da nave do jogador
class
Nave:
def __init__(self):
self.imagem =
pygame.image.load("arqueiro.png")
# Coloque o caminho da sua imagem do arquiro
self.rect = self.imagem.get_rect()
self.rect.center = (400, 550) # Inicia no centro inferior da tela
self.velocidade = 30 # Velocidade de movimento da flecha
def mover(self, esquerda, direita, cima,
baixo):
if esquerda and self.rect.left > 0:
self.rect.x -= self.velocidade
if direita and self.rect.right <
800:
self.rect.x += self.velocidade
if cima and self.rect.top > 0:
self.rect.y -= self.velocidade
if baixo and self.rect.bottom < 600:
self.rect.y += self.velocidade
def desenhar(self):
tela.blit(self.imagem, self.rect)
# Classe
da flecha (no lugar do flecha)
class
Flecha:
def __init__(self, x, y):
self.imagem =
pygame.image.load("flecha.png")
# Coloque o caminho da imagem da flecha
self.imagem =
pygame.transform.scale(self.imagem, (30, 100))
# Ajuste o tamanho da flecha
self.rect = self.imagem.get_rect()
self.rect.center = (x, y)
self.velocidade = 7
def mover(self):
self.rect.y -= self.velocidade # A flecha vai para cima (ajuste para
movimento desejado)
def desenhar(self):
tela.blit(self.imagem, self.rect)
# Classe
do inimigo
class
Inimigo:
def __init__(self):
self.imagem =
pygame.image.load("balão2.png")
# Coloque o caminho da imagem do Balão
self.rect = self.imagem.get_rect()
self.rect.center = (random.randint(50,
750), random.randint(-100, -50)) #
Posiçã o aleatória no topo
self.velocidade = 2
def mover(self):
self.rect.y += self.velocidade
def desenhar(self):
tela.blit(self.imagem, self.rect)
# Função
principal do jogo
def
jogo():
# Criando objetos
jogador = Nave()
flechas = [] # Agora temos uma lista de flechas, ao invés
de mísseis
inimigos = [Inimigo() for _ in range(5)]
# Variáveis de controle
clock = pygame.time.Clock()
pontos = 0
vidas = 3
fim_jogo = False
# Loop principal do jogo
while not fim_jogo:
tela.fill(PRETO)
# Desenhar o fundo
tela.blit(fundo, (0, 0)) # Coloca a imagem de fundo na tela
# Movimentos do jogador
esquerda = direita = cima = baixo =
False
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
fim_jogo = True
if evento.type == pygame.KEYDOWN:
if evento.key == pygame.K_LEFT:
esquerda = True
if evento.key ==
pygame.K_RIGHT:
direita = True
if evento.key == pygame.K_UP:
cima = True
if evento.key == pygame.K_DOWN:
baixo = True
if evento.key ==
pygame.K_SPACE:
# Disparar a flecha
flechas.append(Flecha(jogador.rect.centerx,
jogador.rect.top))
som_disparo.play() # Toca o som do disparo
# Mover o arqueiro
jogador.mover(esquerda, direita, cima,
baixo)
# Mover flechas
for flecha in flechas:
flecha.mover()
if flecha.rect.bottom < 0:
flechas.remove(flecha)
# Mover inimigos
for inimigo in inimigos:
inimigo.mover()
if inimigo.rect.top > 600:
inimigos.remove(inimigo)
inimigos.append(Inimigo())
# Verificar colisão com as flechas
for flecha in flechas:
if
flecha.rect.colliderect(inimigo.rect):
flechas.remove(flecha)
inimigos.remove(inimigo)
inimigos.append(Inimigo())
pontos += 10
som_colisao_inimigo.play() # Toca
o som da colisão com inimigo
# Verificar colisão com o jogador
if
jogador.rect.colliderect(inimigo.rect):
vidas -= 1
inimigos.remove(inimigo)
inimigos.append(Inimigo())
som_colisao_jogador.play() # Toca o som da colisão com o jogador
if vidas <= 0:
fim_jogo = True
# Desenhar tudo
jogador.desenhar()
for flecha in flechas:
flecha.desenhar()
for inimigo in inimigos:
inimigo.desenhar()
# Exibir informações
fonte =
pygame.font.SysFont("arial", 30)
texto_pontos =
fonte.render(f"Pontos: {pontos}", True, BRANCO)
tela.blit(texto_pontos, (10, 10))
texto_vidas =
fonte.render(f"Vidas: {vidas}", True, BRANCO)
tela.blit(texto_vidas, (700, 10))
# Atualizar a tela
pygame.display.flip()
clock.tick(60) # 60 FPS
pygame.quit()
# Iniciar
o jogo
jogo()
Tudo tem que estar assim👇
🔍 Mergulhando na Lógica: Entendendo o Código Passo a Passo
Agora que você conhece os arquivos necessários para criar o nosso jogo de tiro com arco, chegou a hora de entender como tudo funciona por dentro!
Vamos estudar o código por partes, de forma simples, para que você consiga compreender a lógica e criar suas próprias modificações.
👣 Inicializando o Pygame 🎮
import pygame
import random
pygame.init()
O que está acontecendo aqui?
- import pygame: importa a biblioteca responsável por criar a janela, mostrar imagens, reproduzir sons e detectar os comandos do jogador.
- import random: permite gerar posições aleatórias para os balões que aparecem no jogo.
- pygame.init(): inicializa os módulos do Pygame necessários para executar o jogo.
Pense nessa etapa como a preparação de todos os equipamentos antes de começar uma partida!
👣 Criando a janela do jogo 🖥️
tamanho_tela = (800, 600)
tela = pygame.display.set_mode(tamanho_tela)
pygame.display.set_caption("Jogo de Tiro com Arco")
Aqui, criamos a janela onde toda a ação acontecerá.
- tamanho_tela = (800, 600): define a largura de 800 pixels e a altura de 600 pixels.
- pygame.display.set_mode(tamanho_tela): cria a janela com as dimensões definidas.
- pygame.display.set_caption(...): coloca o título na barra superior da janela.
Em resumo: estamos preparando o cenário onde o arqueiro poderá se movimentar e acertar os balões.
3. Definindo as cores 🎨
BRANCO = (255, 255, 255)
PRETO = (0, 0, 0)
VERMELHO = (255, 0, 0)
O Pygame representa as cores usando o sistema RGB, que combina vermelho, verde e azul.
Cada cor é definida por três números, que variam de 0 a 255:
- BRANCO = (255, 255, 255): mistura máxima das três cores.
- PRETO = (0, 0, 0): ausência de intensidade das três cores.
- VERMELHO = (255, 0, 0): intensidade máxima do vermelho.
Essas cores serão utilizadas para preencher áreas da tela e exibir informações, como a pontuação e as vidas do jogador.
👣 Carregando a imagem de fundo ☁️
fundo = pygame.image.load("céu.jpg")
fundo = pygame.transform.scale(fundo, (800, 600))
Nesta etapa, colocamos o céu no cenário do jogo.
- pygame.image.load("céu.jpg"): carrega a imagem do arquivo.
- pygame.transform.scale(fundo, (800, 600)): redimensiona a imagem para ocupar toda a janela.
O arquivo céu.jpg precisa estar no local indicado pelo código.
👣 Preparando os efeitos sonoros 🔊
pygame.mixer.init()
som_disparo = pygame.mixer.Sound("sond/disparo.wav")
som_colisao_inimigo = pygame.mixer.Sound(
"sond/flecha colidindo com o balão.mp3"
)
som_colisao_jogador = pygame.mixer.Sound(
"sond/colisao com jogador.wav"
)
Um jogo fica muito mais interessante quando as ações são acompanhadas por sons!
- pygame.mixer.init(): inicializa o sistema de áudio.
- pygame.mixer.Sound(...): carrega cada efeito sonoro.
- som_disparo: representa o som do disparo da flecha.
- som_colisao_inimigo: representa o som da flecha atingindo um balão.
- som_colisao_jogador: representa o som de uma colisão entre o jogador e um inimigo.
Mais adiante, utilizaremos .play() para reproduzir cada som no momento certo.
Atenção: os nomes e as extensões dos arquivos precisam corresponder aos arquivos existentes na pasta sond. O Pygame também precisa conseguir ler o formato de áudio utilizado.
👣 Criando a classe do arqueiro 🏹
class Nave:
def __init__(self):
self.imagem = pygame.image.load("arqueiro.png")
self.rect = self.imagem.get_rect()
self.rect.center = (400, 550)
self.velocidade = 30
Aqui começa a programação do personagem que será controlado pelo jogador.
Embora a classe tenha o nome Nave, neste jogo ela representa o arqueiro.
- class Nave: cria uma classe, que funciona como um modelo para construir o personagem.
- __init__(self): inicializa as características do personagem quando um objeto é criado.
- self.imagem: guarda a imagem do arqueiro.
- self.rect: representa a área retangular usada para posicionar a imagem e verificar colisões.
- self.rect.center = (400, 550): coloca o centro do personagem próximo à parte inferior da tela.
- self.velocidade = 30: define quantos pixels o personagem se desloca a cada atualização em que o movimento é aplicado.
Como o arqueiro se movimenta?
def mover(self, esquerda, direita, cima, baixo):
if esquerda and self.rect.left > 0:
self.rect.x -= self.velocidade
if direita and self.rect.right < 800:
self.rect.x += self.velocidade
if cima and self.rect.top > 0:
self.rect.y -= self.velocidade
if baixo and self.rect.bottom < 600:
self.rect.y += self.velocidade
Esse método verifica em qual direção o jogador deseja se movimentar.
- esquerda: diminui a posição horizontal.
- direita: aumenta a posição horizontal.
- cima: diminui a posição vertical.
- baixo: aumenta a posição vertical.
As condições verificam os limites da janela para evitar que o personagem ultrapasse as bordas, desde que as dimensões da imagem e a velocidade sejam compatíveis com esses limites.
Como o arqueiro aparece na tela?
def desenhar(self):
tela.blit(self.imagem, self.rect)
O método desenhar() utiliza blit() para colocar a imagem do arqueiro na tela, na posição indicada por self.rect.
👣 Criando a classe da flecha ➶
class Flecha:
def __init__(self, x, y):
self.imagem = pygame.image.load("flecha.png")
self.imagem = pygame.transform.scale(
self.imagem, (30, 100)
)
self.rect = self.imagem.get_rect()
self.rect.center = (x, y)
self.velocidade = 7
A classe Flecha define como cada flecha será criada.
- x e y: indicam a posição inicial da flecha.
- pygame.image.load("flecha.png"): carrega a imagem.
- pygame.transform.scale(...): ajusta a imagem para 30 por 100 pixels.
- self.rect.center = (x, y): posiciona o centro da flecha nas coordenadas recebidas.
- self.velocidade = 7: define a velocidade do disparo.
Para fazer a flecha subir, usamos:
def mover(self):
self.rect.y -= self.velocidade
Como a coordenada vertical diminui, a flecha se desloca para cima.
E para desenhá-la:
def desenhar(self):
tela.blit(self.imagem, self.rect)
Cada vez que o jogador dispara, o programa pode criar uma nova flecha.
👣 Criando os balões inimigos 🎈
class Inimigo:
def __init__(self):
self.imagem = pygame.image.load("balão2.png")
self.rect = self.imagem.get_rect()
self.rect.center = (
random.randint(50, 750),
random.randint(-100, -50)
)
self.velocidade = 2
Agora criamos os alvos que o arqueiro deverá acertar.
- balão2.png: imagem do inimigo.
- random.randint(50, 750): escolhe uma posição horizontal aleatória.
- random.randint(-100, -50): escolhe uma posição vertical acima da tela.
- self.velocidade = 2: define a velocidade de descida.
O movimento acontece neste método:
def mover(self):
self.rect.y += self.velocidade
Como a coordenada vertical aumenta, o balão desce pela tela.
O método desenhar() utiliza tela.blit() para mostrar o balão na posição atual.
👣 Iniciando a função principal do jogo ⚙️
def jogo():
jogador = Nave()
flechas = []
inimigos = [Inimigo() for _ in range(5)]
A função jogo() reúne os elementos necessários para começar a partida.
- jogador = Nave(): cria o arqueiro.
- flechas = []: cria uma lista vazia para armazenar as flechas disparadas.
- inimigos = [Inimigo() for _ in range(5)]: cria cinco balões inimigos.
Por que usamos listas?
Porque o jogador poderá disparar várias flechas, e vários balões poderão aparecer ao mesmo tempo. As listas permitem acompanhar todos esses objetos.
Em seguida, preparamos as variáveis de controle:
clock = pygame.time.Clock()
pontos = 0
vidas = 3
fim_jogo = False
- clock: controla a velocidade de atualização do jogo.
- pontos: registra a pontuação, começando em zero.
- vidas: define três vidas iniciais.
- fim_jogo: indica se a partida deve terminar.
👣 Mantendo o jogo em funcionamento 🔄
while not fim_jogo:
Este é um dos trechos mais importantes de todo o programa!
O while repete as instruções enquanto fim_jogo for falso. A cada repetição, o jogo verifica os comandos, movimenta os personagens, confere colisões e atualiza a imagem.
No início de cada ciclo:
tela.fill(PRETO)
tela.blit(fundo, (0, 0))
A primeira instrução preenche a tela de preto. A segunda desenha o fundo do céu por cima dessa cor.
Isso prepara a imagem que será exibida naquele quadro.
👣 Detectando os comandos do jogador ⌨️
for evento in pygame.event.get():
if evento.type == pygame.QUIT:
fim_jogo = True
O programa verifica os eventos da janela. Se o usuário clicar no botão de fechar, fim_jogo recebe True, indicando que o laço principal deverá terminar.
O código também verifica as teclas pressionadas.
if evento.type == pygame.KEYDOWN:
if evento.key == pygame.K_SPACE:
flechas.append(
Flecha(jogador.rect.centerx, jogador.rect.top)
)
som_disparo.play()
Quando a barra de espaço é pressionada:
- Uma nova flecha é criada.
- A flecha é posicionada na região superior do arqueiro.
- O objeto é adicionado à lista flechas.
- O som do disparo é reproduzido.
As setas do teclado são utilizadas para controlar o movimento do arqueiro. Para que ele continue se movimentando enquanto uma tecla fica pressionada, é necessário consultar as teclas com pygame.key.get_pressed() em cada ciclo do jogo.
👣 Movimentando e removendo as flechas 🎯
for flecha in flechas:
flecha.mover()
if flecha.rect.bottom < 0:
flechas.remove(flecha)
O programa percorre a lista de flechas e atualiza a posição de cada uma.
Quando uma flecha ultrapassa a parte superior da tela, ela é removida da lista.
Isso evita manter no jogo objetos que já não podem ser vistos.
Observação técnica: para evitar problemas ao modificar uma lista durante sua iteração, é mais seguro percorrer uma cópia ou construir uma nova lista com os objetos que devem continuar ativos.
👣 Movimentando os inimigos 👾
for inimigo in inimigos:
inimigo.mover()
if inimigo.rect.top > 600:
inimigos.remove(inimigo)
inimigos.append(Inimigo())
Cada inimigo desce pela tela.
Quando um balão ultrapassa a borda inferior, ele é removido e um novo inimigo é criado. Assim, o jogador continua tendo alvos para acertar.
Essa lógica faz com que o jogo permaneça ativo até que o jogador perca todas as vidas ou feche a janela.
👣 Detectando as colisões entre flechas e balões 💥
if flecha.rect.colliderect(inimigo.rect):
flechas.remove(flecha)
inimigos.remove(inimigo)
inimigos.append(Inimigo())
pontos += 10
som_colisao_inimigo.play()
Aqui está uma das principais mecânicas do jogo!
- colliderect(): verifica se os retângulos de dois objetos se sobrepõem.
- flechas.remove(flecha): remove a flecha que atingiu o alvo.
- inimigos.remove(inimigo): remove o balão atingido.
- inimigos.append(Inimigo()): cria um novo balão.
- pontos += 10: adiciona dez pontos à pontuação.
- som_colisao_inimigo.play(): reproduz o efeito sonoro da colisão.
Portanto, quando uma flecha atinge um balão, o jogador ganha dez pontos e um novo alvo aparece.
👣 Detectando colisões com o arqueiro ❤️
if jogador.rect.colliderect(inimigo.rect):
vidas -= 1
inimigos.remove(inimigo)
inimigos.append(Inimigo())
som_colisao_jogador.play()
if vidas <= 0:
fim_jogo = True
Se um balão encostar no arqueiro, o jogador perde uma vida.
- vidas -= 1: diminui uma vida.
- O balão que atingiu o jogador é removido.
- Um novo balão é criado.
- O som da colisão é reproduzido.
- Se as vidas chegarem a zero, a variável fim_jogo passa a ser verdadeira.
Assim, o programa sabe quando a partida deve terminar.
👣 Desenhando os objetos na tela 🖼️
jogador.desenhar()
for flecha in flechas:
flecha.desenhar()
for inimigo in inimigos:
inimigo.desenhar()
Depois de movimentar os objetos e verificar as colisões, o programa desenha o arqueiro, todas as flechas ativas e todos os balões existentes.
Essa etapa é repetida em cada ciclo do jogo para que as imagens acompanhem os movimentos.
👣 Exibindo a pontuação e as vidas 📊
fonte = pygame.font.SysFont("arial", 30)
texto_pontos = fonte.render(
f"Pontos: {pontos}", True, BRANCO
)
tela.blit(texto_pontos, (10, 10))
texto_vidas = fonte.render(
f"Vidas: {vidas}", True, BRANCO
)
tela.blit(texto_vidas, (700, 10))
O jogo também precisa mostrar ao jogador como está sua partida.
- pygame.font.SysFont("arial", 30): seleciona a fonte Arial, tamanho 30.
- fonte.render(...): transforma o texto em uma imagem.
- tela.blit(...): desenha o texto na janela.
- (10, 10) e (700, 10): definem as posições da pontuação e das vidas.
Dessa forma, o jogador consegue acompanhar seu desempenho.
👣 Atualizando a tela e controlando a velocidade ⏱️
pygame.display.flip()
clock.tick(60)
Essas duas instruções finalizam cada ciclo de atualização.
- pygame.display.flip(): apresenta na janela tudo o que foi desenhado no quadro atual.
- clock.tick(60): limita o ciclo a aproximadamente 60 quadros por segundo.
Sem a atualização da tela, as alterações feitas nos desenhos não seriam apresentadas corretamente. Já o controle de quadros ajuda a manter o jogo funcionando em uma velocidade mais consistente.
👣 Encerrando o jogo e iniciando a partida 🏁
No final da função jogo(), encontramos:
pygame.quit()
Essa instrução encerra os módulos do Pygame quando a partida termina.
E, na última parte do programa:
jogo()
A chamada executa a função principal e inicia a partida.
Pronto! Agora você conhece o caminho completo: o programa prepara os recursos, cria os objetos, recebe os comandos do jogador, movimenta as flechas e os balões, detecta colisões, atualiza a pontuação e encerra a partida quando necessário.
✝️
Reflexão: Precisão e Foco
Na programação, cada instrução tem sua função e precisa estar no lugar certo para que o projeto funcione. Da mesma forma, precisamos de foco, paciência e perseverança para alcançar nossos objetivos.
Assim como o arqueiro precisa mirar com atenção, quem aprende programação precisa observar os detalhes, testar suas ideias e aprender com os erros.
“Os teus olhos olhem direitinho, e as tuas pálpebras mirem defronte de ti.” (Provérbios 4:25)
🏆 Desafio do Arqueiro
Agora que você compreendeu a lógica do jogo, que tal experimentar algumas melhorias?
- Níveis de dificuldade: aumente a velocidade dos balões conforme a pontuação cresce.
- Flecha especial: crie um disparo mais rápido ou com tamanho diferente.
- Vidas ilustradas: substitua o texto das vidas por imagens de corações.
- Recorde de pontos: registre a maior pontuação alcançada.
- Tela de encerramento: mostre uma mensagem quando o jogador perder todas as vidas.
Continue praticando! Cada projeto é uma oportunidade de transformar conhecimento em criatividade.








.png)
.png)
Postar um comentário