packages feed

cadence-0.1.0.0: examples/hungeon/Enemy.hs

{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeApplications           #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Enemy where

import Apecs
import System.Random
import Linear
import Types
import Utils
import Data.Maybe ( isNothing )
import Cadence

enemyAggroRange :: Float
enemyAggroRange = 175.0

makeEnemy :: Enemy -> Position -> System' Entity
makeEnemy enemy pos = do
    let
        (sref, bbox) = case enemyType enemy of
            Reaper -> (Texture RenTexture { textureRef = "reaper-idle", animationFrame = Just 0 }, BoundaryBox (16, 26) (-1, -12))
            Vampire -> (Texture RenTexture { textureRef = "vampire-idle", animationFrame = Just 0 }, BoundaryBox (16, 30) (-6, -11))
            Skeleton -> (Texture RenTexture { textureRef = "skeleton-idle", animationFrame = Just 0 }, BoundaryBox (24, 26) (-2, -11))
            GoldenReaper -> (Texture RenTexture { textureRef = "golden-reaper-idle", animationFrame = Just 0 }, BoundaryBox (16, 26) (-1, -12))
    n <- case enemyType enemy of
        GoldenReaper -> liftIO $ randomRIO (150, 200)
        _ -> liftIO $ randomRIO (35, 50)
    newEntity (enemy, pos, Velocity (V2 0 0), sref, bbox, Health n, Layer 2, IsVisible True)

stepEnemyAI :: System' ()
stepEnemyAI = cmapM_ $ \(Player, Position posP) -> do
    cmapM $ \(Enemy _, Position posE, r) -> case r of
        Texture rt -> do
            let isInRange = distance posP posE <= enemyAggroRange
            ce <- cfold (\_ (CombatEnemy ce) -> Just ce) Nothing
            if isInRange && isNothing ce then do
                let dir = normalize (posP - posE)
                    newVel = dir ^* enemySpeed
                    sref' = case textureRef rt of
                        "reaper-idle" -> rt { textureRef = "reaper-walk", animationFrame = Just 0 }
                        "vampire-idle" -> rt { textureRef = "vampire-walk", animationFrame = Just 0 }
                        "skeleton-idle" -> rt { textureRef = "skeleton-walk", animationFrame = Just 0 }
                        "golden-reaper-idle" -> rt { textureRef = "golden-reaper-walk", animationFrame = Just 0 }
                        _ -> rt
                return (Velocity newVel, Texture sref')
            else
                let sref' = case textureRef rt of
                        "reaper-walk" -> rt { textureRef = "reaper-idle", animationFrame = Just 0 }
                        "vampire-walk" -> rt { textureRef = "vampire-idle", animationFrame = Just 0 }
                        "skeleton-walk" -> rt { textureRef = "skeleton-idle", animationFrame = Just 0 }
                        "golden-reaper-walk" -> rt { textureRef = "golden-reaper-idle", animationFrame = Just 0 }
                        _ -> rt
                in
                    return (Velocity (V2 0 0), Texture sref')
        r' -> return (Velocity (V2 0 0), r')