Adicionando os itens ao jogo

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_03/

Link da documentação oficial do Tkinter:

https://tkdocs.com/

Dicas de livros relacionados:

                                   

O código completo dessa aula é esse, o que tá em azul é o que foi inserido de novo:


import tkinter as tk


class GameObject(object):
    def __init__(self, canvas, item):
        self.canvas = canvas
        self.item = item

    def get_position(self):
        return self.canvas.coords(self.item)

    def move(self, x, y):
        self.canvas.move(self.item, x, y)

    def delete(self):
        self.canvas.delete(self.item)
class Ball(GameObject):
    def __init__(self, canvas, x, y):
        self.radius = 10
        self.direction = [1, -1]
        self.speed = 10
        item = canvas.create_oval(x-self.radius, y-self.radius,
                                  x+self.radius, y+self.radius,
                                  fill='white')
        super(Ball, self).__init__(canvas, item)
class Paddle(GameObject):
    def __init__(self, canvas, x, y):
        self.width = 80
        self.height = 10
        self.ball = None
        item = canvas.create_rectangle(x - self.width / 2,
                                       y - self.height / 2,
                                       x + self.width / 2,
                                       y + self.height / 2,
                                       fill='blue')
        super(Paddle, self).__init__(canvas, item)
    def set_ball(self, ball):
        self.ball = ball
    def move(self, offset):
        coords = self.get_position()
        width = self.canvas.winfo_width()
        if coords[0] + offset >= 0 and coords[2] + offset <= width:
            super(Paddle, self).move(offset, 0)
            if self.ball is not None:
                self.ball.move(offset, 0)
class Brick(GameObject):
    COLORS = {1: '#999999', 2: '#555555', 3: '#222222'}
    def __init__(self, canvas, x, y, hits):
        self.width = 75
        self.height = 20
        self.hits = hits
        color = Brick.COLORS[hits]
        item = canvas.create_rectangle(x - self.width / 2,
                                       y - self.height / 2,
                                       x + self.width / 2,
                                       y + self.height / 2,
                                       fill=color, tags='brick')
        super(Brick, self).__init__(canvas, item)
    def hit(self):
        self.hits -= 1
        if self.hits == 0:
            self.delete()
        else:
            self.canvas.itemconfig(self.item,
                                   fill=Brick.COLORS[self.hits])
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()
        self.items = {}
        self.ball = None
        self.paddle = Paddle(self.canvas, self.width/2, 326)
        self.items[self.paddle.item] = self.paddle
        for x in range(5, self.width - 5, 75):
            self.add_brick(x + 37.5, 50, 2)
            self.add_brick(x + 37.5, 70, 1)
            self.add_brick(x + 37.5, 90, 1)
        self.hud = None
        self.setup_game()
        self.canvas.focus_set()
        self.canvas.bind('',
                         lambda _: self.paddle.move(-10))
        self.canvas.bind('',
                         lambda _: self.paddle.move(10))
    def setup_game(self):
           self.add_ball()
           self.update_lives_text()
           self.text = self.draw_text(300, 200,
                                      'Press Space to start')
           self.canvas.bind('', lambda _: self.start_game())
    def add_ball(self):
        if self.ball is not None:
            self.ball.delete()
        paddle_coords = self.paddle.get_position()
        x = (paddle_coords[0] + paddle_coords[2]) * 0.5
        self.ball = Ball(self.canvas, x, 310)
        self.paddle.set_ball(self.ball)
    def add_brick(self, x, y, hits):
        brick = Brick(self.canvas, x, y, hits)
        self.items[brick.item] = brick
    def draw_text(self, x, y, text, size='40'):
        font = ('Helvetica', size)
        return self.canvas.create_text(x, y, text=text, font=font)
    def update_lives_text(self):
        text = 'Lives: %s' % self.lives
        if self.hud is None:
            self.hud = self.draw_text(50, 20, text, 15)
        else:
            self.canvas.itemconfig(self.hud, text=text)
    def start_game(self):
        pass
if __name__ == '__main__':
    root = tk.Tk()
    root.title('Breakout Game')
    game = Game(root)
    game.mainloop()

Vamos a explicação do código.

Agora que a organização de nossos itens está separada nessas classes de nível superior, podemos estender o método __init__() da nossa classe Game.

Inicialização

Essa inicialização é mais complexa do que a que vimos na aula passada. O master que o __init__() do Game recebe como parâmetro, é sua classe pai( tk.Frame ),  que será passado para a nova instância da classe Game quando for inicializada.

Nós podemos dividir a inicialização em duas seções:

Primeira, a instanciação do objeto jogo e sua inserção no dicionário self.items. Este atributo contém todos os itens da tela que podem colidir com a bola, portanto, adicionamos apenas os tijolos e o rebatedor do jogador. As chaves são referências aos itens da tela e os valores são os objetos do jogo correspondentes. Vamos usar esse atributo mais tarde na verificação de colisão, quando teremos os itens em colisão e precisaremos buscar o objeto do jogo. E a segunda, a ligação da chave de entrada, através do Canvas widget. A chamada canvas.focus_set () define o foco na tela, para que os eventos de entrada sejam diretamente vinculados a esse widget. Em seguida, vinculamos as teclas esquerda e direita ao método move() do rebatedor e à barra de espaço para acionar o início do jogo. Graças à construção lambda, podemos definir funções anônimas como manipuladores de eventos. Como o argumento de retorno de chamada do método bind() é uma função que recebe um evento Tkinter como argumento, definimos um lambda que ignora o primeiro parâmetro( lambda _: <expressão> ).

Adiciona Bola e Adiciona Tijolo

Nossos novos métodos add_ball() e add_brick() são usados para criar objetos de jogo e executar uma inicialização básica. O primeira cria uma nova bola em cima da rebatedor do jogador e o segundo é um atalho para adicionar uma instância do tijolo( brick ).

Desenha o Texto

O método draw_text() será usado para exibir mensagens de texto na tela. O item criado com canvas.create_text() é retornado e pode ser usado para modificar as informações.

Mostra e Atualiza o número de vidas

O método update_lives_text() exibe o número de vidas restantes e altera seu texto quando uma vida é perdida. O update_lives_text() é chamado quando o jogo é inicializado, o texto é desenhado pela primeira vez e também é invocado quando o jogador erra um rebote da bola. Deixamos start_game() não implementado por enquanto, pois ele aciona o ciclo do jogo e essa lógica será adicionada mais a frente. Como o Python requer um bloco de código para cada método, usamos a declaração pass. Isso não executa nenhuma operação e pode ser usado como um espaço reservado quando uma declaração é necessária sintaticamente. Executando o script, ele exibirá uma janela do Tkinter como a mostrada na figura abaixo. Nesse ponto, podemos mover a raquete horizontalmente, para estarmos prontos para iniciar o jogo e bater em alguns tijolos.

;)

Ficamos por aqui e até a próxima.

Para baixar o código acesse o link abaixo:

https://github.com/toticavalcanti/curso_python_games/exemplo_03/

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:

Hostinger

Digital Ocean

One.com

Obrigado, até a próxima e bons estudos. ;)