Como criar um jogo usando Python
Requisitos
- Hello World em Python: caso você nunca tenha visto nada de Python, recomendo começar olhando esse post que explica o básico da linguagem
- Sintaxe Básica do Python: aqui você poderá encontrar uma explicação sobre a sintaxe básica e as principais bibliotecas e funcionalidades da linguagem Python.
- Biblioteca PyGame: aqui você encontrará como instalar a biblioteca e uma explicação sobre todos os comandos usados nesse tutorial.
Repositório do jogo
Definindo o jogo
O primeiro passo é definirmos qual jogo iremos implementar (seu layout, sua mecânica, etc.). Para esse tutorial, optei por recriar o famoso "jogo da cobrinha", ou Snake.
As regras são bem conhecidas, mas vamos recapitular:
- A cobra começa com 3 blocos de comprimento.
- Sempre que ela "comer" uma fruta, ela cresce um bloco e o jogador ganha um ponto.
- Ela tem velocidade constante.
- Se ela encostar em uma parede, ou no próprio corpo, o jogo termina.
- O jogador vence caso não tenha mais espaço para a cobra crescer (boa sorte com isso).
- A cobra só pode girar 90 º por movimento.
- As frutas são geradas em pontos aleatórios da tela.
- A fruta não pode ser gerada em um ponto que já esteja ocupado pela cobra.
Além disso, iremos criar uma tela de game-over informando o score atingido. Também existirá uma mensagem informando que o usuário pode jogar novamente apertando a tecla "Espaço" ou sair do jogo apertando a tecla "Esc".
Estrutura de um jogo
Um ponto que tem que ficar claro antes de programarmos qualquer coisa, é como é uma estrutura padrão de um jogo:
- inicialização de variáveis / criação dos objetos;
- laço infinito até que usuário escolha por sair do jogo;
- verificação de interações do usuário;
- teclas pressionadas;
- movimentação do mouse;
- cliques do mouse;
- etc.
- reset da tela (para a cor de fundo padrão);
- lógica do jogo de acordo com interação (ou falta de) do usuário;
- movimentação de objetos;
- verificação de regras como incremento dos pontos ou fim de jogo;
- etc.
- objetos são desenhados na tela conforme lógica executada.
Agora que sabemos qual a estrutura básica nosso código deve seguir, vamos definir algumas propriedades.
Criando uma pasta para o projeto
Criando a classe Position
Como iremos trabalhar, a todo momento, com a posição dos objetos, iremos criar uma classe que irá encapsular os atributos x e y das posições e alguns métodos úteis, como verificar se uma posição é igual à outra. Para isso, crie um arquivo chamado position.py.
O arquivo deve conter o seguinte:
Definindo as propriedades
Para termos um local único para definição de propriedades e termos fácil acesso à elas, iremos criar um arquivo properties.py, que irá conter:
- Tamanho da área jogável: iremos definir que a área jogável será um quadrado de 600x600.
- O valor da margem padrão (que será diferente da margem do score): 20.
- O valor da margem do score: 80.
- Tamanho total da janela: cálculo considerando o tamanho da área jogável, margem padrão e margem do score.
- Coordenada (x, y) inicial da área jogável: como essa coordenada será usada em diversos locais, faz sentido que esse cálculo seja feita apenas uma vez.
- Coordenada (x, y) final da área jogável: também será bastante usada no código.
- Tamanho dos blocos: os blocos serão a menor unidade de tamanho do jogo. Essa informação será usada para gerar os blocos no tamanho e locais corretos, além de garantir que a cobra tenha um tamanho e movimento correto.
Cores
Vamos criar um arquivo que irá conter o valor RGB para as cores que iremos utilizar no jogo. Isso serve para facilitar a escrita e leitura do código.
Crie um arquivo colors.py:
Score
Vamos criar uma classe que irá representar o score do usuário. Ela precisa:
Guardar o score conforme o usuário joga.
Desenhar na tela a palavra "Score" e, embaixo, a pontuação do usuário.
Portanto, crie um arquivo score.py e, dentro dele, crie a classe Score:
Grid
Agora vamos criar uma classe que irá simplesmente desenhar as linhas da parte jogável da tela para que o usuário saiba até onde ele pode ir.
Cri um arquivo grid.py com o seguinte conteúdo:
Snake
Vamos criar a classe mais importante: a que representa a cobra. Porém, antes disso, precisamos criar uma classe para representar as partes da cobra, visto que cada parte dela tem uma posição e direção de movimento diferentes.
Primeiro, crie um arquivo move_direction.py, que será uma ENUM que irá representar os possíveis movimentos.
Também iremos usar essa enum para garantir que os movimentos sejam de 90º, usando a seguinte lógica: o movimento é inválido caso a sobra da divisão do (valor do próximo movimento menos o valor do movimento atual) por dois seja 0 (move_direction.value - actual_move_direction.value % 2 == 0).
Veja como funciona:
Exemplo 1:
Movimento atual: Left (2)Próximo movimento: Up (1)
(1-2) = -1
-1 % 2 = -1
Portanto, Ir de Left para Up é válido.
Exemplo 2:
Movimento atual: Right(4)Próximo movimento: Left (2)
(2 - 4) = -2
-2 % 2 = 0
Portanto, Ir de Right para Left é inválido.
Enfim, crie o arquivo move_direction.py:
A seguir, crie o arquivo snake_piece.py:

