From df7abf84b72dff6987f9d009d77476dd32322ef6 Mon Sep 17 00:00:00 2001 From: renzon Date: Sat, 30 Aug 2014 15:50:53 -0300 Subject: [PATCH 01/35] =?UTF-8?q?Refatora=C3=A7=C3=A3o=20para=20jogo=20fic?= =?UTF-8?q?ar=20ainda=20mais=20simples?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atores.py | 58 +++------- testes/atores_testes.py | 240 ++++++++++++++-------------------------- 2 files changed, 99 insertions(+), 199 deletions(-) diff --git a/atores.py b/atores.py index 1cf2becbb..f16a63cc0 100644 --- a/atores.py +++ b/atores.py @@ -5,6 +5,7 @@ DESTRUIDO = 'Destruido' ATIVO = 'Ativo' +GRAVIDADE = 10 # m/s^2 class Ator(): @@ -14,35 +15,21 @@ class Ator(): def __init__(self, x=0, y=0): self.y = y self.x = x - self._tempo_de_colisao = None - - def caracter(self, tempo): - return self._caracter_ativo if self.status(tempo) == ATIVO else self._caracter_destruido - - def resetar(self): - self._tempo_de_colisao = None - - def status(self, tempo): - if self._tempo_de_colisao is None or self._tempo_de_colisao > tempo: - return ATIVO - return DESTRUIDO + self.caracter = self._caracter_ativo + self.status = ATIVO def calcular_posicao(self, tempo): - return self.arredondar_posicao() - - def arredondar_posicao(self): - self.x, self.y = round(self.x), round(self.y) return self.x, self.y - def colidir(self, outro_ator, tempo, intervalo=1): - if self.status(tempo) == DESTRUIDO or outro_ator.status(tempo) == DESTRUIDO: + def colidir(self, outro_ator, intervalo=1): + if self.status == DESTRUIDO or outro_ator.status == DESTRUIDO: return - x1, y1 = self.arredondar_posicao() - x2, y2 = outro_ator.arredondar_posicao() - if x1 - intervalo <= x2 <= x1 + intervalo and y1 - intervalo <= y2 <= y1 + intervalo: - self._tempo_de_colisao = tempo - outro_ator._tempo_de_colisao = tempo + if self.x - intervalo <= outro_ator.x <= self.x + intervalo and self.y - intervalo <= outro_ator.y <= self.y + intervalo: + self.status = DESTRUIDO + self.caracter = self._caracter_destruido + outro_ator.caracter = outro_ator._caracter_destruido + outro_ator.status = DESTRUIDO class Obstaculo(Ator): @@ -54,9 +41,6 @@ class Porco(Ator): _caracter_destruido = '+' -GRAVIDADE = 10 # m/s^2 - - class Passaro(Ator): velocidade_escalar = None @@ -67,18 +51,12 @@ def __init__(self, x=0, y=0): self._tempo_de_lancamento = None self._angulo_de_lancamento = None # radianos - def resetar(self): - super().resetar() - self._tempo_de_lancamento = None - self._angulo_de_lancamento = None - - def foi_lancado(self): return self._tempo_de_lancamento is not None - def colidir_com_chao(self, tempo): + def colidir_com_chao(self): if self.y <= 0: - self._tempo_de_colisao = tempo + 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) @@ -94,14 +72,12 @@ def _calcular_posicao(self, tempo): self._calcular_posicao_horizontal(delta_t) def calcular_posicao(self, tempo): - if self._aguardando_lancamento(tempo): - self.x = self._x_inicial - self.y = self._y_inicial - elif self._ja_colidiu(tempo): - self._calcular_posicao(self._tempo_de_colisao) - else: + if self._tempo_de_lancamento is None: + return self._x_inicial, self._y_inicial + if self.status == ATIVO: self._calcular_posicao(tempo) - return self.arredondar_posicao() + return self.x, self.y + def lancar(self, angulo, tempo): self._tempo_de_lancamento = tempo diff --git a/testes/atores_testes.py b/testes/atores_testes.py index b0d00ac7a..675814b5d 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -5,56 +5,33 @@ from atores import Ator, DESTRUIDO, ATIVO, Obstaculo, Porco, PassaroAmarelo, PassaroVermelho -class AtorBaseTest(TestCase): - def assert_ator_caracteres(self, ator, caracter_status_ativo, caracter_status_destruido): - 'Confere status e caracteres ativos e destruidos de um ator' - # Conferencia de caracter de ator ativo - self.assertEqual(ATIVO, ator.status(0)) - self.assertEqual(caracter_status_ativo, ator.caracter(0)) - - # Colidindo ator com ele mesmo para alterar seu status para destruido - ator.colidir(ator, 3.2) - - self.assertEqual(caracter_status_ativo, ator.caracter(3.1), - 'Status ativo, logo o caracter deveria ser %s' % caracter_status_ativo) - self.assertEqual(caracter_status_destruido, ator.caracter(3.2), - 'Status destruido, logo o caracter deveria ser %s' % caracter_status_destruido) - self.assertEqual(caracter_status_destruido, ator.caracter(4), - 'Status destruido, logo o caracter deveria ser %s' % caracter_status_destruido) - - -class AtorTestes(AtorBaseTest): - def teste_ator_posicao(self): +class AtorTestes(TestCase): + def teste_valores_padrao(self): ator = Ator() - self.assertTupleEqual((0, 0), ator.calcular_posicao(0)) - ator = Ator(0.3, 0.5) - self.assertTupleEqual((0, 0), ator.calcular_posicao(2.3), 'Deveria arredondar para inteiro') - ator = Ator(0.6, 2.1) - self.assertTupleEqual((1, 2), ator.calcular_posicao(3.14), 'Deveria arredondar para inteiro') - - def teste_resetar(self): - ator = Ator() - self.assertIsNone(ator._tempo_de_colisao) - ator._tempo_de_colisao = 1 - ator.resetar() - self.assertIsNone(ator._tempo_de_colisao) - + self.assertEqual(0, ator.x) + self.assertEqual(0, ator.y) + self.assertEqual(ATIVO, ator.status) + self.assertEqual('A', ator.caracter) + + def teste_valores_passados_por_parametro(self): + ator = Ator(1, 2) + self.assertEqual(1, ator.x) + self.assertEqual(2, ator.y) + self.assertEqual(ATIVO, ator.status) + self.assertEqual('A', ator.caracter) - def teste_status(self): + def teste_ator_posicao(self): + 'Teste que verifica que o ator comum não deve se mover independente do tempo do jogo' ator = Ator() - 'Confere status de um ator' - # Conferencia de caracter de ator ativo - self.assertEqual(ATIVO, ator.status(0)) + x, y = ator.calcular_posicao(0) + self.assertEqual(0, x) + self.assertEqual(0, y) - # Colidindo ator com ele mesmo para alterar seu status para destruido - ator._tempo_de_colisao = 3.2 + ator = Ator(0.3, 0.5) + x, y = ator.calcular_posicao(10) + self.assertEqual(0.3, x) + self.assertEqual(0.5, y) - self.assertEqual(ATIVO, ator.status(3.1), - 'Status para tempo 3.1 de jogo deveria mostrar status ativo, já que é menor que o tempo de colisão 3.2') - self.assertEqual(DESTRUIDO, ator.status(3.2), - 'Status para tempo 3.2 de jogo deveria mostrar status destruido, já que é igual ao tempo de colisão 3.2') - self.assertEqual(DESTRUIDO, ator.status(4), - 'Status para tempo 4 de jogo deveria mostrar status destruido, já que é maior que o tempo de colisão 3.2') def teste_colisao_entre_atores_ativos(self): ator = Ator(2, 2) # Ator recém criado deve ter status ativo @@ -108,75 +85,73 @@ def teste_colisao_somente_um_ator_destruido(self): def test_caracter(self): ator = Ator() - self.assert_ator_caracteres(ator, 'A', ' ') + self.assertEqual('A', ator.caracter) + outro_ator_na_mesma_posicao = Ator() + ator.colidir(outro_ator_na_mesma_posicao) + self.assertEqual(' ', ator.caracter) def assert_colisao_atores_ativos(self, ator, ator2, intervalo=1): 'Se certifica que há colisão entre atores ativos' - tempo_da_colisao = 2 # Conferindo status dos dois atores antes da colisão - self.assertEqual(ator.status(tempo_da_colisao), ATIVO, 'Status deveria ser ativo antes da colisão') - self.assertEqual(ator2.status(tempo_da_colisao), ATIVO, 'Status deveria ser ativo antes da colisão') - ator.colidir(ator2, tempo_da_colisao, intervalo) + self.assertEqual(ator.status, ATIVO, 'Status deveria ser ativo antes da colisão') + self.assertEqual(ator2.status, ATIVO, 'Status deveria ser ativo antes da colisão') + ator.colidir(ator2, intervalo) # Conferindo status dos dois atores depois da colisão - self.assertEqual(ator2.status(tempo_da_colisao), DESTRUIDO, 'Status deveria ser destruido depois da colisão') - self.assertEqual(ator.status(tempo_da_colisao), DESTRUIDO, 'Status deveria ser destruido depois da colisão') + self.assertEqual(ator2.status, DESTRUIDO, 'Status deveria ser destruido depois da colisão') + self.assertEqual(ator.status, DESTRUIDO, 'Status deveria ser destruido depois da colisão') def assert_nao_colisao(self, ator, ator2): 'Se certifica que não colisão entre dois atores' - tempo_da_colisao = 2 # Armazenando status antes da colisão - status_inicial_ator = ator.status(tempo_da_colisao) - status_inicial_ator_2 = ator2.status(tempo_da_colisao) + status_inicial_ator = ator.status + status_inicial_ator_2 = ator2.status - ator.colidir(ator2, tempo_da_colisao) + ator.colidir(ator2) # Conferindo se status ficaram inalterados - self.assertEqual(status_inicial_ator, ator.status(tempo_da_colisao), 'Status de ator não deveria mudar') - self.assertEqual(status_inicial_ator_2, ator2.status(tempo_da_colisao), 'Status de ator2 não deveria mudar') + self.assertEqual(status_inicial_ator, ator.status, 'Status de ator não deveria mudar') + self.assertEqual(status_inicial_ator_2, ator2.status, 'Status de ator2 não deveria mudar') -class ObstaculoTestes(AtorBaseTest): +class ObstaculoTestes(TestCase): def teste_status(self): obstaculo = Obstaculo() - self.assert_ator_caracteres(obstaculo, 'O', ' ') + self.assertEqual('O', obstaculo.caracter) + outro_ator_na_mesma_posicao = Ator() + obstaculo.colidir(outro_ator_na_mesma_posicao) + self.assertEqual(' ', obstaculo.caracter) -class PorcoTestes(AtorBaseTest): +class PorcoTestes(TestCase): def teste_status(self): porco = Porco() - self.assert_ator_caracteres(porco, '@', '+') + self.assertEqual('@', porco.caracter) + outro_ator_na_mesma_posicao = Ator() + porco.colidir(outro_ator_na_mesma_posicao) + self.assertEqual('+', porco.caracter) -class PassaroBaseTests(AtorBaseTest): +class PassaroBaseTests(TestCase): def assert_passaro_posicao(self, x_esperado, y_esperado, status_esperado, passaro, tempo): x_calculado, y_calculado = passaro.calcular_posicao(tempo) - self.assertEqual(x_esperado, x_calculado) - self.assertEqual(y_esperado, y_calculado) - passaro.colidir_com_chao(tempo) - self.assertEqual(status_esperado, passaro.status(tempo)) + self.assertEqual(x_esperado, round(x_calculado), 'valor real de x = %s' % x_calculado) + self.assertEqual(y_esperado, round(y_calculado), 'valor real de y = %s' % y_calculado) + self.assertEqual(status_esperado, passaro.status, '(x = %s, y = %s)' % (x_calculado, y_calculado)) class PassaroVermelhoTests(PassaroBaseTests): def teste_status(self): passaro_amarelo = PassaroVermelho(1, 1) - self.assert_ator_caracteres(passaro_amarelo, 'V', 'v') + self.assertEqual('V', passaro_amarelo.caracter) + outro_ator_na_mesma_posicao = Ator() + passaro_amarelo.colidir(outro_ator_na_mesma_posicao) + self.assertEqual('v', passaro_amarelo.caracter) + def teste_velocidade_escalar(self): self.assertEqual(20, PassaroVermelho.velocidade_escalar) - def teste_resetar(self): - passaro = PassaroVermelho() - self.assertIsNone(passaro._tempo_de_colisao) - self.assertIsNone(passaro._tempo_de_lancamento) - self.assertIsNone(passaro._angulo_de_lancamento) - passaro._tempo_de_colisao = 1 - passaro._tempo_de_lancamento = 2 - passaro._angulo_de_lancamento = 90 - passaro.resetar() - self.assertIsNone(passaro._tempo_de_colisao) - self.assertIsNone(passaro._tempo_de_lancamento) - self.assertIsNone(passaro._angulo_de_lancamento) def teste_foi_lancado(self): passaro_vermelho = PassaroVermelho(1, 1) @@ -186,99 +161,45 @@ def teste_foi_lancado(self): self.assertTrue(passaro_vermelho.foi_lancado(), 'Se o método lançar foi executado, deve retornar verdadeiro') - def teste_posicao_antes_do_lancamento(self): - 'Método que testa que o pássaro fica parado antes do tempo de lançamento' - passaro_vermelho = PassaroVermelho(1, 1) - passaro_vermelho.lancar(90, 2) # passaro lancado a 90 graus no tempo 2 segundos - # - for t in range(20): - t /= 10 - self.assertEqual((1, 1), passaro_vermelho.calcular_posicao(t), - 'Não deveria se mover no tempo %s < 2 segundtos' % t) - - def teste_colisao_com_chao(self): - for i in range(30): - passaro = PassaroVermelho(i, 0) - passaro.colidir_com_chao(3) - self.assertEqual(DESTRUIDO, passaro.status(3), 'Deve colidir com chão sempre que y=0') - - def teste_colisao(self): - passaro_vermelho = PassaroVermelho(1, 1) - passaro_vermelho.lancar(45, 2) # passaro lancado a 45 graus no tempo 2 segundos - - porco = Porco(14, 10) - x_calculado, y_calculado = passaro_vermelho.calcular_posicao(2.89) - self.assertEqual(14, x_calculado) - self.assertEqual(10, y_calculado) - - passaro_vermelho.colidir(porco, 2.89) - self.assertEqual(DESTRUIDO, passaro_vermelho.status(2.89)) - - # Deve ficar parado onde colidiu para qualquer tempo maior ou igual que o de colisão - x_calculado, y_calculado = passaro_vermelho.calcular_posicao(2.89) - self.assertEqual(14, x_calculado) - self.assertEqual(10, y_calculado) - - x_calculado, y_calculado = passaro_vermelho.calcular_posicao(4) - self.assertEqual(14, x_calculado) - self.assertEqual(10, y_calculado) + passaro = PassaroVermelho(0, 0) + passaro.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro.status, 'Deve colidir com chão sempre que y<=0') + passaro = PassaroVermelho(1, 0) + passaro.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro.status, 'Deve colidir com chão sempre que y<=0') + passaro = PassaroVermelho(2, 0) + passaro.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro.status, 'Deve colidir com chão sempre que y<=0') + passaro = PassaroVermelho(2, -0.1) + passaro.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro.status, 'Deve colidir com chão sempre que y<=0') + passaro = PassaroVermelho(2, -5) + passaro.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro.status, 'Deve colidir com chão sempre que y<=0') class PassaroAmareloTests(PassaroBaseTests): def teste_status(self): passaro_amarelo = PassaroAmarelo(1, 1) - self.assert_ator_caracteres(passaro_amarelo, 'A', 'a') + self.assertEqual('A', passaro_amarelo.caracter) + outro_ator_na_mesma_posicao = Ator() + passaro_amarelo.colidir(outro_ator_na_mesma_posicao) + self.assertEqual('a', passaro_amarelo.caracter) def teste_velocidade_escalar(self): self.assertEqual(30, PassaroAmarelo.velocidade_escalar) - def teste_posicao_antes_do_lancamento(self): - passaro_amarelo = PassaroAmarelo(1, 1) - passaro_amarelo.lancar(90, 2) # passaro lancado a 90 graus no tempo 2 segundos - # - for t in range(20): - t /= 10 - self.assertEqual((1, 1), passaro_amarelo.calcular_posicao(t), - 'Não deveria se mover no tempo %s < 2 segundtos' % t) - - - def teste_colisao_com_chao(self): - for i in range(30): - passaro = PassaroAmarelo(i, 0) - passaro.colidir_com_chao(3) - self.assertEqual(DESTRUIDO, passaro.status(3), 'Deve colidir com chão sempre que y=0') - - def teste_colisao(self): - passaro_amarelo = PassaroAmarelo(1, 1) - passaro_amarelo.lancar(45, 2) # passaro lancado a 45 graus no tempo 2 segundos - porco = Porco(4, 4) - x_calculado, y_calculado = passaro_amarelo.calcular_posicao(2.12) - self.assertEqual(4, x_calculado) - self.assertEqual(3, y_calculado) - - passaro_amarelo.colidir(porco, 2.12) - self.assertEqual(DESTRUIDO, passaro_amarelo.status(2.12)) - # Deve ficar parado onde colidiu para qualquer tempo maior ou igual que o de colisão - x_calculado, y_calculado = passaro_amarelo.calcular_posicao(2.12) - self.assertEqual(4, x_calculado) - self.assertEqual(3, y_calculado) - - x_calculado, y_calculado = passaro_amarelo.calcular_posicao(1000) - self.assertEqual(4, x_calculado) - self.assertEqual(3, y_calculado) - def teste_lacamento_vertical(self): passaro_amarelo = PassaroAmarelo(1, 1) passaro_amarelo.lancar(90, 2) # passaro lancado a 90 graus no tempo 2 segundos # função auxiliar que mantém x fixo com valor 1, status Ativo, variando apenas o tempo e a posição y - def assert_vertical(y_local, tempo): - self.assert_passaro_posicao(1, y_local, ATIVO, passaro_amarelo, tempo) + def assert_vertical(y, tempo): + self.assert_passaro_posicao(1, y, ATIVO, passaro_amarelo, tempo) # subindo - assert_vertical(1, 2.0) assert_vertical(1, 2.0) assert_vertical(1, 2.01) assert_vertical(2, 2.02) @@ -317,7 +238,9 @@ def assert_vertical(y_local, tempo): assert_vertical(1, 8.01) # colisão - self.assert_passaro_posicao(1, 0, DESTRUIDO, passaro_amarelo, 8.02) + assert_vertical(0, 8.04) + passaro_amarelo.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro_amarelo.status) def test_lancamento_45_graus(self): passaro_amarelo = PassaroAmarelo(1, 1) @@ -749,8 +672,9 @@ def test_lancamento_45_graus(self): self.assert_passaro_posicao(91, 1, ATIVO, passaro_amarelo, 6.24) self.assert_passaro_posicao(91, 1, ATIVO, passaro_amarelo, 6.25) self.assert_passaro_posicao(91, 1, ATIVO, passaro_amarelo, 6.26) - self.assert_passaro_posicao(92, 0, DESTRUIDO, passaro_amarelo, 6.27) - + self.assert_passaro_posicao(92, 0, ATIVO, passaro_amarelo, 6.29) + passaro_amarelo.colidir_com_chao() + self.assertEqual(DESTRUIDO, passaro_amarelo.status) # Código de geração de testes # for delta_t in range(0, 550): From a76670ab5faf6daddf69e955ac21665e2bd59217 Mon Sep 17 00:00:00 2001 From: renzon Date: Sat, 30 Aug 2014 16:37:40 -0300 Subject: [PATCH 02/35] =?UTF-8?q?Vers=C3=A3o=20mais=20simples=20finalizada?= =?UTF-8?q?.=20Falta=20documentar=20e=20retirar=20bot=C3=B5e=20de=20reset?= =?UTF-8?q?=20e=20replay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atores.py | 5 +- fase.py | 43 ++++++++-------- placa_grafica.py | 2 +- placa_grafica_tkinter.py | 4 +- testes/fase_testes.py | 105 +++++++++++++++++---------------------- 5 files changed, 72 insertions(+), 87 deletions(-) diff --git a/atores.py b/atores.py index f16a63cc0..f21bcd755 100644 --- a/atores.py +++ b/atores.py @@ -57,6 +57,7 @@ def foi_lancado(self): def colidir_com_chao(self): if self.y <= 0: self.status = DESTRUIDO + self.caracter=self._caracter_destruido def _calcular_posicao_horizontal(self, delta_t): self.x = self._x_inicial + self.velocidade_escalar * delta_t * math.cos(self._angulo_de_lancamento) @@ -86,8 +87,8 @@ def lancar(self, angulo, tempo): def _aguardando_lancamento(self, tempo): return not self.foi_lancado() or tempo < self._tempo_de_lancamento - def _ja_colidiu(self, tempo): - return self.foi_lancado() and self.status(tempo) == DESTRUIDO + def _ja_colidiu(self): + return self.foi_lancado() and self.status() == DESTRUIDO class PassaroAmarelo(Passaro): diff --git a/fase.py b/fase.py index b2bdf8c8f..27ddbdbd9 100644 --- a/fase.py +++ b/fase.py @@ -6,8 +6,8 @@ class Ponto(): def __init__(self, x, y, caracter): self.caracter = caracter - self.x = x - self.y = y + self.x = round(x) + self.y = round(y) def __eq__(self, other): return self.x == other.x and self.y == other.y and self.caracter == other.caracter @@ -35,13 +35,13 @@ def adicionar_porco(self, *porcos): def adicionar_passaro(self, *passaros): self._adicionar_ator(self._passaros, *passaros) - def acabou(self, tempo): - return not self._existe_porco_ativo(tempo) or not self._existe_passaro_ativo(tempo) + def acabou(self): + return not self._existe_porco_ativo() or not self._existe_passaro_ativo() - def status(self, tempo): - if not self._existe_porco_ativo(tempo): + def status(self): + if not self._existe_porco_ativo(): return 'Jogo em encerrado. Você ganhou!' - if self._existe_passaro_ativo(tempo): + if self._existe_passaro_ativo(): return 'Jogo em andamento.' return 'Jogo em encerrado. Você perdeu!' @@ -51,37 +51,34 @@ def lancar(self, angulo, tempo): passaro.lancar(angulo, tempo) return - def resetar(self): - for ator in chain(self._passaros, self._obstaculos, self._porcos): - ator.resetar() def calcular_pontos(self, tempo): pontos = [self._calcular_ponto_de_passaro(p, tempo) for p in self._passaros] obstaculos_e_porcos = chain(self._obstaculos, self._porcos) - pontos.extend([self._transformar_em_ponto(ator, tempo) for ator in obstaculos_e_porcos]) + pontos.extend([self._transformar_em_ponto(ator) for ator in obstaculos_e_porcos]) return pontos - def _transformar_em_ponto(self, ator, tempo): - return Ponto(ator.x, ator.y, ator.caracter(tempo)) + def _transformar_em_ponto(self, ator): + return Ponto(ator.x, ator.y, ator.caracter) def _calcular_ponto_de_passaro(self, passaro, tempo, ): passaro.calcular_posicao(tempo) for ator in chain(self._obstaculos, self._porcos): - if ATIVO == passaro.status(tempo): - passaro.colidir(ator, tempo, self.intervalo_de_colisao) - passaro.colidir_com_chao(tempo) + if ATIVO == passaro.status: + passaro.colidir(ator, self.intervalo_de_colisao) + passaro.colidir_com_chao() else: break - return self._transformar_em_ponto(passaro, tempo) + return self._transformar_em_ponto(passaro) - def _existe_porco_ativo(self, tempo): - return self._verificar_se_existe_ator_ativo(self._porcos, tempo) + def _existe_porco_ativo(self): + return self._verificar_se_existe_ator_ativo(self._porcos) - def _verificar_se_existe_ator_ativo(self, atores, tempo): + def _verificar_se_existe_ator_ativo(self, atores): for a in atores: - if a.status(tempo) == ATIVO: + if a.status == ATIVO: return True return False - def _existe_passaro_ativo(self, tempo): - return self._verificar_se_existe_ator_ativo(self._passaros, tempo) + def _existe_passaro_ativo(self): + return self._verificar_se_existe_ator_ativo(self._passaros) diff --git a/placa_grafica.py b/placa_grafica.py index 5f8bfe3af..77ae67aef 100644 --- a/placa_grafica.py +++ b/placa_grafica.py @@ -52,7 +52,7 @@ def _animar(delta_t, fase, passo, tempo, msg): def _jogar(delta_t, fase, passo, tempo, msg): - while not fase.acabou(tempo): + while not fase.acabou(): tempo = desenhar_e_esperar(delta_t, fase, passo, tempo, msg) entrada = ouvir_teclado() if entrada: diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index 9b8e76f7d..0d619e026 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -57,10 +57,10 @@ def _animar(): if tempo <= 0: tempo = 0 delta_t /= -multiplicador_rebobinar - if fase.acabou(tempo): + if fase.acabou(): camada_de_atores.create_image(162, 55, image=PYTHONBIRDS_LOGO, anchor=NW) camada_de_atores.create_image(54, 540, image=MENU, anchor=NW) - if 'ganhou' in fase.status(tempo): + if 'ganhou' in fase.status(): img = VOCE_GANHOU else: img = VOCE_PERDEU diff --git a/testes/fase_testes.py b/testes/fase_testes.py index 06072f398..2d8fdd832 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -52,7 +52,7 @@ def teste_adicionar_passaro(self): def teste_acabou_sem_porcos(self): fase = Fase() - self.assertTrue(fase.acabou(0)) + self.assertTrue(fase.acabou()) def teste_acabou_com_porcos_e_passaros(self): fase = Fase() @@ -61,26 +61,22 @@ def teste_acabou_com_porcos_e_passaros(self): fase.adicionar_porco(*porcos) fase.adicionar_passaro(*passaros) - self.assertFalse(fase.acabou(0)) - self.assertFalse(fase.acabou(2.9)) - self.assertFalse(fase.acabou(3)) + self.assertFalse(fase.acabou()) - # colidingo cada passaro com um porco no tempo 3 + # colidindo cada passaro com um porco no tempo 3 for passaro, porco in zip(passaros, porcos): passaro.colidir(porco, 3) - self.assertFalse(fase.acabou(0)) - self.assertFalse(fase.acabou(2.9)) - self.assertTrue(fase.acabou(3)) + self.assertTrue(fase.acabou()) fase.adicionar_obstaculo(Obstaculo()) - self.assertTrue(fase.acabou(3), 'Obstáculo não interfere no fim do jogo') + self.assertTrue(fase.acabou(), 'Obstáculo não interfere no fim do jogo') fase.adicionar_porco(Porco()) - self.assertTrue(fase.acabou(3), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar') + self.assertTrue(fase.acabou(), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar') fase.adicionar_passaro(PassaroAmarelo()) - self.assertFalse(fase.acabou(3), 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') + self.assertFalse(fase.acabou(), 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') def teste_status(self): fase = Fase() @@ -88,33 +84,29 @@ def teste_status(self): passaros = [PassaroAmarelo(1, 1) for i in range(2)] fase.adicionar_porco(*porcos) fase.adicionar_passaro(*passaros) - self.assertEqual('Jogo em andamento.', fase.status(0)) - self.assertEqual('Jogo em andamento.', fase.status(2.9)) - self.assertEqual('Jogo em andamento.', fase.status(3)) + self.assertEqual('Jogo em andamento.', fase.status()) for passaro, porco in zip(passaros, porcos): passaro.colidir(porco, 3) - self.assertEqual('Jogo em andamento.', fase.status(0)) - self.assertEqual('Jogo em andamento.', fase.status(2.9)) - self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(3), + self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(), 'Sem porcos ativos o jogo deveria terminar com vitória') fase.adicionar_obstaculo(Obstaculo()) - self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(3), + self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(), 'Obstáculo não interfere para definir vitória') porco = Porco() fase.adicionar_porco(porco) - self.assertEqual('Jogo em encerrado. Você perdeu!', fase.status(3), + self.assertEqual('Jogo em encerrado. Você perdeu!', fase.status(), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar em derrota') fase.adicionar_passaro(PassaroAmarelo()) - self.assertEqual('Jogo em andamento.', fase.status(3), + self.assertEqual('Jogo 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('Jogo em encerrado. Você ganhou!', fase.status(3), + self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(), 'Sem porco ativo, o jogo deveria acabar com vitória') def teste_lancar_passaro_sem_erro_quando_nao_existe_passaro(self): @@ -145,8 +137,8 @@ def teste_intervalo_de_colisao_padrão(self): porco = Porco(2, 2) fase.adicionar_porco(porco) fase.calcular_pontos(0) - self.assertEqual(DESTRUIDO, passaro.status(0)) - self.assertEqual(DESTRUIDO, porco.status(0)) + self.assertEqual(DESTRUIDO, passaro.status) + self.assertEqual(DESTRUIDO, porco.status) def teste_intervalo_de_colisao_nao_padrao(self): ''' @@ -158,8 +150,8 @@ def teste_intervalo_de_colisao_nao_padrao(self): porco = Porco(31, 31) fase.adicionar_porco(porco) fase.calcular_pontos(0) - self.assertEqual(DESTRUIDO, passaro.status(0)) - self.assertEqual(DESTRUIDO, porco.status(0)) + self.assertEqual(DESTRUIDO, passaro.status) + self.assertEqual(DESTRUIDO, porco.status) def teste_calcular_pontos(self): fase_exemplo = criar_fase_exemplo() @@ -167,44 +159,45 @@ def teste_calcular_pontos(self): Ponto(70, 1, '@')] self.assertListEqual(expected, fase_exemplo.calcular_pontos(0)) - expected = [Ponto(31, 11, 'v'), Ponto(17, 25, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), + 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 = [Ponto(32, 11, 'v'), Ponto(17, 25, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), Ponto(70, 1, '@')] + self.assertListEqual(expected, fase_exemplo.calcular_pontos(4)) - expected = [Ponto(31, 11, 'v'), Ponto(57, 30, 'A'), Ponto(69, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), - Ponto(70, 1, '+')] - self.assertListEqual(expected, fase_exemplo.calcular_pontos(7)) + # i variando de 4 até 6.9 + for i in range(400, 700, 1): + fase_exemplo.calcular_pontos(i / 100) - expected = [Ponto(31, 11, 'v'), Ponto(77, 2, 'a'), Ponto(69, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '+'), + expected = [Ponto(32, 11, 'v'), Ponto(57, 30, 'A'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), Ponto(70, 1, '+')] - self.assertListEqual(expected, fase_exemplo.calcular_pontos(8.5)) - self.assertFalse(fase_exemplo.acabou(8.3)) - self.assertTrue(fase_exemplo.acabou(8.5)) + self.assertListEqual(expected, fase_exemplo.calcular_pontos(7)) - def teste_resetar(self): - 'Testa se o método resetar de faze chama o método resetar de todos atores' - fase_exemplo = criar_fase_exemplo() - atores = list(chain(fase_exemplo._passaros, fase_exemplo._obstaculos, fase_exemplo._porcos)) - fase_exemplo.calcular_pontos(0) + # 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)) - fase_exemplo.calcular_pontos(4) - fase_exemplo.calcular_pontos(7) - fase_exemplo.calcular_pontos(8.5) + expected = [Ponto(32,11,'v'), Ponto(77,0,'a'), Ponto(70,2,'a'), Ponto(31,10,' '), Ponto(78,1,'+'), Ponto(70,1,'+')] - self.assertFalse(fase_exemplo.acabou(8.3)) - self.assertTrue(fase_exemplo.acabou(8.5)) - # certificando que todos atore foram destruidos - for a in atores: - self.assertEqual(DESTRUIDO, a.status(8.5)) - for p in fase_exemplo._passaros: - self.assertTrue(p.foi_lancado(), 'Todos pássaros foram lançados') - fase_exemplo.resetar() - for a in atores: - self.assertEqual(ATIVO, a.status(8.5), 'Após resetar atore devem voltar a ficar ativos') - for p in fase_exemplo._passaros: - self.assertFalse(p.foi_lancado(), 'Nenhum pássaro foi lançado') + self.assertListEqual(expected, fase_exemplo.calcular_pontos(8.5)) + + self.assertTrue(fase_exemplo.acabou()) def criar_fase_exemplo(): @@ -217,12 +210,6 @@ def criar_fase_exemplo(): fase_exemplo.adicionar_porco(*porcos) fase_exemplo.adicionar_obstaculo(*obstaculos) - fase_exemplo.lancar(45, 1) - fase_exemplo.lancar(63, 3) - fase_exemplo.lancar(23, 4) - - for i in range(86): - fase_exemplo.calcular_pontos(i / 10) return fase_exemplo From 79a2f7df0358a50a1e68afaffba61624fa2f3cab Mon Sep 17 00:00:00 2001 From: renzon Date: Mon, 1 Sep 2014 09:47:13 -0300 Subject: [PATCH 03/35] =?UTF-8?q?Adicionando=20documenta=C3=A7=C3=A3o=20pa?= =?UTF-8?q?ra=20atores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atores.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/atores.py b/atores.py index f21bcd755..7c970664f 100644 --- a/atores.py +++ b/atores.py @@ -9,19 +9,46 @@ class Ator(): + """ + Classe que representa um ator. Ele representa um ponto cartesiano na tela. + """ _caracter_ativo = 'A' _caracter_destruido = ' ' def __init__(self, x=0, y=0): + """ + 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 + """ self.y = y self.x = x self.caracter = self._caracter_ativo self.status = ATIVO def calcular_posicao(self, tempo): + """ + Método que calcula a posição do ator em determinado tempo. + Deve-se imaginar que o tempo começa em 0 e avança de 0,01 segundos + + :param tempo: o tempo do jogo + :return: posição x, y do ator + """ return self.x, self.y 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 + destruido, seus caracteres para destruido também. + + :param outro_ator: Ator a ser considerado na colisão + :param intervalo: Intervalo a ser considerado + :return: + """ if self.status == DESTRUIDO or outro_ator.status == DESTRUIDO: return @@ -45,6 +72,15 @@ class Passaro(Ator): velocidade_escalar = None 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 + lançamento e angulo de lançamento + + :param x: + :param y: + """ super().__init__(x, y) self._x_inicial = x self._y_inicial = y @@ -52,12 +88,22 @@ def __init__(self, x=0, y=0): self._angulo_de_lancamento = None # radianos def foi_lancado(self): + """ + Método que retorna verdaeira se o pássaro já foi lançado e falso caso contrário + + :return: booleano + """ return self._tempo_de_lancamento is not None 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 + + """ if self.y <= 0: self.status = DESTRUIDO - self.caracter=self._caracter_destruido + self.caracter = self._caracter_destruido def _calcular_posicao_horizontal(self, delta_t): self.x = self._x_inicial + self.velocidade_escalar * delta_t * math.cos(self._angulo_de_lancamento) @@ -73,6 +119,19 @@ def _calcular_posicao(self, tempo): self._calcular_posicao_horizontal(delta_t) 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 + + 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. + + :param tempo: tempo de jogo a ser calculada a posição + :return: posição x, y + """ if self._tempo_de_lancamento is None: return self._x_inicial, self._y_inicial if self.status == ATIVO: @@ -80,8 +139,16 @@ def calcular_posicao(self, tempo): return self.x, self.y - def lancar(self, angulo, tempo): - self._tempo_de_lancamento = tempo + 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. + O ângulo é passado em graus e deve ser transformado em radianos + + :param angulo: + :param tempo_de_lancamento: + :return: + """ + self._tempo_de_lancamento = tempo_de_lancamento self._angulo_de_lancamento = math.radians(angulo) def _aguardando_lancamento(self, tempo): From f67b4c455aa0f67990693e0b2394ce2cbe1190e7 Mon Sep 17 00:00:00 2001 From: renzon Date: Mon, 1 Sep 2014 09:56:41 -0300 Subject: [PATCH 04/35] =?UTF-8?q?Documenta=C3=A7=C3=A3o=20da=20classe=20fa?= =?UTF-8?q?se?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fase.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/fase.py b/fase.py index 27ddbdbd9..ae8de5c16 100644 --- a/fase.py +++ b/fase.py @@ -18,6 +18,11 @@ def __repr__(self, *args, **kwargs): class Fase(): def __init__(self, intervalo_de_colisao=1): + """ + Método que inicializa uma fase. + + :param intervalo_de_colisao: + """ self.intervalo_de_colisao = intervalo_de_colisao self._passaros = [] self._porcos = [] @@ -27,18 +32,54 @@ def _adicionar_ator(self, lista, *atores): lista.extend(atores) def adicionar_obstaculo(self, *obstaculos): + """ + Adiciona obstáculos em uma fase + + :param obstaculos: + """ self._adicionar_ator(self._obstaculos, *obstaculos) def adicionar_porco(self, *porcos): + """ + Adiciona porcos em uma fase + + :param porcos: + """ self._adicionar_ator(self._porcos, *porcos) def adicionar_passaro(self, *passaros): + """ + Adiciona pássaros em uma fase + + :param passaros: + """ self._adicionar_ator(self._passaros, *passaros) def acabou(self): + """ + Método que retorna verdadeiro se o jogo acabou e falso caso contrário + + O jogo pode acabar por dois motivos: + + 1. Não existem mais porcos ativos no jogo + 2. Não existem mais pássaros ativos no jogo + + :return: booleano + """ return not self._existe_porco_ativo() or not self._existe_passaro_ativo() def status(self): + """ + Método que indica com mensagem o status do jogo + + Se o jogo está em andamento (ainda tem porco ativo e pássaro ativo), retorna essa mensagem. + + Se o jogo acabou com derrota (ainda existe porco ativo), retorna essa mensagem + + Se o jogo acabou com vitória (não existe porco ativo), retorna essa mensagem + + :return: + """ if not self._existe_porco_ativo(): return 'Jogo em encerrado. Você ganhou!' if self._existe_passaro_ativo(): @@ -46,6 +87,16 @@ def status(self): return 'Jogo em encerrado. Você perdeu!' def lancar(self, angulo, tempo): + """ + Método que executa lógica de lançamento. + + Deve escolher o primeiro pássaro não lançado da lista e chamar seu método lançar + + 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 + """ for passaro in self._passaros: if not passaro.foi_lancado(): passaro.lancar(angulo, tempo) @@ -53,6 +104,14 @@ def lancar(self, angulo, tempo): def calcular_pontos(self, tempo): + """ + Lógica que retorna os pontos a serem exibidos na tela. + + Cada ator deve ser transformado em um Ponto. + + :param tempo: tempo para o qual devem ser calculados os pontos + :return: objeto do tipo Ponto + """ pontos = [self._calcular_ponto_de_passaro(p, tempo) for p in self._passaros] obstaculos_e_porcos = chain(self._obstaculos, self._porcos) pontos.extend([self._transformar_em_ponto(ator) for ator in obstaculos_e_porcos]) From 3f0d4f9f3ac972b2cd7d7afd2bcbebfb9430ec3c Mon Sep 17 00:00:00 2001 From: renzon Date: Mon, 1 Sep 2014 10:21:52 -0300 Subject: [PATCH 05/35] =?UTF-8?q?Documenta=C3=A7=C3=A3o=20da=20classe=20fa?= =?UTF-8?q?se?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 49 ++++++++++++---------------------------- placa_grafica_tkinter.py | 4 +++- testes/fase_testes.py | 25 ++++++++++++-------- 3 files changed, 34 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index c331ec17e..fabf1efed 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ Python Birds =========== +Essa versão é a mais simples. Ela não contém replay nem reset, de forma que o jogo não pode retroceder. + +Para versão mais complexa, acesse a branch [master](https://github.com/pythonprobr/pythonbirds/tree/master) + Projeto para Ensino de Programação Orientadas a Objetos em Python. A versão utilizada para desenvolvimento foi Python 3.4 @@ -11,20 +15,20 @@ Um vídeo fala mais que 1000 palavras: [Python Birds](https://www.youtube.com/wa Instalar [Python 3](https://www.python.org/download/). -Baixar a versão contendo apenas a [estrutura do projeto](https://github.com/pythonprobr/pythonbirds/archive/diversao.zip) +Baixar o zip do projeto (botão Download Zip) Os testes se encontram dentro do pacote "testes" e servem para definir a dinâmica das classes. Para rodar todos testes, execute python executor_de_testes.py -Explicação detalhada sobre classes e métodos se encontram em [Simplificação do Jogo](#simplifica%C3%A7%C3%A3o-do-jogo) +Explicação detalhada sobre classes e métodos se encontram nos scripts atores.py e fase.py ## Ordem de desenvolvimento A ordem preferida é começar pelos atores, seguindo a ordem dos testes presentes no script atores_testes.py. Depois passar para a fase_teste.py, onde é implementada uma fase. -Após o desenvolvimento é possível emular um jogo que termina em vitória rodando: +É possível emular um jogo que termina em vitória rodando: python fase_testes.py @@ -70,27 +74,10 @@ Classe base para todos atores do jogo. Método que recebe o tempo (float) como parâmetro e retorna uma tupla com 2 elementos, posição horizontal (x) como primeiro elemento e posição vertical (y) como segundo. -### Método resetar - -Método que ao ser executado, seta o valor de _tempo_de_colisão para None - -### Método status - -O ator possui os status Ativo ou Destruido. Além disso o status deve ser dependente do tempo. Ou seja, se o ator foi -destruido no tempo 1, ele deve possuir status Ativo antes desse tempo, como 0.9, e Destruido após esse tempo, como em tempo 1.1. - ### Método colidir O método colidir executa a lógica de colisão. A colisão só ocorre com atores ativos e que estejam em pontos vizinhos. -O ator deve guardar o tempo de colisão para calcular corretamente seu status. -Além disso, um intervalo é recebido como parâmetro indicando qual a tolerância para considerar um ponto vizinho. - Por padrão, seu valor é 1. - -## Método caracter - -O método caracter retorna 'A' quando o ator tem status Ativo e '+' caso contrário. Também é depende do tempo. - ## Classe Obstaculo @@ -111,38 +98,31 @@ representação é a o caracter "@". Classe base de todos os passáros. Cada tipo possui uma velocidade de lançamento (v). No lançamento o jogador escolhe o ângulo (teta), em graus, no qual o passáro deve ser lançado. O lançamento respeita as regras de lançamento oblíquo com -gravidade (G) constante e igual a 10 m/s^2. +gravidade (GRAVIDADE) constante e igual a 10 m/s^2. ### Método lancar O método lançar recebe o ângulo, em graus, que será feito o lançamento. Cada pássaro deve armazenar esse valor e o tempo de lançamento para cálculo de sua posíção. Lembrar que o tempo das fórmulas é delta_t = T_final - T_inicial -### Método de resetar - -O método resetar deve chamar o método resetar de Ator. -Além disso, deve setar como Nome os parầmetros de tempo de lançamento e ângulo de lançamento - ### Método de colidir_com_chao Todo pássaro que colidir com o chão (y<=0) deve ser destruído. -### Método foi lançado +### Método foi_lançado Esse método deve retornar verdadadeiro se o pássaro foi lançado (tempo de lançamento é None). Caso contrário deve retornar falso -### Lançamentomento +### Lançamento -Se o pássaro ainda não foi lançado, ou se o tempo de jogo é menor que o tempo de lançamento, -O pássaro deve permanecer na posição inicial. +Se o pássaro ainda não foi lançado, o pássaro deve permanecer na posição inicial. -Calso tenha sido lançado e seu status esteja ativo, sua posição deve ser calculada de acordo com o lançamento oblíquo. +Caso tenha sido lançado e seu status esteja ativo, sua posição deve ser calculada de acordo com o lançamento oblíquo. Nesse caso, delta_t vai ser igual ao tempo do jogo menos o tempo do lançamento. -Caso contrário, ele deve retornar a posição onde colidiu. Para isso, pasta -calcular o ponto em que o pássaro estava no tempo da colisão. +Caso contrário, ele deve retornar a posição onde colidiu. #### Método posicao_horizontal @@ -195,7 +175,8 @@ Recebe o tempo como parâmetro e retorna mensagem com status do jogo. ### Método lancar -Recebe o ângulo e o tempo do lançamento. Deve delegar o lançamento ao primeiro pássaro ativo da lista de pássaros. +Recebe o ângulo e o tempo do lançamento. Deve delegar o lançamento ao primeiro pássaro ativo da lista de pássaros que +ainda não foi lançado. ### Método calcular_pontos diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index 0d619e026..f769056f1 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -73,7 +73,7 @@ def _animar(): camada_de_atores.create_line(52, 493, 52 + tamanho_seta * math.cos(angulo_rad), 493 + tamanho_seta * math.sin(angulo_rad), width=1.5) - camada_de_atores.create_text(35, 493, text=u"%d°" % angulo) + 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) @@ -88,6 +88,7 @@ def _ouvir_comandos_lancamento(evento): fase.lancar(angulo, tempo) def _replay(event): + return nonlocal tempo nonlocal delta_t if fase.acabou(tempo): @@ -96,6 +97,7 @@ def _replay(event): def _jogar_novamente(event): + return nonlocal tempo nonlocal delta_t if fase.acabou(tempo): diff --git a/testes/fase_testes.py b/testes/fase_testes.py index 2d8fdd832..ca5b748eb 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -2,17 +2,22 @@ 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 from fase import Fase, Ponto -import placa_grafica class FaseTestes(TestCase): @@ -192,19 +197,21 @@ def teste_calcular_pontos(self): fase_exemplo.calcular_pontos(i / 100) print(fase_exemplo.calcular_pontos(8.5)) - - expected = [Ponto(32,11,'v'), Ponto(77,0,'a'), Ponto(70,2,'a'), Ponto(31,10,' '), Ponto(78,1,'+'), Ponto(70,1,'+')] + expected = [Ponto(32, 11, 'v'), Ponto(77, 0, 'a'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '+'), + Ponto(70, 1, '+')] self.assertListEqual(expected, fase_exemplo.calcular_pontos(8.5)) self.assertTrue(fase_exemplo.acabou()) -def criar_fase_exemplo(): - fase_exemplo = Fase() - passaros = [PassaroVermelho(3, 3), PassaroAmarelo(3, 3), PassaroAmarelo(3, 3)] - porcos = [Porco(78, 1), Porco(70, 1)] - obstaculos = [Obstaculo(31, 10)] +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) @@ -214,4 +221,4 @@ def criar_fase_exemplo(): if __name__ == '__main__': - placa_grafica.animar(criar_fase_exemplo()) + rodar_fase(criar_fase_exemplo(10)) From a6a3ecbf2bc37b1011e19699fcd11a88d1d97bd8 Mon Sep 17 00:00:00 2001 From: renzon Date: Mon, 1 Sep 2014 10:30:12 -0300 Subject: [PATCH 06/35] =?UTF-8?q?Retirada=20de=20l=C3=B3gica=20de=20compon?= =?UTF-8?q?entes=20a=20serem=20implementados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atores.py | 61 ++++++++++--------------------------------------------- fase.py | 48 ++++++++----------------------------------- 2 files changed, 19 insertions(+), 90 deletions(-) diff --git a/atores.py b/atores.py index 7c970664f..de8bd9765 100644 --- a/atores.py +++ b/atores.py @@ -35,7 +35,7 @@ def calcular_posicao(self, tempo): :param tempo: o tempo do jogo :return: posição x, y do ator """ - return self.x, self.y + return 1, 1 def colidir(self, outro_ator, intervalo=1): """ @@ -47,29 +47,20 @@ def colidir(self, outro_ator, intervalo=1): :param outro_ator: Ator a ser considerado na colisão :param intervalo: Intervalo a ser considerado - :return: """ - 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: - self.status = DESTRUIDO - self.caracter = self._caracter_destruido - outro_ator.caracter = outro_ator._caracter_destruido - outro_ator.status = DESTRUIDO + pass class Obstaculo(Ator): - _caracter_ativo = 'O' + pass class Porco(Ator): - _caracter_ativo = '@' - _caracter_destruido = '+' + pass class Passaro(Ator): - velocidade_escalar = None + velocidade_escalar = 10 def __init__(self, x=0, y=0): """ @@ -93,7 +84,7 @@ def foi_lancado(self): :return: booleano """ - return self._tempo_de_lancamento is not None + return True def colidir_com_chao(self): """ @@ -101,22 +92,7 @@ def colidir_com_chao(self): o status dos Passaro deve ser alterado para destruido, bem como o seu caracter """ - if self.y <= 0: - self.status = DESTRUIDO - self.caracter = self._caracter_destruido - - def _calcular_posicao_horizontal(self, delta_t): - 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) - - (GRAVIDADE / 2) * delta_t ** 2) - - def _calcular_posicao(self, tempo): - delta_t = tempo - self._tempo_de_lancamento - self._calcular_posicao_vertical(delta_t) - self._calcular_posicao_horizontal(delta_t) + pass def calcular_posicao(self, tempo): """ @@ -132,11 +108,7 @@ def calcular_posicao(self, tempo): :param tempo: tempo de jogo a ser calculada a posição :return: posição x, y """ - if self._tempo_de_lancamento is None: - return self._x_inicial, self._y_inicial - if self.status == ATIVO: - self._calcular_posicao(tempo) - return self.x, self.y + return 1, 1 def lancar(self, angulo, tempo_de_lancamento): @@ -148,23 +120,12 @@ def lancar(self, angulo, tempo_de_lancamento): :param tempo_de_lancamento: :return: """ - self._tempo_de_lancamento = tempo_de_lancamento - self._angulo_de_lancamento = math.radians(angulo) - - def _aguardando_lancamento(self, tempo): - return not self.foi_lancado() or tempo < self._tempo_de_lancamento - - def _ja_colidiu(self): - return self.foi_lancado() and self.status() == DESTRUIDO + pass class PassaroAmarelo(Passaro): - velocidade_escalar = 30 # m/s - _caracter_ativo = 'A' - _caracter_destruido = 'a' + pass class PassaroVermelho(Passaro): - velocidade_escalar = 20 # m/s - _caracter_ativo = 'V' - _caracter_destruido = 'v' + pass \ No newline at end of file diff --git a/fase.py b/fase.py index ae8de5c16..e4c8c7715 100644 --- a/fase.py +++ b/fase.py @@ -28,8 +28,6 @@ def __init__(self, intervalo_de_colisao=1): self._porcos = [] self._obstaculos = [] - def _adicionar_ator(self, lista, *atores): - lista.extend(atores) def adicionar_obstaculo(self, *obstaculos): """ @@ -37,7 +35,7 @@ def adicionar_obstaculo(self, *obstaculos): :param obstaculos: """ - self._adicionar_ator(self._obstaculos, *obstaculos) + pass def adicionar_porco(self, *porcos): """ @@ -45,7 +43,7 @@ def adicionar_porco(self, *porcos): :param porcos: """ - self._adicionar_ator(self._porcos, *porcos) + pass def adicionar_passaro(self, *passaros): """ @@ -53,7 +51,7 @@ def adicionar_passaro(self, *passaros): :param passaros: """ - self._adicionar_ator(self._passaros, *passaros) + pass def acabou(self): """ @@ -66,7 +64,7 @@ def acabou(self): :return: booleano """ - return not self._existe_porco_ativo() or not self._existe_passaro_ativo() + return True def status(self): """ @@ -78,12 +76,8 @@ def status(self): Se o jogo acabou com vitória (não existe porco ativo), retorna essa mensagem - :return: + :return: Mensagem de status """ - if not self._existe_porco_ativo(): - return 'Jogo em encerrado. Você ganhou!' - if self._existe_passaro_ativo(): - return 'Jogo em andamento.' return 'Jogo em encerrado. Você perdeu!' def lancar(self, angulo, tempo): @@ -97,11 +91,7 @@ def lancar(self, angulo, tempo): :param angulo: ângulo de lançamento :param tempo: Tempo de lançamento """ - for passaro in self._passaros: - if not passaro.foi_lancado(): - passaro.lancar(angulo, tempo) - return - + pass def calcular_pontos(self, tempo): """ @@ -112,32 +102,10 @@ def calcular_pontos(self, tempo): :param tempo: tempo para o qual devem ser calculados os pontos :return: objeto do tipo Ponto """ - pontos = [self._calcular_ponto_de_passaro(p, tempo) for p in self._passaros] - obstaculos_e_porcos = chain(self._obstaculos, self._porcos) - pontos.extend([self._transformar_em_ponto(ator) for ator in obstaculos_e_porcos]) + pontos=[] + return pontos def _transformar_em_ponto(self, ator): return Ponto(ator.x, ator.y, ator.caracter) - def _calcular_ponto_de_passaro(self, passaro, tempo, ): - passaro.calcular_posicao(tempo) - for ator in chain(self._obstaculos, self._porcos): - if ATIVO == passaro.status: - passaro.colidir(ator, self.intervalo_de_colisao) - passaro.colidir_com_chao() - else: - break - return self._transformar_em_ponto(passaro) - - def _existe_porco_ativo(self): - return self._verificar_se_existe_ator_ativo(self._porcos) - - def _verificar_se_existe_ator_ativo(self, atores): - for a in atores: - if a.status == ATIVO: - return True - return False - - def _existe_passaro_ativo(self): - return self._verificar_se_existe_ator_ativo(self._passaros) From f9d0e43b0ece8b4579d5ac73448891b66d25d280 Mon Sep 17 00:00:00 2001 From: renzon Date: Mon, 1 Sep 2014 10:33:42 -0300 Subject: [PATCH 07/35] =?UTF-8?q?Consertando=20branch=20com=20vers=C3=A3o?= =?UTF-8?q?=20mais=20complexa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fabf1efed..db6f28be8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Python Birds Essa versão é a mais simples. Ela não contém replay nem reset, de forma que o jogo não pode retroceder. -Para versão mais complexa, acesse a branch [master](https://github.com/pythonprobr/pythonbirds/tree/master) +Para versão mais complexa, acesse a branch [diversao](https://github.com/pythonprobr/pythonbirds/tree/diversao) Projeto para Ensino de Programação Orientadas a Objetos em Python. From 9a879e44693f773423e4c7a65cd5dbcfe97d9562 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 8 Oct 2014 23:21:06 -0300 Subject: [PATCH 08/35] Rodando testes de atores pelo console --- testes/atores_testes.py | 16 ++++++++++++++++ testes/fase_testes.py | 7 +++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 675814b5d..6963467f8 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -1,6 +1,18 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + +import sys +from os import path +import unittest + +project_dir = path.dirname(__file__) +project_dir = path.join('..') +sys.path.append(project_dir) + +project_dir = path.join(path.dirname(__file__), '..') +project_dir = path.normpath(project_dir) +sys.path.append(project_dir) from unittest.case import TestCase from atores import Ator, DESTRUIDO, ATIVO, Obstaculo, Porco, PassaroAmarelo, PassaroVermelho @@ -681,3 +693,7 @@ def test_lancamento_45_graus(self): # t = 2 + (delta_t / 100) # x, y = passaro_amarelo.calcular_posicao(t) # print(' self.assert_passaro_posicao(%s, %s, ATIVO, passaro_amarelo, %s)' % (x, y, t)) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/testes/fase_testes.py b/testes/fase_testes.py index ca5b748eb..5de7aaba8 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -from itertools import chain import os from os import path +import unittest from unittest.case import TestCase import math import sys @@ -10,13 +10,12 @@ 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 +from atores import Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, DESTRUIDO from fase import Fase, Ponto @@ -221,4 +220,4 @@ def criar_fase_exemplo(multiplicador=1): if __name__ == '__main__': - rodar_fase(criar_fase_exemplo(10)) + unittest.main() From b3a5a951bb6f7b2115f1a575a1559d01de0e6c41 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 8 Oct 2014 23:37:19 -0300 Subject: [PATCH 09/35] =?UTF-8?q?Melhorando=20intervalo=20de=20colis=C3=A3?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- placa_grafica_tkinter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index f769056f1..b44c82030 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -134,7 +134,7 @@ def rodar_fase(fase): if __name__ == '__main__': - fase = Fase(intervalo_de_colisao=10) + fase = Fase(intervalo_de_colisao=32) passaros = [PassaroVermelho(30, 30), PassaroAmarelo(30, 30), PassaroAmarelo(30, 30)] porcos = [Porco(750, 1), Porco(700, 1)] obstaculos = [Obstaculo(310, 100)] From c44cc81c133c7d6d12ba26c1240d765592c0ef60 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 8 Oct 2014 23:38:08 -0300 Subject: [PATCH 10/35] =?UTF-8?q?Melhorando=20intervalo=20de=20colis=C3=A3?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fases/escudo_espartano.py | 2 +- fases/rodar_fase_exemplo.py | 2 +- placa_grafica_tkinter.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fases/escudo_espartano.py b/fases/escudo_espartano.py index b5478e16c..9b01135f0 100644 --- a/fases/escudo_espartano.py +++ b/fases/escudo_espartano.py @@ -13,7 +13,7 @@ from random import randint if __name__ == '__main__': - fase = Fase(intervalo_de_colisao=10) + fase = Fase(intervalo_de_colisao=32) # Adicionar Pássaros Amarelos diff --git a/fases/rodar_fase_exemplo.py b/fases/rodar_fase_exemplo.py index 26cbc27f5..0f67e4cf1 100644 --- a/fases/rodar_fase_exemplo.py +++ b/fases/rodar_fase_exemplo.py @@ -11,7 +11,7 @@ from placa_grafica_tkinter import rodar_fase if __name__ == '__main__': - fase = Fase(intervalo_de_colisao=10) + fase = Fase(intervalo_de_colisao=32) # Adicionar Pássaros Vermelhos diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index f769056f1..b44c82030 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -134,7 +134,7 @@ def rodar_fase(fase): if __name__ == '__main__': - fase = Fase(intervalo_de_colisao=10) + fase = Fase(intervalo_de_colisao=32) passaros = [PassaroVermelho(30, 30), PassaroAmarelo(30, 30), PassaroAmarelo(30, 30)] porcos = [Porco(750, 1), Porco(700, 1)] obstaculos = [Obstaculo(310, 100)] From d3fc0f6b4cde45ccf6d49acbb6d32a9e8c4715ec Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 8 Oct 2014 23:38:27 -0300 Subject: [PATCH 11/35] =?UTF-8?q?Melhorando=20intervalo=20de=20colis=C3=A3?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fases/escudo_espartano.py | 2 +- fases/rodar_fase_exemplo.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fases/escudo_espartano.py b/fases/escudo_espartano.py index b5478e16c..9b01135f0 100644 --- a/fases/escudo_espartano.py +++ b/fases/escudo_espartano.py @@ -13,7 +13,7 @@ from random import randint if __name__ == '__main__': - fase = Fase(intervalo_de_colisao=10) + fase = Fase(intervalo_de_colisao=32) # Adicionar Pássaros Amarelos diff --git a/fases/rodar_fase_exemplo.py b/fases/rodar_fase_exemplo.py index 26cbc27f5..0f67e4cf1 100644 --- a/fases/rodar_fase_exemplo.py +++ b/fases/rodar_fase_exemplo.py @@ -11,7 +11,7 @@ from placa_grafica_tkinter import rodar_fase if __name__ == '__main__': - fase = Fase(intervalo_de_colisao=10) + fase = Fase(intervalo_de_colisao=32) # Adicionar Pássaros Vermelhos From a110c7b09627715fc877f29f9e3c844994c98011 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 14:24:04 -0200 Subject: [PATCH 12/35] close #6 --- atores.py | 6 +++--- fase.py | 2 +- testes/atores_testes.py | 24 ++++++++++++------------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/atores.py b/atores.py index 7c970664f..a79a0cbd4 100644 --- a/atores.py +++ b/atores.py @@ -24,9 +24,11 @@ def __init__(self, x=0, y=0): """ self.y = y self.x = x - self.caracter = self._caracter_ativo self.status = ATIVO + def caracter(self): + return self._caracter_ativo if self.status == ATIVO else self._caracter_destruido + def calcular_posicao(self, tempo): """ Método que calcula a posição do ator em determinado tempo. @@ -54,8 +56,6 @@ def colidir(self, outro_ator, intervalo=1): if self.x - intervalo <= outro_ator.x <= self.x + intervalo and self.y - intervalo <= outro_ator.y <= self.y + intervalo: self.status = DESTRUIDO - self.caracter = self._caracter_destruido - outro_ator.caracter = outro_ator._caracter_destruido outro_ator.status = DESTRUIDO diff --git a/fase.py b/fase.py index ae8de5c16..64afcca4a 100644 --- a/fase.py +++ b/fase.py @@ -118,7 +118,7 @@ def calcular_pontos(self, tempo): return pontos def _transformar_em_ponto(self, ator): - return Ponto(ator.x, ator.y, ator.caracter) + return Ponto(ator.x, ator.y, ator.caracter()) def _calcular_ponto_de_passaro(self, passaro, tempo, ): passaro.calcular_posicao(tempo) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 675814b5d..939cba661 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -11,14 +11,14 @@ def teste_valores_padrao(self): self.assertEqual(0, ator.x) self.assertEqual(0, ator.y) self.assertEqual(ATIVO, ator.status) - self.assertEqual('A', ator.caracter) + self.assertEqual('A', ator.caracter()) def teste_valores_passados_por_parametro(self): ator = Ator(1, 2) self.assertEqual(1, ator.x) self.assertEqual(2, ator.y) self.assertEqual(ATIVO, ator.status) - self.assertEqual('A', ator.caracter) + self.assertEqual('A', ator.caracter()) def teste_ator_posicao(self): 'Teste que verifica que o ator comum não deve se mover independente do tempo do jogo' @@ -85,10 +85,10 @@ def teste_colisao_somente_um_ator_destruido(self): def test_caracter(self): ator = Ator() - self.assertEqual('A', ator.caracter) + self.assertEqual('A', ator.caracter()) outro_ator_na_mesma_posicao = Ator() ator.colidir(outro_ator_na_mesma_posicao) - self.assertEqual(' ', ator.caracter) + self.assertEqual(' ', ator.caracter()) def assert_colisao_atores_ativos(self, ator, ator2, intervalo=1): @@ -117,19 +117,19 @@ def assert_nao_colisao(self, ator, ator2): class ObstaculoTestes(TestCase): def teste_status(self): obstaculo = Obstaculo() - self.assertEqual('O', obstaculo.caracter) + self.assertEqual('O', obstaculo.caracter()) outro_ator_na_mesma_posicao = Ator() obstaculo.colidir(outro_ator_na_mesma_posicao) - self.assertEqual(' ', obstaculo.caracter) + self.assertEqual(' ', obstaculo.caracter()) class PorcoTestes(TestCase): def teste_status(self): porco = Porco() - self.assertEqual('@', porco.caracter) + self.assertEqual('@', porco.caracter()) outro_ator_na_mesma_posicao = Ator() porco.colidir(outro_ator_na_mesma_posicao) - self.assertEqual('+', porco.caracter) + self.assertEqual('+', porco.caracter()) class PassaroBaseTests(TestCase): @@ -143,10 +143,10 @@ def assert_passaro_posicao(self, x_esperado, y_esperado, status_esperado, passar class PassaroVermelhoTests(PassaroBaseTests): def teste_status(self): passaro_amarelo = PassaroVermelho(1, 1) - self.assertEqual('V', passaro_amarelo.caracter) + self.assertEqual('V', passaro_amarelo.caracter()) outro_ator_na_mesma_posicao = Ator() passaro_amarelo.colidir(outro_ator_na_mesma_posicao) - self.assertEqual('v', passaro_amarelo.caracter) + self.assertEqual('v', passaro_amarelo.caracter()) def teste_velocidade_escalar(self): @@ -182,10 +182,10 @@ def teste_colisao_com_chao(self): class PassaroAmareloTests(PassaroBaseTests): def teste_status(self): passaro_amarelo = PassaroAmarelo(1, 1) - self.assertEqual('A', passaro_amarelo.caracter) + self.assertEqual('A', passaro_amarelo.caracter()) outro_ator_na_mesma_posicao = Ator() passaro_amarelo.colidir(outro_ator_na_mesma_posicao) - self.assertEqual('a', passaro_amarelo.caracter) + self.assertEqual('a', passaro_amarelo.caracter()) def teste_velocidade_escalar(self): self.assertEqual(30, PassaroAmarelo.velocidade_escalar) From 3b8265b2289aa4f7bb2154613adc4e2fbc0f0615 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 14:46:28 -0200 Subject: [PATCH 13/35] close #8 --- fase.py | 38 ++++++++++++++++++++++---------------- placa_grafica_tkinter.py | 4 ++-- testes/fase_testes.py | 28 ++++++++++++++-------------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/fase.py b/fase.py index 64afcca4a..90f601efa 100644 --- a/fase.py +++ b/fase.py @@ -2,6 +2,12 @@ from itertools import chain from atores import ATIVO +# Status possíveis do jogo + +VITORIA = 'VITORIA' +DERROTA = 'DERROTA' +EM_ANDAMENTO = 'EM_ANDAMENTO' + class Ponto(): def __init__(self, x, y, caracter): @@ -55,18 +61,18 @@ def adicionar_passaro(self, *passaros): """ self._adicionar_ator(self._passaros, *passaros) - def acabou(self): - """ - Método que retorna verdadeiro se o jogo acabou e falso caso contrário - - O jogo pode acabar por dois motivos: - - 1. Não existem mais porcos ativos no jogo - 2. Não existem mais pássaros ativos no jogo - - :return: booleano - """ - return not self._existe_porco_ativo() or not self._existe_passaro_ativo() + # def acabou(self): + # """ + # Método que retorna verdadeiro se o jogo acabou e falso caso contrário + # + # O jogo pode acabar por dois motivos: + # + # 1. Não existem mais porcos ativos no jogo + # 2. Não existem mais pássaros ativos no jogo + # + # :return: booleano + # """ + # return self.status() != EM_ANDAMENTO def status(self): """ @@ -81,10 +87,10 @@ def status(self): :return: """ if not self._existe_porco_ativo(): - return 'Jogo em encerrado. Você ganhou!' + return VITORIA if self._existe_passaro_ativo(): - return 'Jogo em andamento.' - return 'Jogo em encerrado. Você perdeu!' + return EM_ANDAMENTO + return DERROTA def lancar(self, angulo, tempo): """ @@ -128,7 +134,7 @@ def _calcular_ponto_de_passaro(self, passaro, tempo, ): passaro.colidir_com_chao() else: break - return self._transformar_em_ponto(passaro) + return self._transformar_em_ponto(passaro) def _existe_porco_ativo(self): return self._verificar_se_existe_ator_ativo(self._porcos) diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index b44c82030..e4368668e 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -6,7 +6,7 @@ from os import path import atores -from fase import Fase +from fase import Fase, EM_ANDAMENTO from atores import PassaroVermelho, PassaroAmarelo, Porco, Obstaculo ALTURA_DA_TELA = 600 # px @@ -57,7 +57,7 @@ def _animar(): if tempo <= 0: tempo = 0 delta_t /= -multiplicador_rebobinar - if fase.acabou(): + if fase.status()!=EM_ANDAMENTO: camada_de_atores.create_image(162, 55, image=PYTHONBIRDS_LOGO, anchor=NW) camada_de_atores.create_image(54, 540, image=MENU, anchor=NW) if 'ganhou' in fase.status(): diff --git a/testes/fase_testes.py b/testes/fase_testes.py index ca5b748eb..1580fa8d1 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -17,7 +17,7 @@ sys.path.append(project_dir) from atores import Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, DESTRUIDO, ATIVO -from fase import Fase, Ponto +from fase import Fase, Ponto, EM_ANDAMENTO, VITORIA, DERROTA class FaseTestes(TestCase): @@ -57,7 +57,7 @@ def teste_adicionar_passaro(self): def teste_acabou_sem_porcos(self): fase = Fase() - self.assertTrue(fase.acabou()) + self.assertEqual(VITORIA, fase.status()) def teste_acabou_com_porcos_e_passaros(self): fase = Fase() @@ -66,22 +66,22 @@ def teste_acabou_com_porcos_e_passaros(self): fase.adicionar_porco(*porcos) fase.adicionar_passaro(*passaros) - self.assertFalse(fase.acabou()) + 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.assertTrue(fase.acabou()) + self.assertEqual(VITORIA, fase.status()) fase.adicionar_obstaculo(Obstaculo()) - self.assertTrue(fase.acabou(), '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.assertTrue(fase.acabou(), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar') + self.assertEqual(DERROTA, fase.status(), 'Com Porco ativo e sem pássaro para lançar, o jogo deveria acabar') fase.adicionar_passaro(PassaroAmarelo()) - self.assertFalse(fase.acabou(), 'Com Porco ativo e com pássaro para lançar, o jogo não deveria acabar') + 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() @@ -89,29 +89,29 @@ def teste_status(self): passaros = [PassaroAmarelo(1, 1) for i in range(2)] fase.adicionar_porco(*porcos) fase.adicionar_passaro(*passaros) - self.assertEqual('Jogo em andamento.', fase.status()) + self.assertEqual(EM_ANDAMENTO, fase.status()) for passaro, porco in zip(passaros, porcos): passaro.colidir(porco, 3) - self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(), + self.assertEqual(VITORIA, fase.status(), 'Sem porcos ativos o jogo deveria terminar com vitória') fase.adicionar_obstaculo(Obstaculo()) - self.assertEqual('Jogo em encerrado. Você ganhou!', fase.status(), + self.assertEqual(VITORIA, fase.status(), 'Obstáculo não interfere para definir vitória') porco = Porco() fase.adicionar_porco(porco) - self.assertEqual('Jogo em encerrado. Você perdeu!', fase.status(), + 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('Jogo em andamento.', fase.status(), + 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('Jogo em encerrado. Você ganhou!', fase.status(), + 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): @@ -202,7 +202,7 @@ def teste_calcular_pontos(self): self.assertListEqual(expected, fase_exemplo.calcular_pontos(8.5)) - self.assertTrue(fase_exemplo.acabou()) + self.assertEqual(VITORIA, fase_exemplo.status()) def criar_fase_exemplo(multiplicador=1): From c65ace8edeee3fbd683d88b20e4274ad95958316 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 14:46:51 -0200 Subject: [PATCH 14/35] close #8 --- fase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fase.py b/fase.py index 90f601efa..9a288c4ed 100644 --- a/fase.py +++ b/fase.py @@ -134,7 +134,7 @@ def _calcular_ponto_de_passaro(self, passaro, tempo, ): passaro.colidir_com_chao() else: break - return self._transformar_em_ponto(passaro) + return self._transformar_em_ponto(passaro) def _existe_porco_ativo(self): return self._verificar_se_existe_ator_ativo(self._porcos) From c5b3ede6e8d0d09ef328d74ef9e8418c4f89ea9c Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 14:50:12 -0200 Subject: [PATCH 15/35] close #8 --- atores.py | 1 - placa_grafica_tkinter.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/atores.py b/atores.py index a79a0cbd4..8f9a82f49 100644 --- a/atores.py +++ b/atores.py @@ -103,7 +103,6 @@ def colidir_com_chao(self): """ if self.y <= 0: self.status = DESTRUIDO - self.caracter = self._caracter_destruido def _calcular_posicao_horizontal(self, delta_t): self.x = self._x_inicial + self.velocidade_escalar * delta_t * math.cos(self._angulo_de_lancamento) diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index e4368668e..918a02d17 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -6,7 +6,7 @@ from os import path import atores -from fase import Fase, EM_ANDAMENTO +from fase import Fase, EM_ANDAMENTO, VITORIA from atores import PassaroVermelho, PassaroAmarelo, Porco, Obstaculo ALTURA_DA_TELA = 600 # px @@ -57,10 +57,10 @@ def _animar(): if tempo <= 0: tempo = 0 delta_t /= -multiplicador_rebobinar - if fase.status()!=EM_ANDAMENTO: + if fase.status() != EM_ANDAMENTO: camada_de_atores.create_image(162, 55, image=PYTHONBIRDS_LOGO, anchor=NW) camada_de_atores.create_image(54, 540, image=MENU, anchor=NW) - if 'ganhou' in fase.status(): + if fase.status() == VITORIA: img = VOCE_GANHOU else: img = VOCE_PERDEU From 1dcad3cafb8100ae0d1b8890c23aeac19da07008 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 14:53:06 -0200 Subject: [PATCH 16/35] #7 teste para apontar o bug --- testes/fase_testes.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/testes/fase_testes.py b/testes/fase_testes.py index 1580fa8d1..ce7b4cfee 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -81,7 +81,8 @@ def teste_acabou_com_porcos_e_passaros(self): 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') + 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() @@ -160,8 +161,8 @@ def teste_intervalo_de_colisao_nao_padrao(self): def teste_calcular_pontos(self): fase_exemplo = criar_fase_exemplo() - expected = [Ponto(3, 3, 'V'), Ponto(3, 3, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, 'O'), Ponto(78, 1, '@'), - Ponto(70, 1, '@')] + expected = [Ponto(3, 3, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, 'O'), Ponto(78, 1, '@'), + Ponto(70, 1, '@'), Ponto(3, 3, 'V')] self.assertListEqual(expected, fase_exemplo.calcular_pontos(0)) fase_exemplo.lancar(45, 1) From a9b490ac6e4620f5c6b949679fd36d3586b7698c Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 15:05:15 -0200 Subject: [PATCH 17/35] close #7 --- fase.py | 5 ++++- testes/fase_testes.py | 25 +++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/fase.py b/fase.py index 9a288c4ed..f54368e96 100644 --- a/fase.py +++ b/fase.py @@ -18,6 +18,9 @@ def __init__(self, x, y, caracter): def __eq__(self, other): return self.x == other.x and self.y == other.y and self.caracter == other.caracter + def __hash__(self): + return hash(self.x) ^ hash(self.y) + def __repr__(self, *args, **kwargs): return "Ponto(%s,%s,'%s')" % (self.x, self.y, self.caracter) @@ -62,7 +65,7 @@ def adicionar_passaro(self, *passaros): self._adicionar_ator(self._passaros, *passaros) # def acabou(self): - # """ + # """ # Método que retorna verdadeiro se o jogo acabou e falso caso contrário # # O jogo pode acabar por dois motivos: diff --git a/testes/fase_testes.py b/testes/fase_testes.py index ce7b4cfee..85067fa95 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -161,9 +161,9 @@ def teste_intervalo_de_colisao_nao_padrao(self): def teste_calcular_pontos(self): fase_exemplo = criar_fase_exemplo() - expected = [Ponto(3, 3, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, 'O'), Ponto(78, 1, '@'), - Ponto(70, 1, '@'), Ponto(3, 3, 'V')] - self.assertListEqual(expected, fase_exemplo.calcular_pontos(0)) + 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) @@ -179,29 +179,30 @@ def teste_calcular_pontos(self): fase_exemplo.lancar(23, 4) - expected = [Ponto(32, 11, 'v'), Ponto(17, 25, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), - Ponto(70, 1, '@')] + expected = set([Ponto(32, 11, 'v'), Ponto(17, 25, 'A'), Ponto(3, 3, 'A'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), + Ponto(70, 1, '@')]) - self.assertListEqual(expected, fase_exemplo.calcular_pontos(4)) + 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 = [Ponto(32, 11, 'v'), Ponto(57, 30, 'A'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), - Ponto(70, 1, '+')] + expected = set( + [Ponto(32, 11, 'v'), Ponto(57, 30, 'A'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '@'), + Ponto(70, 1, '+')]) - self.assertListEqual(expected, fase_exemplo.calcular_pontos(7)) + 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 = [Ponto(32, 11, 'v'), Ponto(77, 0, 'a'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '+'), - Ponto(70, 1, '+')] + expected = set([Ponto(32, 11, 'v'), Ponto(77, 0, 'a'), Ponto(70, 2, 'a'), Ponto(31, 10, ' '), Ponto(78, 1, '+'), + Ponto(70, 1, '+')]) - self.assertListEqual(expected, fase_exemplo.calcular_pontos(8.5)) + self.assertSetEqual(expected, set(fase_exemplo.calcular_pontos(8.5))) self.assertEqual(VITORIA, fase_exemplo.status()) From 84e75e5c44da81005be4a333a95b0a809d3d0583 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 21:06:00 -0200 Subject: [PATCH 18/35] =?UTF-8?q?Consertando=20documenta=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 53 ++++++++------- testes/atores_testes.py | 138 +++++++++++++++++++++++++++++----------- 2 files changed, 126 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index fabf1efed..22bbfbcb4 100644 --- a/README.md +++ b/README.md @@ -55,12 +55,12 @@ Contém lógica para rodar jogo e exibir no console. ## script placa_grafica_tkinter.py -Contém lógica para rodar jogo e em uma janela. +Contém lógica para rodar jogo em uma janela. # Simplificação do Jogo 1. Atores são pontos no plano cartesiano. -2. A velocidade dos pontos e pequena, de tal forma que a cada passo os atores se movam apenas para pontos vizinhos. +2. A velocidade dos pontos é pequena, de tal forma que a cada passo os atores se movam apenas para pontos vizinhos. 3. A colisão entre pontos ocorre quando eles estão em ponto vizinho, de acordo com valor de intervalo. A seguir é apresentada a especificação detalhada do jogo. @@ -77,12 +77,12 @@ primeiro elemento e posição vertical (y) como segundo. ### Método colidir O método colidir executa a lógica de colisão. A colisão só ocorre com atores ativos e que estejam -em pontos vizinhos. +em pontos vizinhos. Ao colidir, os atores envolvidos devem ter seus status alterado para DESTRUIDO ## Classe Obstaculo -Classe que representa obstáculos na fase e que podem ser destruidos por pássaros. Herda de ator. Seu caracter de -representação é a letra "O" quando Ativo. +Classe que representa obstáculos na fase e que podem ser destruídos por pássaros. Herda de ator. Seu caracter de +representação é a letra "O", quando ATIVO. ### Status @@ -91,9 +91,14 @@ Assim ele vai "sumir" da tela. ## Classe Porco -Classe que representa porcos na fase e que podem ser destruidos por pássaros. Herda de ator. Seu caracter de +Classe que representa porcos na fase e que podem ser destruídos por pássaros. Herda de ator. Seu caracter de representação é a o caracter "@". +### Status + +Um obstáculo ao ter seu status alterado para DESTRUIDO deve ter seu caracter de apresentação alterado para "+" (sinal de mais). +Assim sua imagem é alterada para a de porco morto. + ## Passaro Classe base de todos os passáros. Cada tipo possui uma velocidade de lançamento (v). No lançamento o jogador escolhe o @@ -102,8 +107,9 @@ gravidade (GRAVIDADE) constante e igual a 10 m/s^2. ### Método lancar -O método lançar recebe o ângulo, em graus, que será feito o lançamento. Cada pássaro deve armazenar esse valor e o tempo -de lançamento para cálculo de sua posíção. Lembrar que o tempo das fórmulas é delta_t = T_final - T_inicial +O método lançar recebe o ângulo, em graus, que será feito o lançamento. Ele deve ser convertido para radianos. +Cada pássaro deve armazenar esse valor e o tempo +de lançamento para cálculo de sua posíção. Lembrar que o tempo das fórmulas é delta_t = T_final - T_inicial. ### Método de colidir_com_chao @@ -113,13 +119,13 @@ Todo pássaro que colidir com o chão (y<=0) deve ser destruído. ### Método foi_lançado Esse método deve retornar verdadadeiro se o pássaro foi lançado (tempo de lançamento é None). -Caso contrário deve retornar falso +Caso contrário deve retornar falso. ### Lançamento Se o pássaro ainda não foi lançado, o pássaro deve permanecer na posição inicial. -Caso tenha sido lançado e seu status esteja ativo, sua posição deve ser calculada de acordo com o lançamento oblíquo. +Caso tenha sido lançado e seu status esteja ATIVO, sua posição deve ser calculada de acordo com o lançamento oblíquo. Nesse caso, delta_t vai ser igual ao tempo do jogo menos o tempo do lançamento. Caso contrário, ele deve retornar a posição onde colidiu. @@ -143,39 +149,32 @@ Tipo de Pássaro que representa o pássaro amarelo. Possui velocidade de lançam ## Classe Fase -Classe responsável por organizar atores e transformarem os dados em pontos a serem representados na tela. +Classe responsável por organizar atores e transformar os dados em pontos a serem representados na tela. ### Método adicionar_obstaculo -Método que adiciona um ou mais obstáculos na fase +Método que adiciona um ou mais obstáculos na fase. ### Método adicionar_porco -Método que adiciona um ou mais porcos na fase +Método que adiciona um ou mais porcos na fase. ### Método adicionar_passaro -Método que adiciona um ou mais pássaros na fase - -### Método acabou - -Método que recebe o tempo do jogo e retorna verdadeiro (True) se o jogo acabou e (False) caso contrário. -O jogo pode acabar por duas razôes: +Método que adiciona um ou mais pássaros na fase. -1. Todos porcos foram destruídos -2. Não há mais pássaros a serem lançados ### Método status -Recebe o tempo como parâmetro e retorna mensagem com status do jogo. +Recebe o tempo como parâmetro e retorna status do jogo. -1. Se o jogo está em andamento, retorna mensagem "Jogo em andamento." -2. Se o jogo acabou e não existem porcos ativos, retorna a mensagem "Jogo em encerrado. Você ganhou!" -3. Se o jogo acabou e existem porcos ativos, retorna a mensagem "Jogo em encerrado. Você perdeu!" +1. Se o jogo está em andamento, retorna status "EM_ANDAMENTO"; +2. Se o jogo acabou e não existem porcos ativos, retorna STATUS "VITORIA"; +3. Se o jogo acabou e existem porcos ativos, retorna status "DERROTA". ### Método lancar -Recebe o ângulo e o tempo do lançamento. Deve delegar o lançamento ao primeiro pássaro ativo da lista de pássaros que +Recebe o ângulo e o tempo do lançamento. Deve delegar o lançamento ao primeiro pássaro ATIVO da lista de pássaros que ainda não foi lançado. ### Método calcular_pontos @@ -185,7 +184,7 @@ Método que executa a lógica do jogo a cada passo (tempo), retornando pontos a Ele deve: 1. Calcular a posição de cada pássaro, verificando se ele colidiu com algum obstáculo, porco ou chão. -2. Retornar instâncias da classe Ponto, informando x,y e caracter respectivo a cada ator. +2. Retornar instâncias da classe Ponto, informando x, y e caracter respectivo a cada ator. ### Divirta-se!!!! diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 939cba661..087bd1864 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -7,6 +7,7 @@ class AtorTestes(TestCase): def teste_valores_padrao(self): + 'Testa valores iniciais padrão de um Ator' ator = Ator() self.assertEqual(0, ator.x) self.assertEqual(0, ator.y) @@ -14,6 +15,7 @@ def teste_valores_padrao(self): self.assertEqual('A', ator.caracter()) def teste_valores_passados_por_parametro(self): + 'Testa se valores passados no inicializador são armazenados no objeto' ator = Ator(1, 2) self.assertEqual(1, ator.x) self.assertEqual(2, ator.y) @@ -34,6 +36,12 @@ def teste_ator_posicao(self): def teste_colisao_entre_atores_ativos(self): + """ + Teste de colisão entre dois atores + Incialmente atores possuem status ATIVO. Ao se chocarem, ele muda para Destruído + A função assert_colisao_atores_ativos testa justamente se dois atore ativos se chocam quando estão em posições + vizinhas. + """ ator = Ator(2, 2) # Ator recém criado deve ter status ativo ator2 = Ator(2, 2) self.assert_colisao_atores_ativos(ator, ator2) @@ -51,6 +59,7 @@ def teste_colisao_entre_atores_ativos_com_intervalo(self): self.assert_colisao_atores_ativos(Ator(2, 2), Ator(2, 4), 2) def teste_nao_colisao_entre_atores_ativos(self): + 'Teste de que não há colisão entre atores distantes' self.assert_nao_colisao(Ator(2, 2), Ator(2, 4)) self.assert_nao_colisao(Ator(2, 2), Ator(3, 4)) self.assert_nao_colisao(Ator(2, 2), Ator(4, 2)) @@ -61,8 +70,9 @@ def teste_nao_colisao_entre_atores_ativos(self): self.assert_nao_colisao(Ator(2, 2), Ator(0, 4)) def teste_colisao_somente_um_ator_destruido(self): + 'Teste de que um ator destruído não pode colidir com nenhum outro, mesmo que estejam próximos' ator = Ator(2, 2) - ator.colidir(ator, 0) # colidingo ator com ele mesmo para alterar seu status para destruido + ator.colidir(ator, 0) # colidindo ator com ele mesmo para alterar seu status para destruido ator2 = Ator(2, 2) self.assert_nao_colisao(ator, ator2) self.assert_nao_colisao(Ator(2, 3), ator) @@ -84,6 +94,7 @@ def teste_colisao_somente_um_ator_destruido(self): self.assert_nao_colisao(Ator(1, 3), ator) def test_caracter(self): + 'Teste de caracter para status ATIVO e DESTRUIDO' ator = Ator() self.assertEqual('A', ator.caracter()) outro_ator_na_mesma_posicao = Ator() @@ -92,7 +103,11 @@ def test_caracter(self): def assert_colisao_atores_ativos(self, ator, ator2, intervalo=1): - 'Se certifica que há colisão entre atores ativos' + """ + Se certifica que há colisão entre atores ativos + Atenção: Esse não é método de teste porque nao se inicia com prefixo "text". + Ele serve apenas para encapsular toda lógica de teste de colisão entre dois atores ativos + """ # Conferindo status dos dois atores antes da colisão self.assertEqual(ator.status, ATIVO, 'Status deveria ser ativo antes da colisão') self.assertEqual(ator2.status, ATIVO, 'Status deveria ser ativo antes da colisão') @@ -102,7 +117,12 @@ def assert_colisao_atores_ativos(self, ator, ator2, intervalo=1): self.assertEqual(ator.status, DESTRUIDO, 'Status deveria ser destruido depois da colisão') def assert_nao_colisao(self, ator, ator2): - 'Se certifica que não colisão entre dois atores' + """ + 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". + 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 + """ # Armazenando status antes da colisão status_inicial_ator = ator.status status_inicial_ator_2 = ator2.status @@ -133,7 +153,23 @@ def teste_status(self): class PassaroBaseTests(TestCase): + """ + Classe base para teste de passaros. + Essa classe não contèm nenhum teste, serve apenas para encapsular a lógica de asserção de posição de passaros + vermelhos e também dos amarelos. + + """ + def assert_passaro_posicao(self, x_esperado, y_esperado, status_esperado, passaro, tempo): + """ + Mètodo que se testa posição do pássaro. + Atenção: Esse não é método de teste porque nao se inicia com prefixo "text". + :param x_esperado: posição x esperada do passaro + :param y_esperado: posição y esperada do passaro + :param status_esperado: status esperado do passaro + :param passaro: passaro alvo do teste + :param tempo: tempo do jogo + """ x_calculado, y_calculado = passaro.calcular_posicao(tempo) self.assertEqual(x_esperado, round(x_calculado), 'valor real de x = %s' % x_calculado) self.assertEqual(y_esperado, round(y_calculado), 'valor real de y = %s' % y_calculado) @@ -141,6 +177,10 @@ def assert_passaro_posicao(self, x_esperado, y_esperado, status_esperado, passar class PassaroVermelhoTests(PassaroBaseTests): + """ + Classe de teste e Passaro Vermelho + """ + def teste_status(self): passaro_amarelo = PassaroVermelho(1, 1) self.assertEqual('V', passaro_amarelo.caracter()) @@ -154,6 +194,11 @@ def teste_velocidade_escalar(self): def teste_foi_lancado(self): + """ + Teste de lançamento. Enquanto o método lançar do passaro não for chamado, o méotod foi_lancado deve retornar + Falso + :return: + """ passaro_vermelho = PassaroVermelho(1, 1) self.assertFalse(passaro_vermelho.foi_lancado(), 'Se o método lançar ainda não foi executado, deve retornar falso') @@ -162,6 +207,10 @@ def teste_foi_lancado(self): 'Se o método lançar foi executado, deve retornar verdadeiro') def teste_colisao_com_chao(self): + """ + Testando que o passáro colido quando sua posição y é menor ou igual a 0 + :return: + """ passaro = PassaroVermelho(0, 0) passaro.colidir_com_chao() self.assertEqual(DESTRUIDO, passaro.status, 'Deve colidir com chão sempre que y<=0') @@ -180,6 +229,10 @@ def teste_colisao_com_chao(self): class PassaroAmareloTests(PassaroBaseTests): + """ + Classe de Tests para passaros amarelos + """ + def teste_status(self): passaro_amarelo = PassaroAmarelo(1, 1) self.assertEqual('A', passaro_amarelo.caracter()) @@ -191,54 +244,56 @@ 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 + :return: + """ passaro_amarelo = PassaroAmarelo(1, 1) passaro_amarelo.lancar(90, 2) # passaro lancado a 90 graus no tempo 2 segundos - # função auxiliar que mantém x fixo com valor 1, status Ativo, variando apenas o tempo e a posição y - def assert_vertical(y, tempo): - self.assert_passaro_posicao(1, y, ATIVO, passaro_amarelo, tempo) + # subindo - assert_vertical(1, 2.0) - assert_vertical(1, 2.01) - assert_vertical(2, 2.02) - assert_vertical(2, 2.03) - assert_vertical(2, 2.04) - assert_vertical(2, 2.05) + self.assert_posicao_vertical(1, 2.0, passaro_amarelo) + self.assert_posicao_vertical(1, 2.01, passaro_amarelo) + self.assert_posicao_vertical(2, 2.02, passaro_amarelo) + self.assert_posicao_vertical(2, 2.03, passaro_amarelo) + self.assert_posicao_vertical(2, 2.04, passaro_amarelo) + self.assert_posicao_vertical(2, 2.05, passaro_amarelo) # descendo - assert_vertical(46, 5.26) - assert_vertical(46, 5.27) - assert_vertical(46, 5.279999999999999) - assert_vertical(46, 5.29) - assert_vertical(46, 5.3) - assert_vertical(46, 5.3100000000000005) - assert_vertical(45, 5.32) - assert_vertical(45, 5.33) - assert_vertical(45, 5.34) - assert_vertical(45, 5.35) - assert_vertical(45, 5.359999999999999) - assert_vertical(45, 5.37) - assert_vertical(45, 5.38) - assert_vertical(45, 5.390000000000001) - assert_vertical(45, 5.4) - assert_vertical(45, 5.41) - assert_vertical(45, 5.42) - assert_vertical(45, 5.43) - assert_vertical(45, 5.4399999999999995) - assert_vertical(45, 5.45) - assert_vertical(45, 5.46) - assert_vertical(45, 5.470000000000001) - assert_vertical(45, 5.48) + self.assert_posicao_vertical(46, 5.26, passaro_amarelo) + self.assert_posicao_vertical(46, 5.27, passaro_amarelo) + self.assert_posicao_vertical(46, 5.279999999999999, passaro_amarelo) + self.assert_posicao_vertical(46, 5.29, passaro_amarelo) + self.assert_posicao_vertical(46, 5.3, passaro_amarelo) + self.assert_posicao_vertical(46, 5.3100000000000005, passaro_amarelo) + self.assert_posicao_vertical(45, 5.32, passaro_amarelo) + self.assert_posicao_vertical(45, 5.33, passaro_amarelo) + self.assert_posicao_vertical(45, 5.34, passaro_amarelo) + self.assert_posicao_vertical(45, 5.35, passaro_amarelo) + self.assert_posicao_vertical(45, 5.359999999999999, passaro_amarelo) + self.assert_posicao_vertical(45, 5.37, passaro_amarelo) + self.assert_posicao_vertical(45, 5.38, passaro_amarelo) + self.assert_posicao_vertical(45, 5.390000000000001, passaro_amarelo) + self.assert_posicao_vertical(45, 5.4, passaro_amarelo) + self.assert_posicao_vertical(45, 5.41, passaro_amarelo) + self.assert_posicao_vertical(45, 5.42, passaro_amarelo) + self.assert_posicao_vertical(45, 5.43, passaro_amarelo) + self.assert_posicao_vertical(45, 5.4399999999999995, passaro_amarelo) + self.assert_posicao_vertical(45, 5.45, passaro_amarelo) + self.assert_posicao_vertical(45, 5.46, passaro_amarelo) + self.assert_posicao_vertical(45, 5.470000000000001, passaro_amarelo) + self.assert_posicao_vertical(45, 5.48, passaro_amarelo) # preparando para impacto no chão - assert_vertical(1, 8.0) - assert_vertical(1, 8.01) + self.assert_posicao_vertical(1, 8.0, passaro_amarelo) + self.assert_posicao_vertical(1, 8.01, passaro_amarelo) # colisão - assert_vertical(0, 8.04) + self.assert_posicao_vertical(0, 8.04, passaro_amarelo) passaro_amarelo.colidir_com_chao() self.assertEqual(DESTRUIDO, passaro_amarelo.status) @@ -681,3 +736,10 @@ def test_lancamento_45_graus(self): # t = 2 + (delta_t / 100) # x, y = passaro_amarelo.calcular_posicao(t) # print(' self.assert_passaro_posicao(%s, %s, ATIVO, passaro_amarelo, %s)' % (x, y, t)) + + def assert_posicao_vertical(self, y, tempo, passaro): + """ + Método auxiliar que mantém x fixo com valor 1, status Ativo, variando apenas o tempo e a posição y + Atenção, esse não é um teste porque não começa com prefixo "test" + """ + self.assert_passaro_posicao(1, y, ATIVO, passaro, tempo) From 3ebf2f66beed6b535a4927e1df2e7c153255416c Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 21:22:22 -0200 Subject: [PATCH 19/35] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20do=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 22bbfbcb4..8320dc675 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,23 @@ A versão utilizada para desenvolvimento foi Python 3.4 Um vídeo fala mais que 1000 palavras: [Python Birds](https://www.youtube.com/watch?v=b899h0lNd7U&list=PLA05yVJtRWYTm0sIa6n56UpCjCsR5ekla) +# Contribuidores + +[Giovane Liberato](https://github.com/giovaneliberato) +[Michel Amaral](https://github.com/michelamaral) +[Renzo Nuccitelli](https://github.com/renzon) + # Abordagem Instalar [Python 3](https://www.python.org/download/). Baixar o zip do projeto (botão Download Zip) -Os testes se encontram dentro do pacote "testes" e servem para definir a dinâmica das classes. Para rodar todos testes, execute +Os testes se encontram dentro do pacote "testes" e servem para definir a dinâmica das classes. Para rodar todos testes, execute: python executor_de_testes.py -Explicação detalhada sobre classes e métodos se encontram nos scripts atores.py e fase.py +Explicação detalhada sobre classes e métodos se encontram nos scripts atores.py e fase.py. ## Ordem de desenvolvimento @@ -141,11 +147,13 @@ Fórmula Y=Y0+v*sen(teta)delta_t-(G*delta_t^2)/2. ## Classe Passaro Vermelho -Tipo de Pássaro que representa o pássaro vermelho. Possui velocidade de lançamento igual a 20 m/s. Seu caracter é "D". +Tipo de Pássaro que representa o pássaro vermelho. Possui velocidade de lançamento igual a 20 m/s. +Seu caracter quanto ATIVO é "V". Quando DESTRUIDO é "v". ## Classe Passaro Amarelo -Tipo de Pássaro que representa o pássaro amarelo. Possui velocidade de lançamento igual a 30 m/s. Seu caracter é ">". +Tipo de Pássaro que representa o pássaro amarelo. Possui velocidade de lançamento igual a 30 m/s. +Seu caracter quanto DESTRUIDO é "a". ## Classe Fase From 7a20adcebcdb1d86cdeb99bfebca784331096393 Mon Sep 17 00:00:00 2001 From: renzon Date: Wed, 12 Nov 2014 21:25:19 -0200 Subject: [PATCH 20/35] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20do=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8320dc675..8da421483 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Um vídeo fala mais que 1000 palavras: [Python Birds](https://www.youtube.com/wa # Contribuidores -[Giovane Liberato](https://github.com/giovaneliberato) -[Michel Amaral](https://github.com/michelamaral) -[Renzo Nuccitelli](https://github.com/renzon) +* [Giovane Liberato](https://github.com/giovaneliberato) +* [Michel Amaral](https://github.com/michelamaral) +* [Renzo Nuccitelli](https://github.com/renzon) # Abordagem From 5e426f713c8120294d17d2e8cbc29861b7a28fda Mon Sep 17 00:00:00 2001 From: Renzo Nuccitelli Date: Thu, 8 Jan 2015 16:38:54 -0200 Subject: [PATCH 21/35] =?UTF-8?q?Acrescentando=20links=20para=20o=20projet?= =?UTF-8?q?o=20do=20Estev=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2fc310741..60f9987fd 100644 --- a/README.md +++ b/README.md @@ -196,4 +196,14 @@ Ele deve: ### Divirta-se!!!! -Powered by [Python Pro](http://adm.python.pro.br) \ No newline at end of file +Powered by [Python Pro](http://adm.python.pro.br) + +# Observação Importante + +Esse projeto usa somente o interpretador padrão do Python. Para fazer jogos com mais interatividade, existe a biblioteca Pygame. Ela não foi utilizada por motivos de simplicidade, para evitar que o aluno iniciante tenha dificuldades na hora de instalar o projeto. + +Contudo o Estevão Fonseca fez um versão com essa biblioteca, confira o projeto: + + + +Ele também colocou esse [vídeo no Youtube](https://www.youtube.com/watch?v=B7G5JtCFepE). From 6e38449892695b3d39d20e0fbcdbc49d5445e0b6 Mon Sep 17 00:00:00 2001 From: renzon Date: Sat, 28 Mar 2015 17:01:19 -0300 Subject: [PATCH 22/35] Consertando testes de atores para rodar via linha de comando --- testes/atores_testes.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 087bd1864..26444643a 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -1,6 +1,14 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +from os import path +import sys + +project_dir = path.dirname(__file__) +project_dir = path.join('..') +sys.path.append(project_dir) + +import unittest from unittest.case import TestCase from atores import Ator, DESTRUIDO, ATIVO, Obstaculo, Porco, PassaroAmarelo, PassaroVermelho @@ -743,3 +751,8 @@ def assert_posicao_vertical(self, y, tempo, passaro): Atenção, esse não é um teste porque não começa com prefixo "test" """ self.assert_passaro_posicao(1, y, ATIVO, passaro, tempo) + + +if __name__=='__main__': + teste= AtorTestes() + teste.teste_colisao_entre_atores_ativos() \ No newline at end of file From 0e6a7e4d6c717fc23def0473f3c6bbb85138e53b Mon Sep 17 00:00:00 2001 From: renzon Date: Fri, 24 Apr 2015 17:21:05 -0300 Subject: [PATCH 23/35] close #12 --- placa_grafica_tkinter.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 From df5687f236ea1db9b89dc3b3866714c7a6a886a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Perc=C3=BA?= Date: Sat, 16 May 2015 12:44:00 -0300 Subject: [PATCH 24/35] =?UTF-8?q?Melhorando=20a=20descri=C3=A7=C3=A3o=20do?= =?UTF-8?q?=20teste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Arrumando digitação - Mudando status para maiusculo --- testes/atores_testes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 26444643a..07102d640 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -46,7 +46,7 @@ def teste_ator_posicao(self): def teste_colisao_entre_atores_ativos(self): """ Teste de colisão entre dois atores - Incialmente atores possuem status ATIVO. Ao se chocarem, ele muda para Destruído + Inicialmente atores possuem status ATIVO. Ao se chocarem, ele muda para DESTRUIDO A função assert_colisao_atores_ativos testa justamente se dois atore ativos se chocam quando estão em posições vizinhas. """ @@ -755,4 +755,4 @@ def assert_posicao_vertical(self, y, tempo, passaro): if __name__=='__main__': teste= AtorTestes() - teste.teste_colisao_entre_atores_ativos() \ No newline at end of file + teste.teste_colisao_entre_atores_ativos() From 63a4981193c4ea0af606fc0967da06da6c22d918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Perc=C3=BA?= Date: Sat, 16 May 2015 13:22:01 -0300 Subject: [PATCH 25/35] Melhoria no nome do teste MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tornando o nome mais descritivo do que o teste realmente está fazendo. --- testes/atores_testes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 26444643a..5f7edd961 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -66,7 +66,7 @@ def teste_colisao_entre_atores_ativos_com_intervalo(self): # Com intervalo 2, diferente do padrão 1, essa colisão deveria acontecer self.assert_colisao_atores_ativos(Ator(2, 2), Ator(2, 4), 2) - def teste_nao_colisao_entre_atores_ativos(self): + def teste_nao_colisao_entre_atores_distantes(self): 'Teste de que não há colisão entre atores distantes' self.assert_nao_colisao(Ator(2, 2), Ator(2, 4)) self.assert_nao_colisao(Ator(2, 2), Ator(3, 4)) @@ -755,4 +755,4 @@ def assert_posicao_vertical(self, y, tempo, passaro): if __name__=='__main__': teste= AtorTestes() - teste.teste_colisao_entre_atores_ativos() \ No newline at end of file + teste.teste_colisao_entre_atores_ativos() From bbb2a2916f2f6be908e6e4f2af0c29a5e984eca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Perc=C3=BA?= Date: Sat, 16 May 2015 13:31:00 -0300 Subject: [PATCH 26/35] Mais melhorias na doc --- testes/atores_testes.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index 26444643a..b2ed84a01 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -143,6 +143,9 @@ def assert_nao_colisao(self, ator, ator2): class ObstaculoTestes(TestCase): + """ + Esperado '0' como caracter de obstáculo ativo e ' ' como caracter de obstáculo destruído + """ def teste_status(self): obstaculo = Obstaculo() self.assertEqual('O', obstaculo.caracter()) @@ -152,6 +155,9 @@ def teste_status(self): class PorcoTestes(TestCase): + """ + Esperado '@' como caracter de porco ativo e '+' como caracter de porco destruido + """ def teste_status(self): porco = Porco() self.assertEqual('@', porco.caracter()) @@ -170,8 +176,8 @@ class PassaroBaseTests(TestCase): def assert_passaro_posicao(self, x_esperado, y_esperado, status_esperado, passaro, tempo): """ - Mètodo que se testa posição do pássaro. - Atenção: Esse não é método de teste porque nao se inicia com prefixo "text". + Método que se testa posição do pássaro. + Atenção: Esse não é um método de teste porque não se inicia com prefixo "test". :param x_esperado: posição x esperada do passaro :param y_esperado: posição y esperada do passaro :param status_esperado: status esperado do passaro @@ -203,7 +209,7 @@ def teste_velocidade_escalar(self): def teste_foi_lancado(self): """ - Teste de lançamento. Enquanto o método lançar do passaro não for chamado, o méotod foi_lancado deve retornar + Teste de lançamento. Enquanto o método lançar do passaro não for chamado, o méotodo foi_lancado deve retornar Falso :return: """ @@ -216,7 +222,7 @@ def teste_foi_lancado(self): def teste_colisao_com_chao(self): """ - Testando que o passáro colido quando sua posição y é menor ou igual a 0 + Testando que o passáro colide quando sua posição y é menor ou igual a 0 :return: """ passaro = PassaroVermelho(0, 0) @@ -755,4 +761,4 @@ def assert_posicao_vertical(self, y, tempo, passaro): if __name__=='__main__': teste= AtorTestes() - teste.teste_colisao_entre_atores_ativos() \ No newline at end of file + teste.teste_colisao_entre_atores_ativos() From 30b1b6abfbcafee518625c165d164c3050886948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Perc=C3=BA?= Date: Sun, 17 May 2015 13:26:11 -0300 Subject: [PATCH 27/35] =?UTF-8?q?Definindo=20intervalo=20para=20=C3=A2ngul?= =?UTF-8?q?o=20[0,=20360]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- placa_grafica_tkinter.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/placa_grafica_tkinter.py b/placa_grafica_tkinter.py index ea020ccbb..318542e65 100644 --- a/placa_grafica_tkinter.py +++ b/placa_grafica_tkinter.py @@ -86,8 +86,12 @@ def _ouvir_comandos_lancamento(evento): nonlocal angulo if evento.keysym == 'Up': angulo += 1 + if angulo > 360: + angulo = 1 elif evento.keysym == 'Down': angulo -= 1 + if angulo < 0: + angulo = 359 elif evento.keysym == 'Return' or evento.keysym == 'space': fase.lancar(angulo, tempo) From dbc979201c92b85cb2a6c130797081b834df91e9 Mon Sep 17 00:00:00 2001 From: Renzo Nuccitelli Date: Mon, 25 May 2015 11:20:59 -0300 Subject: [PATCH 28/35] Update README.md Adicionando Guido como contribuidor --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 60f9987fd..0899c0a28 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Um vídeo fala mais que 1000 palavras: [Python Birds](https://www.youtube.com/wa # Contribuidores * [Giovane Liberato](https://github.com/giovaneliberato) +* [Guido Luz](https://github.com/GuidoBR) * [Michel Amaral](https://github.com/michelamaral) * [Renzo Nuccitelli](https://github.com/renzon) From 6bf264bf936a8aa33b3ddff5f887aa7e68f37e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Perc=C3=BA?= Date: Wed, 27 May 2015 21:05:35 -0300 Subject: [PATCH 29/35] =?UTF-8?q?Mudando=20nome=20da=20vari=C3=A1vel=20de?= =?UTF-8?q?=20acordo=20com=20nome=20da=20classe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- testes/atores_testes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testes/atores_testes.py b/testes/atores_testes.py index fedfe46a3..f4254f29e 100644 --- a/testes/atores_testes.py +++ b/testes/atores_testes.py @@ -196,11 +196,11 @@ class PassaroVermelhoTests(PassaroBaseTests): """ def teste_status(self): - passaro_amarelo = PassaroVermelho(1, 1) - self.assertEqual('V', passaro_amarelo.caracter()) + passaro_vermelho = PassaroVermelho(1, 1) + self.assertEqual('V', passaro_vermelho.caracter()) outro_ator_na_mesma_posicao = Ator() - passaro_amarelo.colidir(outro_ator_na_mesma_posicao) - self.assertEqual('v', passaro_amarelo.caracter()) + passaro_vermelho.colidir(outro_ator_na_mesma_posicao) + self.assertEqual('v', passaro_vermelho.caracter()) def teste_velocidade_escalar(self): From 25e33ab581b1ee9d547a95ffe1849d1a22fd03bf Mon Sep 17 00:00:00 2001 From: renzon Date: Fri, 13 May 2016 18:01:18 -0300 Subject: [PATCH 30/35] fase funcionando --- fase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fase.py b/fase.py index ea8f9af24..3385175c6 100644 --- a/fase.py +++ b/fase.py @@ -98,7 +98,7 @@ def calcular_pontos(self, tempo): :param tempo: tempo para o qual devem ser calculados os pontos :return: objeto do tipo Ponto """ - pontos=[] + pontos=[self._transformar_em_ponto(a) for a in self._passaros+self._obstaculos+self._porcos] return pontos From a12773fdf5fd762295f073f918b6c8f4be0c8c77 Mon Sep 17 00:00:00 2001 From: renzon Date: Tue, 6 Dec 2016 21:54:00 -0200 Subject: [PATCH 31/35] =?UTF-8?q?Testes=20de=20fase=20divididos=20em=20int?= =?UTF-8?q?egracao=20e=20unit=C3=A1rios=20com=20Objetos=20Fake=20emulando?= =?UTF-8?q?=20Mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit d5f5528) --- testes/fase_testes.py | 232 ++++++++++++++++----------------- testes/integracao.py | 188 ++++++++++++++++++++++++++ testes/testes_placa_grafica.py | 2 - 3 files changed, 297 insertions(+), 125 deletions(-) create mode 100644 testes/integracao.py 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 From c1aa928b8ef2041e0afb3f745aaee6ae79cfa475 Mon Sep 17 00:00:00 2001 From: renzon Date: Tue, 6 Dec 2016 22:08:06 -0200 Subject: [PATCH 32/35] =?UTF-8?q?Adicionando=20Exce=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atores.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atores.py b/atores.py index b4519a9db..cfc2ef5ea 100644 --- a/atores.py +++ b/atores.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + import math DESTRUIDO = 'Destruido' @@ -63,6 +64,10 @@ class Porco(Ator): pass +class DuploLancamentoExcecao(Exception): + pass + + class Passaro(Ator): velocidade_escalar = 10 From 4e4175093ddf0f91261f6fad66b3dcdac2c0b226 Mon Sep 17 00:00:00 2001 From: Renzo Nuccitelli Date: Mon, 20 Mar 2017 23:56:18 -0300 Subject: [PATCH 33/35] =?UTF-8?q?Escapando=20*=20nas=20f=C3=B3rmulas=20de?= =?UTF-8?q?=20lan=C3=A7amento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0899c0a28..78b9e1abb 100644 --- a/README.md +++ b/README.md @@ -139,11 +139,11 @@ Caso contrário, ele deve retornar a posição onde colidiu. #### Método posicao_horizontal -Fórmula X=X0+v*cos(teta)*delta_t. +Fórmula X=X0+v\*cos(teta)\*delta_t. #### Método posicao_vertical -Fórmula Y=Y0+v*sen(teta)delta_t-(G*delta_t^2)/2. +Fórmula Y=Y0+v\*sen(teta)delta_t-(G\*delta_t^2)/2. ## Classe Passaro Vermelho From 61582035798a297a39bfe091b71c4db032c08d32 Mon Sep 17 00:00:00 2001 From: Jonatas oliveira lima da silva Date: Wed, 22 Apr 2020 14:36:36 -0300 Subject: [PATCH 34/35] Remover acento til no nome da funcao Funcao "def teste_intervalo_de_colisao_nao_padrao(self):" na linha 200 havia um til --- testes/fase_testes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testes/fase_testes.py b/testes/fase_testes.py index 8158a43f5..dc0dcfbd3 100644 --- a/testes/fase_testes.py +++ b/testes/fase_testes.py @@ -179,7 +179,7 @@ def teste_lancar_passaro_sem_erro_quando_nao_existe_passaro(self): self.assertTrue(passaros[0].foi_lancado()) self.assertTrue(passaros[1].foi_lancado()) - def teste_intervalo_de_colisao_padrão(self): + def teste_intervalo_de_colisao_padrao(self): ''' Método que testa se o intervalo de colisão da Fase é repassado aos atores. Padrão de intervalo é 1 From 47f62f3b00da56f47fa1fdf54165c29fcc7b3bcd Mon Sep 17 00:00:00 2001 From: engnogueira Date: Wed, 14 Oct 2020 21:05:49 +0000 Subject: [PATCH 35/35] Fully automate dev setup with Gitpod This commit implements a fully-automated development setup using Gitpod.io, an online IDE for GitHub and GitLab that enables Dev-Environments-As-Code. This makes it easy for anyone to get a ready-to-code workspace for any branch, issue or pull request almost instantly with a single click. --- .gitpod.Dockerfile | 7 +++++++ .gitpod.yml | 6 ++++++ README.md | 2 ++ 3 files changed, 15 insertions(+) create mode 100644 .gitpod.Dockerfile create mode 100644 .gitpod.yml diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 000000000..f8e49f267 --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,7 @@ +FROM gitpod/workspace-full + +# Install custom tools, runtimes, etc. +# For example "bastet", a command-line tetris clone: +# RUN brew install bastet +# +# More information: https://www.gitpod.io/docs/config-docker/ diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 000000000..475c7d9ad --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +image: + file: .gitpod.Dockerfile + +tasks: + - init: 'echo "TODO: Replace with init/build command"' + command: 'echo "TODO: Replace with command to start project"' diff --git a/README.md b/README.md index 78b9e1abb..cbb6dfb5e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/pythonprobr/pythonbirds) + Python Birds ===========