Aula 01 - Criando games em python - Utilizando o Tkinter
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:
Para baixar o código acesse o link abaixo:
Link da documentação oficial do Tkinter:
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.
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. |
Você pode conferir uma referência completa da sintaxe dos eventos, bem como alguns exemplos em:
Ficamos por aqui e até a próxima.
Para baixar o código acesse o link abaixo:
Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook
Link do código fluente no Pinterest
Novamente deixo meus link de afiliados:
Obrigado, até a próxima e bons estudos. ;)