Nesta terceira parte, temos os seguintes objetivos:Limpar as classesVarios avioesMultiplos tiros.Generalizar os objetos do jogo em uma super classeExibir um placarAtribuir teclas para atirar e jogar de novo ou sairNa versao da Parte II, as classes tem muito codigo repetido.Analisando cada uma delas, podemos chegar a conclusao de um comportamento comum quantoa forma de desenhar e atualizar os objetos. Um metodo para retirar o objeto do jogo tambem e utilizado.Todo objeto do jogo precisa ter acesso ao jogo em sim.Embora quase nao utilizemos cores, eu adicionei a cor como parametro, uma vez que pode ser usada para representar multiplos jogadores ou diferentes tipos de objetos.Uma das coisas que nao ficaram claras na versao anterior e o controle de colisao. Na realidade, o controle de colisao que utilizamos e bem basico e dificil de generalizar. Para permitir o controle da colisao entre objetos, cada objeto tera uma posicao x e y na tela, com altura e largura.Desta forma, dois objetos colidem se o retangulo formado pelos pontos:(x, y), (x + largura, y), (x + largura, y + altura), (x, y + altura)De dois objetos tiverem pontos em comum.Como diferentes tipos de objetos colidem entre si, a propriedade colisao guarda o tipo de objeto.Desta forma, podemos separar os tiros do aviao em si.Uma variavel de DEBUG tambem foi adicionada, para mostrar o retangulo de colisao caso precisemos fazer ajustes.class ObjetoDoJogo: def __init__(self, jogo, cor): self.jogo = jogo self.cor = cor self.ativo = True self.colisao = FUNDO self.largura = 0 self.altura = 0 self.x = 0 self.y = 0 self.debug = DEBUGSe debug estiver ativo, vamos desenhar uma caixa em volta do objeto.Desta forma, fica mais facil detectar erros nos limites e no tamanho do objeto. def desenha(self): if self.debug: set_color(2) pyglet.graphics.draw(4, pyglet.gl.GL_LINE_LOOP, ('v2f', (self.x, self.y, self.x + self.largura, self.y, self.x + self.largura, self.y + self.altura, self.x, self.y + self.altura)))A atualizacao das propriedades, embora presente em todos os objetos, nao tem um comportamento padrao.Vamos utilizar apenas pass para marcar o lugar. def atualiza(self): """Calcula nova posicao, atualiza valores a cada frame""" passAqui um metodo para dar uma oportunidade ao objeto de tratar a colisao com outro objeto.Este metodo sera chamado pelo jogo, sempre que dois objetos colidirem. def colidiu(self, outro): """O que fazer em caso de colisao? Recebe o outro objeto""" passE este aqui e o teste de colisao em si, bem simples. Ele so funciona com larguras e alturas positivas. def colide(self, outro): if self.x < outro.x + outro.largura and self.x + self.largura > outro.x and \ self.y < outro.y + outro.altura and self.altura + self.y > outro.y: self.colidiu(outro) outro.colidiu(self)Quando a colisao e detectada, o metodo colidiu dos dois objetos e chamado.E finalmente o metodo para desativar e retirar o objeto do jogo: def desativa(self): self.ativo = False self.jogo.desativa(self)Vejamos como ficou a classe do Aviao:class Aviao(ObjetoDoJogo): def __init__(self, jogo, cor=3): super(Aviao, self).__init__(jogo, cor) self.velocidade = (random.randint(0, 6) + 4) * RATIO self.y = 159 - (random.randint(0, 135) + 11) self.x = self.velocidade self.altura = 9 self.largura = 15 self.colisao = AVIAO self.escapou = False def desenha(self): super().desenha() y = self.y + self.altura x =