diff --git a/atores.py b/atores.py index cfc2ef5ea..86deb1d72 100644 --- a/atores.py +++ b/atores.py @@ -9,7 +9,7 @@ GRAVIDADE = 10 # m/s^2 -class Ator(): +class Ator: """ Classe que representa um ator. Ele representa um ponto cartesiano na tela. """ @@ -38,7 +38,7 @@ def calcular_posicao(self, tempo): :param tempo: o tempo do jogo :return: posição x, y do ator """ - return 1, 1 + return self.x, self.y def colidir(self, outro_ator, intervalo=1): """ @@ -52,16 +52,20 @@ def colidir(self, outro_ator, intervalo=1): :param intervalo: Intervalo a ser considerado :return: """ - pass - + if self.status == ATIVO and outro_ator.status == ATIVO: + delta_x = abs(self.x - outro_ator.x) + delta_y = abs(self.y - outro_ator.y) + if delta_x <= intervalo and delta_y <= intervalo: + self.status = outro_ator.status = DESTRUIDO class Obstaculo(Ator): - pass + _caracter_ativo = 'O' class Porco(Ator): - pass + _caracter_ativo = '@' + _caracter_destruido = '+' class DuploLancamentoExcecao(Exception): @@ -89,11 +93,11 @@ def __init__(self, x=0, y=0): def foi_lancado(self): """ - Método que retorna verdaeira se o pássaro já foi lançado e falso caso contrário + Método que retorna verdadeiro se o pássaro já foi lançado e falso caso contrário :return: booleano """ - return True + return not self._tempo_de_lancamento is None def colidir_com_chao(self): """ @@ -101,7 +105,8 @@ def colidir_com_chao(self): o status dos Passaro deve ser alterado para destruido, bem como o seu caracter """ - pass + if self.y <= 0: + self.status = DESTRUIDO def calcular_posicao(self, tempo): """ @@ -117,8 +122,11 @@ def calcular_posicao(self, tempo): :param tempo: tempo de jogo a ser calculada a posição :return: posição x, y """ - return 1, 1 - + if self._esta_voando(): + delta_t = tempo - self._tempo_de_lancamento + self._calcular_posicao_vertical(delta_t) + self._calcular_posicao_horizontal(delta_t) + return super().calcular_posicao(tempo) def lancar(self, angulo, tempo_de_lancamento): """ @@ -129,12 +137,33 @@ def lancar(self, angulo, tempo_de_lancamento): :param tempo_de_lancamento: :return: """ - pass + self._angulo_de_lancamento = math.radians(angulo) + self._tempo_de_lancamento = tempo_de_lancamento + + def _calcular_posicao_vertical(self, delta_t): + y_atual = self._y_inicial + angulo_radianos = self._angulo_de_lancamento + y_atual += self.velocidade_escalar * delta_t * math.sin(angulo_radianos) + y_atual -= (GRAVIDADE * (delta_t ** 2)) / 2 + self.y = y_atual + + def _calcular_posicao_horizontal(self, delta_t): + x_atual = self._x_inicial + angulo_radianos = self._angulo_de_lancamento + x_atual += self.velocidade_escalar * delta_t * math.cos(angulo_radianos) + self.x = x_atual + + def _esta_voando(self): + return self.foi_lancado() and self.status == ATIVO class PassaroAmarelo(Passaro): - pass + _caracter_ativo = 'A' + _caracter_destruido = 'a' + velocidade_escalar = 30 class PassaroVermelho(Passaro): - pass \ No newline at end of file + _caracter_ativo = 'V' + _caracter_destruido = 'v' + velocidade_escalar = 20 diff --git a/fase.py b/fase.py index 3385175c6..2066f96e5 100644 --- a/fase.py +++ b/fase.py @@ -2,7 +2,6 @@ from itertools import chain from atores import ATIVO - VITORIA = 'VITORIA' DERROTA = 'DERROTA' EM_ANDAMENTO = 'EM_ANDAMENTO' @@ -36,14 +35,13 @@ def __init__(self, intervalo_de_colisao=1): self._porcos = [] self._obstaculos = [] - def adicionar_obstaculo(self, *obstaculos): """ Adiciona obstáculos em uma fase :param obstaculos: """ - pass + self._obstaculos.extend(obstaculos) def adicionar_porco(self, *porcos): """ @@ -51,7 +49,7 @@ def adicionar_porco(self, *porcos): :param porcos: """ - pass + self._porcos.extend(porcos) def adicionar_passaro(self, *passaros): """ @@ -59,7 +57,7 @@ def adicionar_passaro(self, *passaros): :param passaros: """ - pass + self._passaros.extend(passaros) def status(self): """ @@ -73,7 +71,12 @@ def status(self): :return: """ - return EM_ANDAMENTO + if not self._possui_porco_ativo(): + return VITORIA + elif self._possui_passaros_ativos(): + return EM_ANDAMENTO + else: + return DERROTA def lancar(self, angulo, tempo): """ @@ -86,8 +89,10 @@ def lancar(self, angulo, tempo): :param angulo: ângulo de lançamento :param tempo: Tempo de lançamento """ - pass - + for passaro in self._passaros: + if not passaro.foi_lancado(): + passaro.lancar(angulo, tempo) + break def calcular_pontos(self, tempo): """ @@ -98,10 +103,26 @@ def calcular_pontos(self, tempo): :param tempo: tempo para o qual devem ser calculados os pontos :return: objeto do tipo Ponto """ - pontos=[self._transformar_em_ponto(a) for a in self._passaros+self._obstaculos+self._porcos] + for passaro in self._passaros: + passaro.calcular_posicao(tempo) + for alvo in self._obstaculos + self._porcos: + passaro.colidir(alvo, self.intervalo_de_colisao) + passaro.colidir_com_chao() + pontos = [self._transformar_em_ponto(a) for a in self._passaros + self._obstaculos + self._porcos] return pontos def _transformar_em_ponto(self, ator): return Ponto(ator.x, ator.y, ator.caracter()) + def _possui_porco_ativo(self): + for porco in self._porcos: + if porco.status == ATIVO: + return True + return False + + def _possui_passaros_ativos(self): + for passaro in self._passaros: + if passaro.status == ATIVO: + return True + return False diff --git a/oo/__init__.py b/oo/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/oo/carro.py b/oo/carro.py new file mode 100644 index 000000000..ea6dd1277 --- /dev/null +++ b/oo/carro.py @@ -0,0 +1,153 @@ +""" +Você deve criar uma classe carro que vai possuir +dois atributos compostos por outras duas classes: + +1) Motor +2) Direção + +O Motor terá a responsabilidade de controlar a velocidade. +Ele oferece os seguintes atributos: +1) Atributo de dado velocidade +2) Método acelerar, que deverá incremetar a velocidade de uma unidade +3) Método frear que deverá decrementar a velocidade em duas unidades + +A Direção terá a responsabilidade de controlar a direção. Ela oferece +os seguintes atributos: +1) Valor de diração com valores possíveis: Norte, Sul, Leste, Oeste. +2) Método girar_a_direita +2) Método girar_a_esquerda + + N +O L + S + + Exemplo: + >>> # Testando motor + >>> motor = Motor() + >>> motor.velocidade + 0 + >>> motor.acelerar() + >>> motor.velocidade + 1 + >>> motor.acelerar() + >>> motor.velocidade + 2 + >>> motor.acelerar() + >>> motor.velocidade + 3 + >>> motor.frear() + >>> motor.velocidade + 1 + >>> motor.frear() + >>> motor.velocidade + 0 + >>> # Testando Direcao + >>> direcao = Direcao() + >>> direcao.valor + 'Norte' + >>> direcao.girar_a_direita() + >>> direcao.valor + 'Leste' + >>> direcao.girar_a_direita() + >>> direcao.valor + 'Sul' + >>> direcao.girar_a_direita() + >>> direcao.valor + 'Oeste' + >>> direcao.girar_a_direita() + >>> direcao.valor + 'Norte' + >>> direcao.girar_a_esquerda() + >>> direcao.valor + 'Oeste' + >>> direcao.girar_a_esquerda() + >>> direcao.valor + 'Sul' + >>> direcao.girar_a_esquerda() + >>> direcao.valor + 'Leste' + >>> direcao.girar_a_esquerda() + >>> direcao.valor + 'Norte' + >>> carro = Carro(direcao, motor) + >>> carro.calcular_velocidade() + 0 + >>> carro.acelerar() + >>> carro.calcular_velocidade() + 1 + >>> carro.acelerar() + >>> carro.calcular_velocidade() + 2 + >>> carro.frear() + >>> carro.calcular_velocidade() + 0 + >>> carro.calcular_direcao() + 'Norte' + >>> carro.girar_a_direita() + >>> carro.calcular_direcao() + 'Leste' + >>> carro.girar_a_esquerda() + >>> carro.calcular_direcao() + 'Norte' + >>> carro.girar_a_esquerda() + >>> carro.calcular_direcao() + 'Oeste' +""" + +class Carro(): + def __init__(self, direcao, motor): + self.direcao = direcao + self.motor = motor + + def calcular_velocidade(self): + return self.motor.velocidade + + def acelerar(self): + return self.motor.acelerar() + + def frear(self): + self.motor.frear() + + def calcular_direcao(self): + return self.direcao.valor + + def girar_a_direita(self): + return self.direcao.girar_a_direita() + + def girar_a_esquerda(self): + return self.direcao.girar_a_esquerda() + +NORTE = 'Norte' +SUL = 'Sul' +LESTE = 'Leste' +OESTE = 'Oeste' + +class Direcao(object): + rotacao_a_direita_dct = { + NORTE: LESTE, LESTE: SUL, SUL: OESTE, OESTE: NORTE + } + + rotacao_a_esquerda_dct = { + NORTE: OESTE, LESTE: NORTE, SUL: LESTE, OESTE: SUL + } + + def __init__(self): + self.valor = NORTE + + def girar_a_direita(self): + self.valor = self.rotacao_a_direita_dct[self.valor] + + def girar_a_esquerda(self): + self.valor = self.rotacao_a_esquerda_dct[self.valor] + + +class Motor(): + def __init__(self): + self.velocidade = 0 + + def acelerar(self): + self.velocidade += 1 + + def frear(self): + self.velocidade -= 2 + self.velocidade = max(0, self.velocidade) \ No newline at end of file diff --git a/oo/pessoa.py b/oo/pessoa.py new file mode 100644 index 000000000..4c2f8abb1 --- /dev/null +++ b/oo/pessoa.py @@ -0,0 +1,81 @@ +class Pessoa: + # Atributo de classe (também chamado de Atributo "default"). Deve ser usado se o valor for igual para + # todas as instâncias da classe. + olhos = 2 + + # Atributos + def __init__(self, *filhos, nome=None, idade=None): + self.nome = nome + self.idade = idade + # Atributo complexo 'filhos' + self.filhos = list(filhos) + + # Método cumprimentar + def cumprimentar(self): + return f'Olá, meu nome é {self.nome}' + + # Método de classe, que independe do objeto e por isso não precisa receber nenhum atributo (não há 'self'). + # Para criar, utiliza-se um decorator chamado @staticmethod ou + @staticmethod + def metodo_estatico(): + return 42 + + @classmethod + def nome_e_atributos_de_classe(cls): + return f'{cls} - Olhos: {cls.olhos}' + +# Classe 'Homem', que herda os atributos e métodos da superclasse 'Pessoa' +class Homem(Pessoa): + def cumprimentar(self): + # Sobrescrita de método + cumprimentar_classe_pai = super().cumprimentar() + return f'{cumprimentar_classe_pai}. Aperto de mão' + +class Mutante(Pessoa): + # Sobrescrita de atributo + olhos = 3 + +if __name__ == '__main__': + # Objeto comum - instância da classe Pessoa + filho = Pessoa(nome='Giancarlo', idade=34) + + # Objeto com atributo complexo + mae = Pessoa(filho, nome='Bernadete', idade=18) + + print(filho.nome) + print(mae.nome) + + # Atributo dinâmico 'sobrenome', adicionado ao objeto 'filho' em tempo de execução + filho.sobrenome = "Silva" + print(filho.nome, filho.sobrenome) + + # Atributos de classe "olhos" + print(Pessoa.olhos) + print(filho.olhos) + print(mae.olhos) + + # Chamando os métodos estáticos + print(Pessoa.metodo_estatico()) + print(filho.metodo_estatico()) + + print(Pessoa.nome_e_atributos_de_classe()) + print(filho.nome_e_atributos_de_classe()) + + irmao = Homem(nome='Eduardo', idade=37) + + print(irmao.nome) + + print(isinstance(irmao, Pessoa)) + print(isinstance(filho, Pessoa)) + print(isinstance(filho, Homem)) + + print(filho.olhos) + + mutante = Mutante(nome='Wolverine', idade=80) + + print(mutante.olhos) + + print(filho.cumprimentar()) + print(mae.cumprimentar()) + + print(irmao.cumprimentar()) \ No newline at end of file diff --git a/oo/teste_carro.py b/oo/teste_carro.py new file mode 100644 index 000000000..e5ed9500c --- /dev/null +++ b/oo/teste_carro.py @@ -0,0 +1,27 @@ +from unittest import TestCase + +from oo.carro import Motor, Direcao, Carro + + +class CarroTestCase(TestCase): + def teste_direcao(self): + direcao = Direcao() + direcao.girar_a_esquerda() + self.assertEqual(None, direcao.girar_a_esquerda()) + + direcao.girar_a_direita() + self.assertEqual(None, direcao.girar_a_direita()) + + def teste_velocidade_inicial(self): + motor = Motor() + self.assertEqual(0, motor.velocidade) + + def teste_acelerar(self): + motor = Motor() + motor.acelerar() + self.assertEqual(1, motor.velocidade) + + def teste_frear(self): + motor = Motor() + motor.frear() + self.assertEqual(0, motor.velocidade) diff --git a/testes/atores_testes.py b/testes/testes_atores.py similarity index 99% rename from testes/atores_testes.py rename to testes/testes_atores.py index f4254f29e..e8ea91c12 100644 --- a/testes/atores_testes.py +++ b/testes/testes_atores.py @@ -8,7 +8,6 @@ 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 @@ -42,7 +41,6 @@ def teste_ator_posicao(self): self.assertEqual(0.3, x) self.assertEqual(0.5, y) - def teste_colisao_entre_atores_ativos(self): """ Teste de colisão entre dois atores @@ -109,11 +107,10 @@ def test_caracter(self): 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 - Atenção: Esse não é método de teste porque nao se inicia com prefixo "text". + Atenção: Esse não é método de teste porque nao se inicia com prefixo "test". 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 @@ -144,8 +141,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 + Esperado 'O' 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()) @@ -158,6 +156,7 @@ 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()) @@ -202,11 +201,9 @@ def teste_status(self): passaro_vermelho.colidir(outro_ator_na_mesma_posicao) self.assertEqual('v', passaro_vermelho.caracter()) - def teste_velocidade_escalar(self): self.assertEqual(20, PassaroVermelho.velocidade_escalar) - def teste_foi_lancado(self): """ Teste de lançamento. Enquanto o método lançar do passaro não for chamado, o méotodo foi_lancado deve retornar @@ -265,8 +262,6 @@ def teste_lacamento_vertical(self): passaro_amarelo = PassaroAmarelo(1, 1) passaro_amarelo.lancar(90, 2) # passaro lancado a 90 graus no tempo 2 segundos - - # subindo self.assert_posicao_vertical(1, 2.0, passaro_amarelo) @@ -759,6 +754,6 @@ def assert_posicao_vertical(self, y, tempo, passaro): self.assert_passaro_posicao(1, y, ATIVO, passaro, tempo) -if __name__=='__main__': - teste= AtorTestes() +if __name__ == '__main__': + teste = AtorTestes() teste.teste_colisao_entre_atores_ativos() diff --git a/testes/fase_testes.py b/testes/testes_fase.py similarity index 95% rename from testes/fase_testes.py rename to testes/testes_fase.py index 8158a43f5..ee51e1c36 100644 --- a/testes/fase_testes.py +++ b/testes/testes_fase.py @@ -8,15 +8,13 @@ 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, DuploLancamentoExcecao) -from fase import Fase, Ponto, EM_ANDAMENTO, VITORIA, DERROTA +from atores import Obstaculo, DESTRUIDO, ATIVO, DuploLancamentoExcecao +from fase import Fase, EM_ANDAMENTO, VITORIA, DERROTA class AtorFake: @@ -173,7 +171,7 @@ def teste_lancar_passaro_sem_erro_quando_nao_existe_passaro(self): fase.lancar(90, 1) fase.lancar(45, 3) fase.lancar(31, - 5) # testando que lançar passaros depios de todos + 5) # testando que lançar passaros depois de todos # lançados não causa erro self.assertTrue(passaros[0].foi_lancado()) diff --git a/testes/integracao.py b/testes/testes_integracao.py similarity index 99% rename from testes/integracao.py rename to testes/testes_integracao.py index 11f2f0178..2df2c043e 100644 --- a/testes/integracao.py +++ b/testes/testes_integracao.py @@ -16,8 +16,7 @@ project_dir = os.path.normpath(project_dir) sys.path.append(project_dir) -from atores import Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, DESTRUIDO, ATIVO, \ - Ator, Passaro +from atores import Obstaculo, Porco, PassaroVermelho, PassaroAmarelo, DESTRUIDO from fase import Fase, Ponto, EM_ANDAMENTO, VITORIA, DERROTA class FaseTestes(TestCase):