Untitled
-- Calcula a nova posição e direção do inimigo novaPosicaoEDirecao :: Float -> (Int, Int) -> Mapa -> (Float, Float) -> Float -> ((Float, Float), (Float, Float)) novaPosicaoEDirecao dt destino mapa (xAtual, yAtual) velocidade = let celulaAtual = (floor yAtual, floor xAtual) -- Célula onde o inimigo está (em coordenadas linha-coluna) caminho = gerarCaminho celulaAtual destino mapa -- Calcula o caminho in case caminho of [] -> ((xAtual, yAtual), (0, 0)) -- Sem caminho, o inimigo não se move (prox:_) -> let (linhaProx, colunaProx) = prox -- Próxima célula no caminho (xProx, yProx) = centroCelula prox -- Centro da próxima célula -- Decide a direção do movimento (apenas vertical ou horizontal) direcao | xAtual < xProx = (1, 0) -- Vai para a direita | xAtual > xProx = (-1, 0) -- Vai para a esquerda | yAtual < yProx = (0, 1) -- Vai para baixo | yAtual > yProx = (0, -1) -- Vai para cima | otherwise = (0, 0) -- Já está no centro da célula -- Calcula o próximo movimento com base na velocidade vel = velocidade * dt (dx, dy) = (fromIntegral (fst direcao) * vel, fromIntegral (snd direcao) * vel) novaPos = (xAtual + dx, yAtual + dy) -- Garante que o inimigo não ultrapasse o centro da próxima célula posFinal = limitarPosicao novaPos (xProx, yProx) direcao in (posFinal, direcao) -- Calcula o centro de uma célula do mapa centroCelula :: (Int, Int) -> (Float, Float) centroCelula (linha, coluna) = (fromIntegral coluna + 0.5, fromIntegral linha + 0.5) -- Garante que o inimigo não ultrapasse o centro da célula limitarPosicao :: (Float, Float) -> (Float, Float) -> (Float, Float) -> (Float, Float) limitarPosicao (xAtual, yAtual) (xProx, yProx) (dx, dy) | dx > 0 && xAtual > xProx = (xProx, yAtual) -- Indo para a direita | dx < 0 && xAtual < xProx = (xProx, yAtual) -- Indo para a esquerda | dy > 0 && yAtual > yProx = (xAtual, yProx) -- Indo para baixo | dy < 0 && yAtual < yProx = (xAtual, yProx) -- Indo para cima | otherwise = (xAtual, yAtual) -- Gera o caminho usando BFS gerarCaminho :: (Int, Int) -> (Int, Int) -> Mapa -> [(Int, Int)] gerarCaminho inicio destino mapa = bfs inicio destino mapa -- BFS para calcular o caminho no mapa bfs :: (Int, Int) -> (Int, Int) -> Mapa -> [(Int, Int)] bfs inicio destino mapa = bfsAux [(inicio, [inicio])] [] destino mapa where bfsAux [] _ _ _ = [] -- Sem caminho possível bfsAux ((atual, caminho):fila) visitados destino mapa | atual == destino = reverse caminho -- Chegou ao destino | atual `elem` visitados = bfsAux fila visitados destino mapa -- Ignorar visitados | otherwise = let vizinhosValidos = filter (ehCelulaValida mapa) (vizinhos atual) novos = [(viz, viz:caminho) | viz <- vizinhosValidos, viz `notElem` visitados] in bfsAux (fila ++ novos) (atual:visitados) destino mapa -- Retorna os vizinhos de uma célula vizinhos :: (Int, Int) -> [(Int, Int)] vizinhos (linha, coluna) = [(linha-1, coluna), (linha+1, coluna), (linha, coluna-1), (linha, coluna+1)] -- Norte, Sul, Oeste, Este -- Verifica se uma célula é válida ehCelulaValida :: Mapa -> (Int, Int) -> Bool ehCelulaValida mapa (linha, coluna) = linha >= 0 && linha < length mapa && coluna >= 0 && coluna < length (head mapa) && (mapa !! linha !! coluna == Relva) -- Apenas células de Relva são válidas
Leave a Comment