diff --git a/atores.py b/atores.py index 8f9a82f49..4e07b7255 100644 --- a/atores.py +++ b/atores.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + import math DESTRUIDO = 'Destruido' @@ -17,7 +18,8 @@ class Ator(): def __init__(self, x=0, y=0): """ - Método de inicialização da classe. Deve inicializar os parâmetros x, y, caracter e status + Método de inicialização da classe. Deve inicializar os parâmetros x, + y, caracter e status :param x: Posição horizontal inicial do ator :param y: Posição vertical inicial do ator @@ -27,7 +29,8 @@ def __init__(self, x=0, y=0): self.status = ATIVO def caracter(self): - return self._caracter_ativo if self.status == ATIVO else self._caracter_destruido + return self._caracter_ativo if self.status == ATIVO else \ + self._caracter_destruido def calcular_posicao(self, tempo): """ @@ -43,8 +46,10 @@ def colidir(self, outro_ator, intervalo=1): """ Método que executa lógica de colisão entre dois atores. Só deve haver colisão se os dois atores tiverem seus status ativos. - Para colisão, é considerado um quadrado, com lado igual ao parâmetro intervalo, em volta do ponto onde se - encontra o ator. Se os atores estiverem dentro desse mesmo quadrado, seus status devem ser alterados para + Para colisão, é considerado um quadrado, com lado igual ao parâmetro + intervalo, em volta do ponto onde se + encontra o ator. Se os atores estiverem dentro desse mesmo quadrado, + seus status devem ser alterados para destruido, seus caracteres para destruido também. :param outro_ator: Ator a ser considerado na colisão @@ -54,7 +59,8 @@ def colidir(self, outro_ator, intervalo=1): if self.status == DESTRUIDO or outro_ator.status == DESTRUIDO: return - if self.x - intervalo <= outro_ator.x <= self.x + intervalo and self.y - intervalo <= outro_ator.y <= self.y + intervalo: + if abs(self.x - outro_ator.x) <= intervalo and abs( + self.y - outro_ator.y) <= intervalo: self.status = DESTRUIDO outro_ator.status = DESTRUIDO @@ -68,6 +74,10 @@ class Porco(Ator): _caracter_destruido = '+' +class DuploLancamentoExcecao(Exception): + pass + + class Passaro(Ator): velocidade_escalar = None @@ -75,7 +85,8 @@ def __init__(self, x=0, y=0): """ Método de inicialização de pássaro. - Deve chamar a inicialização de ator. Além disso, deve armazenar a posição inicial e incializar o tempo de + Deve chamar a inicialização de ator. Além disso, deve armazenar a + posição inicial e incializar o tempo de lançamento e angulo de lançamento :param x: @@ -89,7 +100,8 @@ def __init__(self, x=0, y=0): def foi_lancado(self): """ - Método que retorna verdaeira se o pássaro já foi lançado e falso caso contrário + Método que retorna verdadeiro se o pássaro já foi lançado e falso + caso contrário :return: booleano """ @@ -97,19 +109,24 @@ def foi_lancado(self): def colidir_com_chao(self): """ - Método que executa lógica de colisão com o chão. Toda vez que y for menor ou igual a 0, - o status dos Passaro deve ser alterado para destruido, bem como o seu caracter + Método que executa lógica de colisão com o chão. Toda vez que y for + menor ou igual a 0, + o status dos Passaro deve ser alterado para destruido, bem como o + seu caracter """ if self.y <= 0: self.status = DESTRUIDO def _calcular_posicao_horizontal(self, delta_t): - self.x = self._x_inicial + self.velocidade_escalar * delta_t * math.cos(self._angulo_de_lancamento) + self.x = self._x_inicial + self.velocidade_escalar * delta_t * \ + math.cos( + self._angulo_de_lancamento) def _calcular_posicao_vertical(self, delta_t): self.y = (self._y_inicial + - self.velocidade_escalar * delta_t * math.sin(self._angulo_de_lancamento) - + self.velocidade_escalar * delta_t * math.sin( + self._angulo_de_lancamento) - (GRAVIDADE / 2) * delta_t ** 2) def _calcular_posicao(self, tempo): @@ -121,12 +138,16 @@ def calcular_posicao(self, tempo): """ Método que cálcula a posição do passaro de acordo com o tempo. - Antes do lançamento o pássaro deve retornar o valor de sua posição inicial + Antes do lançamento o pássaro deve retornar o valor de sua posição + inicial - Depois do lançamento o pássaro deve calcular de acordo com sua posição inicial, velocidade escalar, - ângulo de lancamento, gravidade (constante GRAVIDADE) e o tempo do jogo. + Depois do lançamento o pássaro deve calcular de acordo com sua + posição inicial, velocidade escalar, + ângulo de lancamento, gravidade (constante GRAVIDADE) e o tempo do + jogo. - Após a colisão, ou seja, ter seus status destruido, o pássaro deve apenas retornar a última posição calculada. + Após a colisão, ou seja, ter seus status destruido, o pássaro deve + apenas retornar a última posição calculada. :param tempo: tempo de jogo a ser calculada a posição :return: posição x, y @@ -137,16 +158,18 @@ def calcular_posicao(self, tempo): self._calcular_posicao(tempo) return self.x, self.y - def lancar(self, angulo, tempo_de_lancamento): """ - Lógica que lança o pássaro. Deve armazenar o ângulo e o tempo de lançamento para posteriores cálculo. + Lógica que lança o pássaro. Deve armazenar o ângulo e o tempo de + lançamento para posteriores cálculo. O ângulo é passado em graus e deve ser transformado em radianos :param angulo: :param tempo_de_lancamento: :return: """ + if self.foi_lancado(): + raise DuploLancamentoExcecao('Pássaro já foi lançado') self._tempo_de_lancamento = tempo_de_lancamento self._angulo_de_lancamento = math.radians(angulo) diff --git a/fase.py b/fase.py index f54368e96..ffa7084ab 100644 --- a/fase.py +++ b/fase.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- from itertools import chain -from atores import ATIVO +from atores import ATIVO, DuploLancamentoExcecao # Status possíveis do jogo @@ -104,11 +104,14 @@ def lancar(self, angulo, tempo): Se não houver esse tipo de pássaro, não deve fazer nada :param angulo: ângulo de lançamento - :param tempo: Tempo de lançamento + :param tempo: tempo de lançamento """ for passaro in self._passaros: - if not passaro.foi_lancado(): + try: passaro.lancar(angulo, tempo) + except DuploLancamentoExcecao: + continue + else: return diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index 918a02d17..ea020ccbb 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -43,13 +43,15 @@ def plotar(camada_de_atores, ponto): camada_de_atores.create_image((x, y), image=image, anchor=NW) -def animar(tela, camada_de_atores, fase, passo=0.01, delta_t=0.01): +def animar(tela, camada_de_atores, fase, passo=0.01, delta_t=0.04): tempo = 0 passo = int(1000 * passo) angulo = 0 multiplicador_rebobinar = 20 def _animar(): + tempo_de_inicio_de_animacao=time.time() + nonlocal tempo nonlocal delta_t nonlocal angulo @@ -76,7 +78,9 @@ def _animar(): camada_de_atores.create_text(35, 493, text="%d°" % angulo) for ponto in fase.calcular_pontos(tempo): plotar(camada_de_atores, ponto) - tela.after(passo, _animar) + tempo_gasto_com_animacao= round((time.time() - tempo_de_inicio_de_animacao)*1000) # Trans + tempo_proxima_animacao = passo - tempo_gasto_com_animacao if passo>tempo_gasto_com_animacao else 1 + tela.after(tempo_proxima_animacao, _animar) def _ouvir_comandos_lancamento(evento): nonlocal angulo diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 087bd1864..5f4e66f0e 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals from unittest.case import TestCase -from atores import Ator, DESTRUIDO, ATIVO, Obstaculo, Porco, PassaroAmarelo, PassaroVermelho +from atores import Ator, DESTRUIDO, ATIVO, Obstaculo, Porco, PassaroAmarelo, PassaroVermelho, \ + DuploLancamentoExcecao class AtorTestes(TestCase): @@ -119,9 +120,9 @@ def assert_colisao_atores_ativos(self, ator, ator2, intervalo=1): def assert_nao_colisao(self, ator, ator2): """ Se certifica que não colisão entre dois atores - Atenção: Esse não é método de teste porque nao se inicia com prefixo "text". + Atenção: Esse não é método de teste porque não se inicia com prefixo "text". Ele apenas encapsula a lógica de não colisão entre dois atores. - So seja, eles deve manter seus respectivos status mesmo depois da chamada do metodo colidir + Ou seja, eles devem manter seus respectivos status mesmo depois da chamada do método colidir """ # Armazenando status antes da colisão status_inicial_ator = ator.status @@ -206,6 +207,15 @@ def teste_foi_lancado(self): self.assertTrue(passaro_vermelho.foi_lancado(), 'Se o método lançar foi executado, deve retornar verdadeiro') + def test_excecao_ao_lancar_passaro_pela_segunda_vez(self): + """Se certifica que pássaro só pode ser lançado uma vez""" + passaro = PassaroVermelho(0,0) + passaro.lancar(0,0) + with self.assertRaises(DuploLancamentoExcecao): + passaro.lancar(1,1) + self.assertEqual(passaro._angulo_de_lancamento,0,'Deveria continuar com angulo passado no primeiro lançamento') + self.assertEqual(passaro._tempo_de_lancamento,0,'Deveria continuar com tempo passado no primeiro lançamento') + def teste_colisao_com_chao(self): """ Testando que o passáro colido quando sua posição y é menor ou igual a 0 @@ -229,6 +239,7 @@ def teste_colisao_com_chao(self): class PassaroAmareloTests(PassaroBaseTests): + """ Classe de Tests para passaros amarelos """ @@ -243,9 +254,10 @@ def teste_status(self): def teste_velocidade_escalar(self): self.assertEqual(30, PassaroAmarelo.velocidade_escalar) + def teste_lacamento_vertical(self): """ - Tests de lançamento vertical. Nele, o passaro só se move verticalmente e sua posição y se matém contanstante + Testes de lançamento vertical. Nele, o passaro só se move verticalmente e sua posição y se matém contanstante :return: """ passaro_amarelo = PassaroAmarelo(1, 1) diff --git a/testes/fase_testes.py b/testes/fase_testes.py index 85067fa95..8158a43f5 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -from itertools import chain import os +import sys from os import path from unittest.case import TestCase -import math -import sys project_dir = path.dirname(__file__) project_dir = path.join('..') @@ -16,211 +14,199 @@ project_dir = os.path.normpath(project_dir) sys.path.append(project_dir) -from atores import Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, DESTRUIDO, ATIVO +from atores import (Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, + DESTRUIDO, ATIVO, DuploLancamentoExcecao) from fase import Fase, Ponto, EM_ANDAMENTO, VITORIA, DERROTA +class AtorFake: + def __init__(self, x=0, y=0): + self.y = y + self.x = x + self.status = ATIVO + self.colidir_executado = False + self.calcular_posicao_executado = False + self.intervalo_colisao = None + + def calcular_posicao(self, tempo): + self.calcular_posicao_executado = True + + def colidir(self, outro_ator, intervalo): + self.colidir_executado = outro_ator.colidir_executado = True + self.intervalo_colisao = outro_ator.intervalo_colisao = intervalo + + def caracter(self): + return ' ' + + +class ObstaculoFake(AtorFake): + pass + + +class PorcoFake(AtorFake): + pass + + +class PassaroFake(AtorFake): + def __init__(self, x=0, y=0): + super().__init__(x, y) + self._lancado = False + self.colidir_com_chao_executado = False + + def foi_lancado(self): + return self._lancado + + def lancar(self, angulo, tempo): + if self._lancado: + raise DuploLancamentoExcecao() + self._lancado = True + + def colidir_com_chao(self): + self.colidir_com_chao_executado = True + + class FaseTestes(TestCase): def teste_adicionar_obstaculo(self): fase = Fase() self.assertListEqual([], fase._obstaculos) - obstaculo = Obstaculo() + obstaculo = ObstaculoFake() fase.adicionar_obstaculo(obstaculo) self.assertListEqual([obstaculo], fase._obstaculos) - obstaculo1, obstaculo2 = Obstaculo(), Obstaculo() + obstaculo1, obstaculo2 = ObstaculoFake(), ObstaculoFake() fase.adicionar_obstaculo(obstaculo1, obstaculo2) - self.assertListEqual([obstaculo, obstaculo1, obstaculo2], fase._obstaculos) + self.assertListEqual([obstaculo, obstaculo1, obstaculo2], + fase._obstaculos) def teste_adicionar_porco(self): fase = Fase() self.assertListEqual([], fase._porcos) - porco = Porco() + porco = PorcoFake() fase.adicionar_porco(porco) self.assertListEqual([porco], fase._porcos) - porco1, porco2 = Porco(), Porco() + porco1, porco2 = PorcoFake(), PorcoFake() fase.adicionar_porco(porco1, porco2) self.assertListEqual([porco, porco1, porco2], fase._porcos) def teste_adicionar_passaro(self): fase = Fase() self.assertListEqual([], fase._passaros) - passaro = PassaroVermelho() + passaro = PassaroFake() fase.adicionar_passaro(passaro) self.assertListEqual([passaro], fase._passaros) - passaro1, passaro2 = PassaroVermelho(), PassaroAmarelo() + passaro1, passaro2 = PassaroFake(), PassaroFake() fase.adicionar_passaro(passaro1, passaro2) self.assertListEqual([passaro, passaro1, passaro2], fase._passaros) - def teste_acabou_sem_porcos(self): fase = Fase() self.assertEqual(VITORIA, fase.status()) def teste_acabou_com_porcos_e_passaros(self): fase = Fase() - porcos = [Porco(1, 1) for i in range(2)] # criando 2 porcos - passaros = [PassaroAmarelo(1, 1) for i in range(2)] # criando 2 pássaros + porcos = [PorcoFake(1, 1) for _ in range(2)] # criando 2 porcos + passaros = [PassaroFake(1, 1) for _ in range(2)] # criando 2 pássaros fase.adicionar_porco(*porcos) fase.adicionar_passaro(*passaros) self.assertEqual(EM_ANDAMENTO, fase.status()) - # colidindo cada passaro com um porco no tempo 3 - for passaro, porco in zip(passaros, porcos): - passaro.colidir(porco, 3) - + for ator in porcos + passaros: + ator.status = DESTRUIDO self.assertEqual(VITORIA, fase.status()) fase.adicionar_obstaculo(Obstaculo()) - self.assertEqual(VITORIA, fase.status(), 'Obstáculo não interfere no fim do jogo') + self.assertEqual(VITORIA, fase.status(), + 'Obstáculo não interfere no fim do jogo') - fase.adicionar_porco(Porco()) - self.assertEqual(DERROTA, fase.status(), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar') + fase.adicionar_porco(PorcoFake()) + self.assertEqual(DERROTA, fase.status(), + 'Com Porco ativo e sem pássaro para lançar, o jogo ' + 'deveria acabar') - fase.adicionar_passaro(PassaroAmarelo()) + fase.adicionar_passaro(PassaroFake()) self.assertEqual(EM_ANDAMENTO, fase.status(), - 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') + 'Com Porco ativo e com pássaro para lançar, o jogo ' + 'não deveria acabar') def teste_status(self): fase = Fase() - porcos = [Porco(1, 1) for i in range(2)] - passaros = [PassaroAmarelo(1, 1) for i in range(2)] + porcos = [PorcoFake(1, 1) for _ in range(2)] + passaros = [PassaroFake(1, 1) for _ in range(2)] fase.adicionar_porco(*porcos) fase.adicionar_passaro(*passaros) self.assertEqual(EM_ANDAMENTO, fase.status()) - for passaro, porco in zip(passaros, porcos): - passaro.colidir(porco, 3) - + for ator in porcos + passaros: + ator.status = DESTRUIDO self.assertEqual(VITORIA, fase.status(), - 'Sem porcos ativos o jogo deveria terminar com vitória') + 'Sem porcos ativos o jogo deveria terminar com ' + 'vitória') - fase.adicionar_obstaculo(Obstaculo()) + fase.adicionar_obstaculo(ObstaculoFake()) self.assertEqual(VITORIA, fase.status(), 'Obstáculo não interfere para definir vitória') - porco = Porco() + porco = PorcoFake() fase.adicionar_porco(porco) self.assertEqual(DERROTA, fase.status(), - 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar em derrota') + 'Com Porco ativo e sem pássaro para lançar, o jogo ' + 'deveria acabar em derrota') - fase.adicionar_passaro(PassaroAmarelo()) + fase.adicionar_passaro(PassaroFake()) self.assertEqual(EM_ANDAMENTO, fase.status(), - 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') + 'Com Porco ativo e com pássaro para lançar, o jogo ' + 'não deveria acabar') - porco.colidir(porco, 3) + porco.status = DESTRUIDO self.assertEqual(VITORIA, fase.status(), 'Sem porco ativo, o jogo deveria acabar com vitória') def teste_lancar_passaro_sem_erro_quando_nao_existe_passaro(self): - passaro_vermelho, passaro_amarelo = PassaroVermelho(1, 1), PassaroAmarelo(1, 1) + passaros = [PassaroFake(1, 1) for _ in range(2)] fase = Fase() - fase.adicionar_passaro(passaro_vermelho, passaro_amarelo) - self.assertFalse(passaro_vermelho.foi_lancado()) - self.assertFalse(passaro_amarelo.foi_lancado()) + fase.adicionar_passaro(*passaros) + self.assertFalse(passaros[0].foi_lancado()) + self.assertFalse(passaros[1].foi_lancado()) fase.lancar(90, 1) fase.lancar(45, 3) - fase.lancar(31, 5) # testando que lançar passaros depios de todos lançados não causa erro + fase.lancar(31, + 5) # testando que lançar passaros depios de todos + # lançados não causa erro - self.assertTrue(passaro_vermelho.foi_lancado()) - self.assertEqual(math.radians(90), passaro_vermelho._angulo_de_lancamento) - self.assertEqual(1, passaro_vermelho._tempo_de_lancamento) - - self.assertTrue(passaro_amarelo.foi_lancado()) - self.assertEqual(math.radians(45), passaro_amarelo._angulo_de_lancamento) - self.assertEqual(3, passaro_amarelo._tempo_de_lancamento) + self.assertTrue(passaros[0].foi_lancado()) + self.assertTrue(passaros[1].foi_lancado()) def teste_intervalo_de_colisao_padrão(self): ''' - Método que testa se o intervalo de colisão da Fase é repassado aos atores. Padrão de intervalo é 1 + Método que testa se o intervalo de colisão da Fase é repassado aos + atores. Padrão de intervalo é 1 ''' fase = Fase() - passaro = PassaroAmarelo(1, 1) + passaro = PassaroFake(1, 1) fase.adicionar_passaro(passaro) - porco = Porco(2, 2) + porco = PorcoFake(2, 2) fase.adicionar_porco(porco) fase.calcular_pontos(0) - self.assertEqual(DESTRUIDO, passaro.status) - self.assertEqual(DESTRUIDO, porco.status) + self.assertTrue(passaro.colidir_executado) + self.assertTrue(porco.colidir_executado) + self.assertTrue(passaro.calcular_posicao_executado) + self.assertTrue(passaro.colidir_com_chao_executado) + self.assertEqual(1, passaro.intervalo_colisao) + self.assertEqual(1, porco.intervalo_colisao) def teste_intervalo_de_colisao_nao_padrao(self): ''' - Método que testa se o intervalo de colisão da Fase é repassado aos atores. valor testado: 31 + Método que testa se o intervalo de colisão da Fase é repassado aos + atores. valor testado: 31 ''' fase = Fase(30) - passaro = PassaroAmarelo(1, 1) + passaro = PassaroFake(1, 1) fase.adicionar_passaro(passaro) - porco = Porco(31, 31) + porco = PorcoFake(31, 31) fase.adicionar_porco(porco) fase.calcular_pontos(0) - self.assertEqual(DESTRUIDO, passaro.status) - self.assertEqual(DESTRUIDO, porco.status) - - def teste_calcular_pontos(self): - fase_exemplo = criar_fase_exemplo() - expected = set([Ponto(3, 3, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, 'O'), Ponto(78, 1, '@'), - Ponto(70, 1, '@'), Ponto(3, 3, 'V')]) - self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(0))) - - fase_exemplo.lancar(45, 1) - - # i variando de 1 até 2.9 - for i in range(100, 300, 1): - fase_exemplo.calcular_pontos(i / 100) - - fase_exemplo.lancar(63, 3) - - # i variando de 3 até 3.9 - for i in range(300, 400, 1): - fase_exemplo.calcular_pontos(i / 100) - - fase_exemplo.lancar(23, 4) - - expected = set([Ponto(32, 11, 'v'), Ponto(17, 25, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), - Ponto(70, 1, '@')]) - - self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(4))) - - # i variando de 4 até 6.9 - for i in range(400, 700, 1): - fase_exemplo.calcular_pontos(i / 100) - - expected = set( - [Ponto(32, 11, 'v'), Ponto(57, 30, 'A'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), - Ponto(70, 1, '+')]) - - self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(7))) - - # i variando de 7 até 8.49 - for i in range(700, 849, 1): - fase_exemplo.calcular_pontos(i / 100) - print(fase_exemplo.calcular_pontos(8.5)) - - expected = set([Ponto(32, 11, 'v'), Ponto(77, 0, 'a'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '+'), - Ponto(70, 1, '+')]) - - self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(8.5))) - - self.assertEqual(VITORIA, fase_exemplo.status()) - - -def criar_fase_exemplo(multiplicador=1): - fase_exemplo = Fase(1 if multiplicador == 1 else 32) - passaros = [PassaroVermelho(3 * multiplicador, 3 * multiplicador), - PassaroAmarelo(3 * multiplicador, 3 * multiplicador), - PassaroAmarelo(3 * multiplicador, 3 * multiplicador)] - porcos = [Porco(78 * multiplicador, multiplicador), Porco(70 * multiplicador, multiplicador)] - obstaculos = [Obstaculo(31 * multiplicador, 10 * multiplicador)] - - fase_exemplo.adicionar_passaro(*passaros) - fase_exemplo.adicionar_porco(*porcos) - fase_exemplo.adicionar_obstaculo(*obstaculos) - - return fase_exemplo - - -if __name__ == '__main__': - rodar_fase(criar_fase_exemplo(10)) + self.assertEqual(30, passaro.intervalo_colisao) + self.assertEqual(30, porco.intervalo_colisao) diff --git a/testes/integracao.py b/testes/integracao.py new file mode 100644 index 000000000..11f2f0178 --- /dev/null +++ b/testes/integracao.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +from itertools import chain + +import os +from os import path +from unittest.case import TestCase +import math +import sys + +project_dir = path.dirname(__file__) +project_dir = path.join('..') +sys.path.append(project_dir) +from placa_grafica_tkinter import rodar_fase + +project_dir = os.path.join(os.path.dirname(__file__), '..') +project_dir = os.path.normpath(project_dir) +sys.path.append(project_dir) + +from atores import Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, DESTRUIDO, ATIVO, \ + Ator, Passaro +from fase import Fase, Ponto, EM_ANDAMENTO, VITORIA, DERROTA + +class FaseTestes(TestCase): + def teste_acabou_com_porcos_e_passaros(self): + fase = Fase() + porcos = [Porco(1, 1) for i in range(2)] # criando 2 porcos + passaros = [PassaroAmarelo(1, 1) for i in range(2)] # criando 2 pássaros + fase.adicionar_porco(*porcos) + fase.adicionar_passaro(*passaros) + + self.assertEqual(EM_ANDAMENTO, fase.status()) + + # colidindo cada passaro com um porco no tempo 3 + for passaro, porco in zip(passaros, porcos): + passaro.colidir(porco, 3) + + self.assertEqual(VITORIA, fase.status()) + + fase.adicionar_obstaculo(Obstaculo()) + self.assertEqual(VITORIA, fase.status(), 'Obstáculo não interfere no fim do jogo') + + fase.adicionar_porco(Porco()) + self.assertEqual(DERROTA, fase.status(), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar') + + fase.adicionar_passaro(PassaroAmarelo()) + self.assertEqual(EM_ANDAMENTO, fase.status(), + 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') + + def teste_status(self): + fase = Fase() + porcos = [Porco(1, 1) for i in range(2)] + passaros = [PassaroAmarelo(1, 1) for i in range(2)] + fase.adicionar_porco(*porcos) + fase.adicionar_passaro(*passaros) + self.assertEqual(EM_ANDAMENTO, fase.status()) + + for passaro, porco in zip(passaros, porcos): + passaro.colidir(porco, 3) + + self.assertEqual(VITORIA, fase.status(), + 'Sem porcos ativos o jogo deveria terminar com vitória') + + fase.adicionar_obstaculo(Obstaculo()) + self.assertEqual(VITORIA, fase.status(), + 'Obstáculo não interfere para definir vitória') + + porco = Porco() + fase.adicionar_porco(porco) + self.assertEqual(DERROTA, fase.status(), + 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar em derrota') + + fase.adicionar_passaro(PassaroAmarelo()) + self.assertEqual(EM_ANDAMENTO, fase.status(), + 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') + + porco.colidir(porco, 3) + self.assertEqual(VITORIA, fase.status(), + 'Sem porco ativo, o jogo deveria acabar com vitória') + + def teste_lancar_passaro_sem_erro_quando_nao_existe_passaro(self): + passaro_vermelho, passaro_amarelo = PassaroVermelho(1, 1), PassaroAmarelo(1, 1) + fase = Fase() + fase.adicionar_passaro(passaro_vermelho, passaro_amarelo) + self.assertFalse(passaro_vermelho.foi_lancado()) + self.assertFalse(passaro_amarelo.foi_lancado()) + fase.lancar(90, 1) + fase.lancar(45, 3) + fase.lancar(31, 5) # testando que lançar passaros depios de todos lançados não causa erro + + self.assertTrue(passaro_vermelho.foi_lancado()) + self.assertEqual(math.radians(90), passaro_vermelho._angulo_de_lancamento) + self.assertEqual(1, passaro_vermelho._tempo_de_lancamento) + + self.assertTrue(passaro_amarelo.foi_lancado()) + self.assertEqual(math.radians(45), passaro_amarelo._angulo_de_lancamento) + self.assertEqual(3, passaro_amarelo._tempo_de_lancamento) + + def teste_intervalo_de_colisao_padrão(self): + ''' + Método que testa se o intervalo de colisão da Fase é repassado aos atores. Padrão de intervalo é 1 + ''' + fase = Fase() + passaro = PassaroAmarelo(1, 1) + fase.adicionar_passaro(passaro) + porco = Porco(2, 2) + fase.adicionar_porco(porco) + fase.calcular_pontos(0) + self.assertEqual(DESTRUIDO, passaro.status) + self.assertEqual(DESTRUIDO, porco.status) + + def teste_intervalo_de_colisao_nao_padrao(self): + ''' + Método que testa se o intervalo de colisão da Fase é repassado aos atores. valor testado: 31 + ''' + fase = Fase(30) + passaro = PassaroAmarelo(1, 1) + fase.adicionar_passaro(passaro) + porco = Porco(31, 31) + fase.adicionar_porco(porco) + fase.calcular_pontos(0) + self.assertEqual(DESTRUIDO, passaro.status) + self.assertEqual(DESTRUIDO, porco.status) + + def teste_calcular_pontos(self): + fase_exemplo = criar_fase_exemplo() + expected = set([Ponto(3, 3, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, 'O'), Ponto(78, 1, '@'), + Ponto(70, 1, '@'), Ponto(3, 3, 'V')]) + self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(0))) + + fase_exemplo.lancar(45, 1) + + # i variando de 1 até 2.9 + for i in range(100, 300, 1): + fase_exemplo.calcular_pontos(i / 100) + + fase_exemplo.lancar(63, 3) + + # i variando de 3 até 3.9 + for i in range(300, 400, 1): + fase_exemplo.calcular_pontos(i / 100) + + fase_exemplo.lancar(23, 4) + + expected = set([Ponto(32, 11, 'v'), Ponto(17, 25, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), + Ponto(70, 1, '@')]) + + self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(4))) + + # i variando de 4 até 6.9 + for i in range(400, 700, 1): + fase_exemplo.calcular_pontos(i / 100) + + expected = set( + [Ponto(32, 11, 'v'), Ponto(57, 30, 'A'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), + Ponto(70, 1, '+')]) + + self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(7))) + + # i variando de 7 até 8.49 + for i in range(700, 849, 1): + fase_exemplo.calcular_pontos(i / 100) + print(fase_exemplo.calcular_pontos(8.5)) + + expected = set([Ponto(32, 11, 'v'), Ponto(77, 0, 'a'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '+'), + Ponto(70, 1, '+')]) + + self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(8.5))) + + self.assertEqual(VITORIA, fase_exemplo.status()) + + +def criar_fase_exemplo(multiplicador=1): + fase_exemplo = Fase(1 if multiplicador == 1 else 32) + passaros = [PassaroVermelho(3 * multiplicador, 3 * multiplicador), + PassaroAmarelo(3 * multiplicador, 3 * multiplicador), + PassaroAmarelo(3 * multiplicador, 3 * multiplicador)] + porcos = [Porco(78 * multiplicador, multiplicador), Porco(70 * multiplicador, multiplicador)] + obstaculos = [Obstaculo(31 * multiplicador, 10 * multiplicador)] + + fase_exemplo.adicionar_passaro(*passaros) + fase_exemplo.adicionar_porco(*porcos) + fase_exemplo.adicionar_obstaculo(*obstaculos) + + return fase_exemplo + + +if __name__ == '__main__': + rodar_fase(criar_fase_exemplo(10)) diff --git a/testes/testes_placa_grafica.py b/testes/testes_placa_grafica.py index 025c04004..556328f98 100644 --- a/testes/testes_placa_grafica.py +++ b/testes/testes_placa_grafica.py @@ -14,8 +14,6 @@ def teste_inverter_coordenadas(self): self.assertTupleEqual((10, 0), placa_grafica.normalizar_coordenadas(10, placa_grafica.ALTURA - 1)) def teste_desenhar_frame_vazio(self): - self.maxDiff = None - class PontoCartesiano(): def __init__(self, x, y, caracter): self.caracter = caracter