Game Maker: Python com Pgzero para Crianças
Organizando o Código com Funções
Aprenda sobre organizando o código com funções
Aula: Organizando o Código com Funções
Olá, futuros desenvolvedores de jogos! 👋 Sejam bem-vindos a mais uma aula emocionante do nosso curso. Até agora, vocês aprenderam a fazer personagens se moverem, a desenhar coisas na tela e a interagir com o teclado. Mas, à medida que seus jogos ficam mais complexos, o código pode começar a ficar um pouco bagunçado, não é? 😅
Nesta aula, vamos aprender uma ferramenta superpoderosa para manter nosso código limpo, organizado e fácil de entender: as funções! Elas são como pequenas caixas de ferramentas que guardam um pedaço específico do seu código, pronto para ser usado quando você precisar.
🎯 Objetivos da Aula:
- Entender o que são funções e por que elas são importantes.
- Aprender a criar suas próprias funções em Python com Pgzero.
- Saber como passar informações para as funções (parâmetros).
- Ver como funções podem retornar valores.
- Praticar a organização do código do seu jogo usando funções.
1. Introdução: Por Que Organizar o Código? 🤔
Imaginem que vocês estão construindo uma casa de LEGO. Se todas as peças estivessem misturadas em uma única caixa gigante, seria muito difícil encontrar o que você precisa, certo? 😫
Com o código é a mesma coisa! Quando escrevemos um jogo, temos muitas tarefas diferentes:
- Desenhar o jogador.
- Mover o inimigo.
- Verificar se o jogador pegou uma moeda.
- Atualizar a pontuação.
- Reproduzir um som.
Se colocarmos todo esse código em um único lugar (como dentro das funções draw() ou update() do Pgzero), ele se torna:
- Difícil de ler: Uma parede de texto sem pausas.
- Difícil de modificar: Mudar uma pequena parte pode afetar outras sem querer.
- Difícil de reutilizar: Se você precisa desenhar um tipo de inimigo várias vezes, teria que copiar e colar o código. 😱
É aí que as funções entram! Elas nos permitem agrupar um conjunto de instruções que realizam uma tarefa específica, dando a esse grupo um nome. Pensem nelas como "mini-programas" dentro do seu programa principal.
2. Explicação Detalhada com Exemplos 🧑🏫
O que é uma Função?
Uma função é um bloco de código que só é executado quando é chamado. Você define a função uma vez e pode chamá-la (executá-la) quantas vezes quiser, de qualquer lugar do seu programa.
Como Definir uma Função?
Em Python, usamos a palavra-chave def (de "define") para criar uma função, seguida do nome da função, parênteses () e dois pontos :. O código que faz parte da função deve ser indentado (com espaços ou tab).
# Exemplo 1: Uma função simples que diz "Olá!"
def saudar():
print("Olá, aventureiro!")
print("Bem-vindo ao meu jogo!")
# Nada acontece até chamarmos a função!Como Chamar uma Função?
Para executar o código dentro de uma função, você simplesmente escreve o nome dela seguido de parênteses ().
# Chamando a função que definimos acima
saudar()
# Saída:
# Olá, aventureiro!
# Bem-vindo ao meu jogo!
saudar() # Podemos chamar a mesma função várias vezes!
# Saída:
# Olá, aventureiro!
# Bem-vindo ao meu jogo!Parâmetros e Argumentos: Passando Informações para as Funções 📥
Muitas vezes, uma função precisa de algumas informações para fazer seu trabalho. Por exemplo, uma função para desenhar um personagem pode precisar saber onde ele deve ser desenhado (posição X e Y). Essas informações são chamadas de parâmetros na definição da função e argumentos quando a função é chamada.
# Exemplo 2: Função com parâmetros
def desenhar_mensagem(texto, cor):
print(f"Desenhando: '{texto}' na cor {cor}")
# No Pgzero, usaríamos algo como: screen.draw.text(texto, (10, 10), color=cor)
# Chamando a função com argumentos
desenhar_mensagem("Pontuação: 100", "white")
# Saída: Desenhando: 'Pontuação: 100' na cor white
desenhar_mensagem("Fim de Jogo!", "red")
# Saída: Desenhando: 'Fim de Jogo!' na cor redtextoecorsão parâmetros na definição da função."Pontuação: 100"e"white"são argumentos passados para a função.
Retornando Valores de uma Função 📤
Às vezes, uma função faz um cálculo ou processamento e queremos que ela nos dê um resultado de volta. Usamos a palavra-chave return para isso.
# Exemplo 3: Função que retorna um valor
def calcular_dano(ataque_jogador, defesa_inimigo):
dano = ataque_jogador - defesa_inimigo
if dano < 0:
dano = 0 # Dano mínimo é 0
return dano # A função "devolve" o valor de 'dano'
# Usando o valor retornado
dano_causado = calcular_dano(20, 5)
print(f"O jogador causou {dano_causado} de dano.")
# Saída: O jogador causou 15 de dano.
dano_fraco = calcular_dano(5, 10)
print(f"O jogador causou {dano_fraco} de dano.")
# Saída: O jogador causou 0 de dano.Funções no Contexto do Pgzero: Organizando Seu Jogo 🎮
No Pgzero, as funções draw() e update() são chamadas automaticamente. Podemos usar nossas próprias funções para organizar o que acontece dentro delas!
Por exemplo, em vez de ter todo o código de desenho do jogador, inimigos e moedas dentro de draw(), podemos criar funções separadas para cada um:
# Código sem funções (exemplo ruim)
# def draw():
# player.draw()
# enemy.draw()
# coin.draw()
# screen.draw.text("Score: " + str(score), (10, 10), color="white")
# Código com funções (exemplo bom!)
def desenhar_personagens():
player.draw()
enemy.draw()
def desenhar_itens():
coin.draw()
def desenhar_hud(): # HUD = Head-Up Display (informações na tela)
screen.draw.text("Score: " + str(score), (10, 10), color="white")
def draw(): # Agora, draw() fica limpo e fácil de entender!
screen.clear()
desenhar_personagens()
desenhar_itens()
desenhar_hud()Isso torna o código muito mais legível! Se você precisar mudar como o jogador é desenhado, sabe exatamente onde ir: na função desenhar_personagens().
3. Código de Exemplo Oficial (Adaptado para Pgzero) 🚀
A documentação oficial do Pgzero foca nas funcionalidades da biblioteca, mas a forma de usar funções é um conceito fundamental do Python. Vamos adaptar um exemplo simples de jogo para mostrar como as funções podem organizar o código.
Cenário: Um jogador que se move e coleta moedas.
Código "Bagunçado" (para entender o problema):
# game_baguncado.py
WIDTH = 800
HEIGHT = 600
player = Actor('player', (WIDTH / 2, HEIGHT / 2))
coin = Actor('coin', (100, 100))
score = 0
def draw():
screen.clear()
player.draw()
coin.draw()
screen.draw.text(f"Score: {score}", (10, 10), color="white", fontsize=30)
def update():
global score
# Movimento do jogador
if keyboard.left:
player.x -= 5
if keyboard.right:
player.x += 5
if keyboard.up:
player.y -= 5
if keyboard.down:
player.y += 5
# Limitar o jogador dentro da tela
if player.left < 0:
player.left = 0
if player.right > WIDTH:
player.right = WIDTH
if player.top < 0:
player.top = 0
if player.bottom > HEIGHT:
player.bottom = HEIGHT
# Colisão com a moeda
if player.colliderect(coin):
score += 1
coin.pos = (random.randint(50, WIDTH - 50), random.randint(50, HEIGHT - 50))
import randomMesmo para um jogo simples, o update() já está ficando grandinho. Agora, vamos organizar!
Código Organizado com Funções:
# game_organizado.py
import random
WIDTH = 800
HEIGHT = 600
# Cores
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
# Atores
player = Actor('player', (WIDTH / 2, HEIGHT / 2))
coin = Actor('coin', (random.randint(50, WIDTH - 50), random.randint(50, HEIGHT - 50)))
# Variáveis do jogo
score = 0
game_over = False
# --- Funções de Desenho ---
def desenhar_jogador():
"""Desenha o ator do jogador na tela."""
player.draw()
def desenhar_moeda():
"""Desenha o ator da moeda na tela."""
coin.draw()
def desenhar_hud():
"""Desenha o placar e outras informações na tela."""
screen.draw.text(f"Score: {score}", (10, 10), color=WHITE, fontsize=30)
if game_over:
screen.draw.text("GAME OVER!", center=(WIDTH/2, HEIGHT/2), color=BLUE, fontsize=80)
# --- Funções de Lógica do Jogo ---
def mover_jogador():
"""Atualiza a posição do jogador com base nas teclas pressionadas."""
if keyboard.left:
player.x -= 5
if keyboard.right:
player.x += 5
if keyboard.up:
player.y -= 5
if keyboard.down:
player.y += 5
# Limitar o jogador dentro da tela
if player.left < 0:
player.left = 0
if player.right > WIDTH:
player.right = WIDTH
if player.top < 0:
player.top = 0
if player.bottom > HEIGHT:
player.bottom = HEIGHT
def verificar_colisao_moeda():
"""Verifica se o jogador colidiu com a moeda e atualiza o placar."""
global score # Precisamos do 'global' para modificar a variável global 'score'
if player.colliderect(coin):
score += 1
coin.pos = (random.randint(50, WIDTH - 50), random.randint(50, HEIGHT - 50))
# --- Funções Principais do Pgzero ---
def draw():
"""Função principal de desenho do Pgzero."""
screen.clear()
desenhar_jogador()
desenhar_moeda()
desenhar_hud()
def update():
"""Função principal de atualização do Pgzero."""
if not game_over: # Só atualiza se o jogo não acabou
mover_jogador()
verificar_colisao_moeda()
# Exemplo de uma função de evento (opcional, para mostrar mais organização)
def on_mouse_down(pos):
"""Função chamada quando o botão do mouse é clicado."""
global game_over
if game_over:
if player.collidepoint(pos): # Se clicou no jogador quando o jogo acabou
print("Clicou no jogador para reiniciar!")
# Reiniciar jogo (exemplo)
score = 0
game_over = False
player.pos = (WIDTH / 2, HEIGHT / 2)
coin.pos = (random.randint(50, WIDTH - 50), random.randint(50, HEIGHT - 50))
else:
print("Clicou em outro lugar.")
Observe como as funções draw() e update() agora estão muito mais curtas e fáceis de ler. Cada função tem uma responsabilidade clara, tornando o código mais modular e fácil de dar manutenção!
4. Exercícios/Desafios: Mão na Massa! 🛠️
Agora é a sua vez de colocar em prática o que aprendeu! Pegue o código game_organizado.py como base e faça as seguintes modificações usando funções.
📝 Tarefas:
-
Tarefa 1: Adicionar um Inimigo Simples 👾
- Crie um novo ator chamado
enemy(use a imagem 'enemy' ou 'alien'). - Crie uma função chamada
desenhar_inimigo()que seja responsável por desenhar oenemy. - Chame
desenhar_inimigo()dentro da funçãodraw().
- Crie um novo ator chamado
-
Tarefa 2: Movimento do Inimigo ➡️⬅️
- Crie uma função chamada
mover_inimigo()que faça o inimigo se mover de um lado para o outro na tela (por exemplo, mudandoenemy.xe invertendo a direção quando ele atinge as bordas). - Chame
mover_inimigo()dentro da funçãoupdate().
- Crie uma função chamada
-
Tarefa 3: Colisão com o Inimigo (Game Over) 💥
- Crie uma função chamada
verificar_colisao_inimigo()que detecta se oplayercolidiu com oenemy. - Se houver colisão, defina a variável
game_overcomoTrue. - Chame
verificar_colisao_inimigo()dentro da funçãoupdate(). - Desafio Extra: Na função
desenhar_hud(), adicione uma condição para que, segame_overforTrue, o placar não seja mais atualizado e uma mensagem "GAME OVER!" apareça no centro da tela. (Já implementado no exemplo, mas revise para entender!)
- Crie uma função chamada
-
Tarefa 4: Reiniciar o Jogo 🔄
- Crie uma função chamada
reiniciar_jogo()que:- Define
score = 0. - Define
game_over = False. - Reseta a posição do
playerpara o centro. - Reseta a posição da
coinpara um lugar aleatório. - Reseta a posição do
enemypara um lugar inicial.
- Define
- Modifique a função
on_mouse_down(pos)para que, se ogame_overforTruee o mouse for clicado em qualquer lugar da tela, a funçãoreiniciar_jogo()seja chamada.
- Crie uma função chamada
Dica: Lembre-se de usar global quando precisar modificar uma variável que foi definida fora da função (como score, game_over, player.pos, etc.).
5. Resumo e Próximos Passos 📚
Parabéns! 🎉 Você deu um grande passo para se tornar um programador mais organizado e eficiente.
O que aprendemos hoje:
- Funções são blocos de código reutilizáveis que realizam uma tarefa específica.
- Elas tornam seu código mais legível, modular e fácil de dar manutenção.
- Usamos
defpara definir uma função e()para chamá-la. - Podemos passar informações para as funções usando parâmetros e argumentos.
- Funções podem nos dar um resultado de volta usando
return. - No Pgzero, funções são essenciais para organizar as lógicas dentro de
draw(),update()e os manipuladores de eventos.
Organizar seu código com funções é uma das habilidades mais importantes que você pode aprender. Isso fará uma enorme diferença na complexidade dos jogos que você poderá criar!
Próximos Passos: Na próxima aula, vamos explorar como lidar com múltiplos objetos do mesmo tipo (por exemplo, vários inimigos ou várias moedas) de uma forma ainda mais elegante, usando listas e talvez até introduzindo o conceito de classes. Preparem-se para mais aventura! 🚀