Note que ele tem um método copy(). Usaremos ele para copiar a última parte da cobra quando uma fruta for consumida pela cobra e ela tiver que aumentar de tamanho.
Por fim, vamos criar a classe Snake. Por ser a classe mais importante do jogo, ela é também a mais complexa, então vamos quebrar ela em partes para facilitar a explicação.
Crie um arquivo snake.py e adicione os seguintes imports e o método __init__:
No método __init__(), definimos a cor da cobra como verde, inicializamos a lista que irá conter suas partes, chamamos o método que gera o corpo inicial da cobra (com 3 partes) e definimos a velocidade. É importante definir a velocidade porque quando o usuário pressionar nenhuma tecla de direção, ela deverá se mover constantemente na direção definida.
O método __generate_initial_body() primeiro chama o método __init_head_snake_piece(), que irá encontrar o bloco central da área jogável e criar a primeira parte da cobra ali. Em seguida, partindo dessa posição, são criados mais duas partes à direita.
O método __init_speed() simplesmente define a velocidade como 7 (fique à vontade para alterar esse valor para aumentar ou diminuir a dificuldade do jogo)
Com isso, já conseguimos criar o método para desenhar a cobra na tela:
Para movermos a cobra, precisamos criar o método move, que deve verificar algumas coisas:
- Caso o usuário tenha pressionado uma tecla de direção, ele deve ignorar caso a tecla seja inválida (mesma direção ou direção oposta da atual)
- Caso o usuário não tenha pressionado uma tecla, deve verificar se já é hora de mover a cobra
- Caso seja necessário mover a cobra, deve controlar a lógica de acordo com a direção
- Deve garantir que as partes mudem de direção conforme as demais
Os seguintes métodos verificam se a cobra comeu a fruta (verificando as posições) e, caso positivo, incrementa a cobra:
Por fim, precisamos criar os métodos pra verificar se a cobra colidiu com a parede ou com ela mesma:
Fruta
- Desenhar a fruta na tela.
- Criar a fruta em uma posição válida.
Crie um arquivo food.py:
Agora vamos criar a classe que irá mostrar a:
- Mensagem de Game-Over.
- Pontuação do jogador.
- Mensagem perguntando se ele deseja jogar novamente.
Crie um arquivo game_over.py:
Game Manager
Por fim, vamos criar a classe que irá controlar esses objetos e de fato fazer o jogo rodar.
Por ser a classe que irá controlar todos os objetos, ela também é relativamente grande, então vamos quebrar a criação dela em partes.
Crie a classe game_manager.py e importe as dependências necessárias:
Em seguida, vamos criar os métodos de inicialização das variáveis e objetos e o método de finalização do jogo:
Agora vamos adicionar a estrutura básica, mencionada no início do post:
Vamos adicionar o tratamento de eventos (interações do usuário):
Para finalizar, vamos adicionar a lógica do jogo e o desenho dos objetos:
Pronto!
Testando o jogo
Conclusão
Espero que tenha gostado do pequeno projeto. Apesar de ser um jogo simples, podemos ver que programá-lo não é tão simples como parece, mas é bastante divertido.
Comentários
Postar um comentário