Untitled
unknown
plain_text
10 months ago
8.0 kB
7
Indexable
{-|
Module : Tarefa3
Description : Mecânica do Jogo
Copyright : Matheus Henrique Monteiro da Silva Azevedo <a111430@alunos.uminho.pt>
Francisco Luciano Martins <a111775@alunos.uminho.pt>
Módulo para a realização da Tarefa 3 de LI1 em 2024/25.
-}
module Tarefa3 where
import LI12425
import Tarefa1
import Tarefa2
-- | Função auxiliar que atualiza as ondas.
atualizaOnda :: Tempo -> Onda -> Onda
atualizaOnda t Onda {inimigosOnda = linimigos, tempoOnda = trestantei, cicloOnda = tempoentreinimigos, entradaOnda = 0} -- se onda estiver ativa:
= case trestantei of
0 -> Onda {inimigosOnda = tail linimigos, tempoOnda = tempoentreinimigos} -- falta botar o inimigo que saiu para jogo
x -> Onda {tempoOnda = max 0 (x - t)}
atualizaOnda t Onda {inimigosOnda = linimigos, tempoOnda = trestantei, entradaOnda = tonda, cicloOnda = tempoentreinimigos}
= Onda {entradaOnda = tnovoonda, inimigosOnda = linimigos, tempoOnda = trestantei, cicloOnda = tempoentreinimigos}
where tnovoonda = max 0 (tonda - t)
-- | Função que atualiza todos os portais do jogo com o passar do tempo.
atualizaPortal :: Tempo -> Portal -> Portal
atualizaPortal t Portal {ondasPortal = londas, posicaoPortal = pos} =
case (inimigosOnda onda) of
[] -> Portal {ondasPortal = restoondas, posicaoPortal = pos}
_ -> Portal {ondasPortal = ondaatualizada:restoondas, posicaoPortal = pos}
where
(onda:restoondas) = londas
ondaatualizada = atualizaOnda t onda
-- | Função que atualiza todos os portais do jogo com o passar do tempo.
atualizaPortais :: Tempo -> [Portal] -> [Portal]
atualizaPortais t lportais = map (atualizaPortal t) lportais
-- | Função auxiliar que atualiza uma torre (cooldown).
atualizaTorre :: Tempo -> [Inimigo] -> Torre -> Torre
atualizaTorre t inimigos torre = torre
-- | Função que atualiza todas as torres do jogo com o passar do tempo.
atualizaTorres :: Tempo -> [Inimigo] -> [Torre] -> [Torre]
atualizaTorres t inimigos torres = map (atualizaTorre t inimigos) torres
-- | Função que atualiza a vida de um inimigo de acordo com os projeteis ativos.
atualizaVidaProjeteis :: Inimigo -> Float
atualizaVidaProjeteis Inimigo {vidaInimigo = vida, projeteisInimigo = lprojeteis}
= if (any (\proj -> tipoProjetil proj == Fogo) lprojeteis)
then vida - 5 -- valor 5 é alterável (testar depois em jogo)
else vida
-- | Função que move os inimigos ** ver melhor se a movimentação está correta **
moveInimigo :: Tempo -> Inimigo -> Mapa -> (Direcao,Posicao)
moveInimigo t Inimigo {posicaoInimigo = (x,y), direcaoInimigo = direcao, velocidadeInimigo = velocidade, projeteisInimigo = lprojeteis} mapa
= if any (\proj -> tipoProjetil proj == Gelo) lprojeteis
then (direcao,(x,y))
else
case direcao of
Norte -> if validaPosicaoTerra (x,y+(velocidade*t)) mapa
then (direcao,(x,y+(velocidade*t)))
else if validaPosicaoTerra (x+(velocidade*t),y) mapa
then (Este,(x,y))
else (Oeste,(x,y))
Sul -> if validaPosicaoTerra (x,(y-velocidade*t)) mapa
then (direcao,(x,(y-velocidade*t)))
else if validaPosicaoTerra (x+(velocidade*t),y) mapa
then (Este,(x,y))
else (Oeste,(x,y))
Este -> if validaPosicaoTerra (x+(velocidade*t),y) mapa
then (direcao,(x+(velocidade*t),y))
else if validaPosicaoTerra (x,y+(velocidade*t)) mapa
then (Norte,(x,y))
else (Sul,(x,y))
Oeste -> if validaPosicaoTerra (x-(velocidade*t),y) mapa
then (direcao,(x-(velocidade*t),y))
else if validaPosicaoTerra (x,y+(velocidade*t)) mapa
then (Norte,(x,y))
else (Sul,(x,y))
-- | Função que atualiza a duração de um projétil com o passar do tempo.
atualizaProjetil :: Tempo -> Projetil -> Projetil
atualizaProjetil t Projetil {duracaoProjetil = Infinita} = Projetil {duracaoProjetil = Infinita}
atualizaProjetil t Projetil {duracaoProjetil = Finita d} = Projetil {duracaoProjetil = Finita (d-t)}
-- | Função que dada uma lista de inimigos ativos retorna uma lista com os inimigos apos serem atacados por uma torre.
atacaInimigos :: Torre -> [Inimigo] -> [Inimigo]
atacaInimigos torre inimigos =
let (iatacar,r) = splitAt (rajadaTorre torre) (inimigosNoAlcance torre inimigos)
inimigosAtacados = map (atingeInimigo torre) iatacar
inimigosRestantes = filter (`notElem` iatacar) inimigos
in inimigosAtacados ++ inimigosRestantes
-- | Função auxiliar que atualiza os inimigos que já sofreram o dano da torre, isto é, movimentação, dano dos projéteis, etc.
atualizaInimigo :: Tempo -> Mapa -> Inimigo -> Inimigo
atualizaInimigo t mapa i
= Inimigo {posicaoInimigo = posnova,
direcaoInimigo = direcaonova,
vidaInimigo = vidanova,
velocidadeInimigo = velocidadenova,
projeteisInimigo = lprojeteisnova}
where lprojeteis = projeteisInimigo i
velocidade = velocidadeInimigo i
(direcaonova,posnova) = moveInimigo t i mapa
vidanova = atualizaVidaProjeteis i
lprojeteisnova = map (atualizaProjetil t) lprojeteis
velocidadenova = if any (\proj -> tipoProjetil proj == Resina) lprojeteis then (velocidade * 0.5) else velocidade
-- | Função auxiliar que retorna o dano que os inimigos que chegaram a base causaram a ela.
getDanoNaBase :: [Inimigo] -> Base -> Float
getDanoNaBase inimigos base = danobase
where inimigosbase = filter (\i -> posicaoInimigo i == posicaoBase base) inimigos
danobase = sum (map (\i -> ataqueInimigo i) inimigosbase)
-- | Função auxiliar que retorna os créditos que os inimigos mortos deram a base.
getButim :: [Inimigo] -> Creditos
getButim inimigos = butim
where inimigosmortos = filter (\i -> vidaInimigo i <= 0) inimigos
butim = sum (map (\i -> butimInimigo i) inimigosmortos)
-- | Função que atualiza os inimigos do jogo (aplica dano, movimenta, etc) e no fim retorna uma tupla com a lista de inimigos atualizadas, o dano dos inimigos a base e o butim dos inimigos mortos.
atualizaInimigos :: Tempo -> Mapa -> Base -> [Torre] -> [Inimigo] -> ([Inimigo],Float,Creditos)
atualizaInimigos t mapa base torres inimigos
= (filter (\i -> vidaInimigo i > 0 && posicaoInimigo i /= posicaoBase base) inimigosatualizados, danobase, butim)
where inimigosaposataque = concatMap (\torre -> if tempoTorre torre == 0 then atacaInimigos torre inimigos else inimigos) torres
inimigosatualizados = map (atualizaInimigo t mapa) inimigosaposataque -- ainda faltam retirar os mortos e os que chegaram a base
danobase = getDanoNaBase inimigosatualizados base
butim = getButim inimigosatualizados
-- | Função que atualiza a base, i.e, a vida da base e os créditos da base.
atualizaBase :: Tempo -> Base -> Float -> Creditos -> Base
atualizaBase t Base {vidaBase = vida, posicaoBase = base, creditosBase = creditos} danobase butim
= Base {vidaBase = vidanova, creditosBase = creditosnovos, posicaoBase = base}
where vidanova = vida - danobase
creditosnovos = creditos + butim
-- | Função principal que atualiza o jogo com o passar do tempo.
atualizaJogo :: Tempo -> Jogo -> Jogo
atualizaJogo t Jogo {baseJogo = base, portaisJogo = lportais, torresJogo = ltorres, inimigosJogo = linimigos, mapaJogo = mapa}
= Jogo {baseJogo = baseatt, portaisJogo = lportaisatt, torresJogo = ltorresatt, inimigosJogo = linimigosatt, mapaJogo = mapa}
where
lportaisatt = atualizaPortais t lportais
ltorresatt = atualizaTorres t linimigos ltorres
(linimigosatt,danonabase,butim) = atualizaInimigos t mapa base ltorresatt linimigos
baseatt = atualizaBase t base danonabase butim
Editor is loading...
Leave a Comment