Aula 01 – Criando games em python
Aula 01 – Criando games em python – Utilizando o Tkinter
Voltar para página principal do blog
Todas as aulas desse curso
Aula 02
Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook
Esse é o link do código fluente no Pinterest
Meus links de afiliados:
Hostinger
Digital Ocean
One.com
Para baixar o código acesse o link abaixo:
https://github.com/toticavalcanti/curso_python_games/Jogo_Breakout/aula_01/
Link da documentação oficial do Tkinter:
https://tkdocs.com/
Uma visão geral do jogo Breakout
O jogo Breakout começa com um rebatedor e uma bola na parte inferior da tela e alguns linhas de tijolos no topo.
O jogador deve eliminar todos os tijolos batendo neles com o bola, que se rebate contra as bordas da tela, os tijolos e o rebatedor inferior.
Como em Pong, que foi o primeiro videojogo lucrativo da história, e deu origem a um novo setor da indústria, o jogador controla o movimento horizontal do rebatedor.
O jogador começa o jogo com três vidas e se ele perder o rebote da bola e atingir a borda inferior da tela, uma vida é perdida.
O jogo acaba quando todos os tijolos são destruídos, ou quando o jogador perde todas as suas vidas.
Esta é uma captura de tela da versão final do nosso jogo:
Dicas de livros relacionados:
O layout básico da GUI( Graphical User Interface )
Vamos começar o jogo criando uma janela de nível superior.
Usaremos o Tkinter para essa interface.
O Tkinter é um framework para criação de interfaces gráficas do usuário em python.
Veja a lista abaixo, ela mostra além do Tkinter, outros frameworks para desenvolver interfaces gráficas em Python:
- WxWidgets;
- Tkinter;
- Kivy;
- PyGTK;
- PySide;
- QT.
O Tkinter já vem com a instalação padrão do python, com exceção de algumas distribuições Linux, nesses casos é necessário fazer o download do módulo e a instalação.
Nesse link você encontrará os detalhes de como instalar o Tkinter, caso seja necessário.
https://tkdocs.com/tutorial/install.html
Usaremos dois widgets aninhados: um container frame e o canvas, isto é, a tela onde os objetos do jogo serão desenhados:
Com o Tkinter podemos fazer isso usando o seguinte código:
import tkinter as tk
lives = 3
root = tk.Tk()
frame = tk.Frame(root)
canvas = tk.Canvas(frame, width=600, height=400, bg='#aaaaff')
frame.pack()
canvas.pack()
root.title('Primeira Janela')
root.mainloop()
Através do tk, acessamos as classes definidas no módulo tkinter, tk.Frame(moldura), e tk.Canvas(tela).
O tk é o apelido do tkinter no nosso código.
Quando fizemos: import tkinter as tk, apelidamos o tinker de tk.
Observe o primeiro argumento de cada chamada do construtor que indica o widget (child container) , e o pack() é chamado para exibir os widgets no container pai.
O pack() é o gerenciador de geometria que organiza widgets em blocos antes de colocá-los no widget pai.
Isso não é necessário para a instância Tk, já que é a janela raiz.
No entanto, essa abordagem não é exatamente orientada a objetos, já que usamos variáveis globais e não definimos nenhuma nova classe para representar nossas novas estruturas de dados.
Se a base de código cresce, isso pode levar a projetos mal organizados e a códigos altamente acoplados.
Podemos começar a encapsular as peças do nosso jogo dessa maneira, crie o arquivo abaixo:
/python_games/aula_01/exemplo_01.py
import tkinter as tk
class Game(tk.Frame):
def __init__(self, master):
super(Game, self).__init__(master)
self.lives = 3
self.width = 610
self.height = 400
self.canvas = tk.Canvas(self, bg='#aaaaff',
width=self.width,
height=self.height)
self.canvas.pack()
self.pack()
if __name__ == '__main__':
root = tk.Tk()
root.title('Janela do Game!')
game = Game(root)
#essa linha é só para abrir a janela, é a chamada a instância do Game.
game.mainloop()
O mainloop() é um método que é usado quando tá tudo pronto para o aplicativo ser executado.
O mainloop() é um loop infinito usado para executar o aplicativo e esperar que um evento ocorra para processar esse evento até que a janela seja fechada.
Ele só para de executar quando a janela é fechada.
Nosso novo tipo, chamado Game, herda da classe Frame do Tkinter.
A classe Game (tk.Frame): define o nome da classe e da superclasse entre parênteses.
Se você é novo em programação orientada a objetos com Python, esta sintaxe pode não parecer familiar.
Se for esse seu caso, acesse as aulas de orientação a objetos em python aqui do blog:
https://www.codigofluente.com.br/aula-15-python-orientacao-a-objeto-01/
https://www.codigofluente.com.br/aula-16-python-orientacao-a-objetos-02/
Os conceitos mais importantes aqui são o método __init__ e a variável self:
- O método __init__ é um método especial que é invocado quando uma nova instância de classe é criada. Aqui, definimos os atributos do objeto, como largura, altura e widget de tela. Também chamamos a inicialização da classe pai com o super (Game, self) .__ init __ (master), então o estado inicial do Frame é propriamente inicializado.
- A variável self refere-se ao objeto em memória, a instância do Game na memória, e deve ser o primeiro argumento de um método se você quiser acessar a instância dele. Não é estritamente uma palavra-chave da linguagem, mas, uma convenção do Python, equivalente ao this do Java.
No pedaço de código anterior, introduzimos a condição if __name__ == ‘__main__’, que está presente em muitos scripts Python.
Na aula 13 do curso de python aqui do blog código fluente tem uma explicação mais detalhada sobre o if __name__ == ‘__main__’: https://www.codigofluente.com.br/aula-13-python-modules-modulos/
Execute o código do /python_games/aula_01/exemplo_01.py.
python /python_games/aula_01/exemplo_01.py
Ou se o terminal já tiver na mesma pasta é só executar:
python exemplo_01.py
O loop principal será executado indefinidamente até você clicar no botão fechar da janela, ou então, você pode matar o processo a partir da linha de comando.
Este é o ponto de partida do nosso jogo, por isso vamos começar a mergulhar no widget Canvas e ver como podemos desenhar e animar itens nele.
Widget de Tela
Até agora, temos a janela configurada e podemos começar a desenhar itens na tela.
O widget de tela é bidimensional e usa o sistema de coordenadas cartesianas.
A origem, o par ordenado (0, 0), é colocado no canto superior esquerdo e o eixo pode ser representado conforme mostrado na captura de tela a seguir:
Mantendo este layout em mente, podemos usar dois métodos do widget Canvas para desenhar o rebatedor, os tijolos e a bola:
- canvas.create_rectangle(x0, y0, x1, y1, **options)
- canvas.create_oval(x0, y0, x1, y1, **options)
Cada uma dessas chamadas retorna um inteiro, que identifica o item.
Esta referência é usada posteriormente para manipular a posição do item e suas opções.
A sintaxe das opções, representa um par chave / valor de argumentos adicionais que podem ser passados para a chamada do método.
Em nosso caso, usaremos o fill e as tags options.
As coordenadas x0 e y0 indicam o canto superior esquerdo do objeto e x1 e y1 são indicam o canto inferior direito.
Por exemplo, podemos chamar canvas.create_rectangle (250, 300, 330, 320, fill = ‘blue’, tags = ‘rebatedor’) para criar o rebatedor de um jogador, onde:
- O canto superior esquerdo está nas coordenadas (250, 300).
- O canto inferior direito está nas coordenadas (300, 320).
- O fill = ‘blue’ significa que a cor de fundo do item é azul.
- As tags = ‘rebatedor’ significa que o item é marcado como um rebatedor. Esta string será
útil mais tarde para encontrar itens na tela com tags específicas.
Vamos invocar outros métodos do Canvas para manipular os itens e recuperar o widget em formação.
Esta tabela fornece as referências ao widget Canvas que será usado nessas aulas:
Método | Descrição |
---|---|
canvas.coords(item) | Retorna as coordenadas da caixa delimitadora de um item. |
canvas.move(item, x, y) | Move um item fazendo um deslocamento horizontal e vertical. |
canvas.delete(item) | Exclui um item da tela. |
canvas.winfo_width() | Recupera a largura da tela. |
canvas.itemconfig(item, **options) | Altera as opções de um item, como a cor de preenchimento ou suas tags. |
canvas.bind(event, callback) | Vincula um evento de entrada com a execução de uma função. O manipulador de retorno de chamada recebe um parâmetro do tipo Tkinter event. |
canvas.unbind(event) | Desvincula o evento de entrada para que não haja nenhuma função de retorno de chamada executada quando o evento ocorre. |
canvas.create_text(*position, **opts) | Desenha o texto na tela. A posição e os argumentos de opções são semelhantes aos passados em canvas.create_rectangle e canvas.create_oval. |
canvas.find_withtag(tag) | Retorna os itens com uma tag específica. |
canvas.find_overlapping(*position) | Retorna os itens que se sobrepõem ou são completamente delimitados por um determinado retângulo. |