packages feed

edge-0.8: Combat.hs

{-# LANGUAGE ExistentialQuantification #-}

module Combat where

import Updating
import Animation
import Moving
import Data.WrapAround

data Projectile = forall a. ( Animation a
                       , Colliding a
                       , Transient a
                       , Damaging a
                       , Damageable a
                       ) => Projectile a

instance Colliding Projectile where

  collisionRadius (Projectile a) = collisionRadius a

instance Moving Projectile where

  velocity (Projectile a) = velocity a

instance Locatable Projectile where
  center (Projectile a) = center a

instance Damaging Projectile where
  damageEnergy (Projectile a) = damageEnergy a

instance Damageable Projectile where
  inflictDamage (Projectile a) et = Projectile (inflictDamage a et)

instance Transient Projectile where
  expired' (Projectile a) = expired' a

instance InternallyUpdating Projectile where
  preUpdate (Projectile a) et = Projectile (preUpdate a et)
  postUpdate (Projectile a) et = Projectile (postUpdate a et)

class Damaging a where

  damageEnergy :: a -> Double

class Damageable a where

  inflictDamage :: a -> Double -> a

inflictDamage' :: (Damaging a, Damageable b) => a -> b -> b
inflictDamage' a b = inflictDamage b (damageEnergy a)

class Launcher a where

  deployProjectiles :: a -> ([Projectile], a)

handleCollisionDamage :: ( Damaging a
                         , Damageable a
                         , Colliding a
                         , Damaging b
                         , Damageable b
                         , Colliding b
                         ) => WrapMap -> Double -> a -> [b] -> (a, [b])

handleCollisionDamage wmap tw x ys = handleCollisionDamage' x ys []

  where handleCollisionDamage' x [] nys = (x, nys)
        handleCollisionDamage' x (y:ys) nys =
          if not $ collisionWindow wmap (max
                                        (maxExpectedVelocity * tw)
                                        (collisionRadius x + collisionRadius y)) x y
            then handleCollisionDamage' x ys (nys ++ [y])
            else
              case collision wmap tw x y of
                Nothing -> handleCollisionDamage' x ys (nys ++ [y])
                Just _ -> let (nx, ny) = ( inflictDamage' y x
                                         , inflictDamage' x y
                                         ) in
                          handleCollisionDamage' nx ys (nys ++ [ny])

handleCollisionDamage' :: ( Damaging a
                         , Damageable a
                         , Colliding a
                         , Damaging b
                         , Damageable b
                         , Colliding b
                         ) => WrapMap -> Double -> [a] -> [b] -> ([a], [b])

handleCollisionDamage' wmap tw xs ys = handleCollisionDamage'' xs ys []

  where handleCollisionDamage'' [] ys nxs = (nxs, ys)
        handleCollisionDamage'' (x:xs) ys nxs =
          let (rx, rys) = handleCollisionDamage wmap tw x ys in
          handleCollisionDamage'' xs rys (nxs ++ [rx])

data Impacting = forall a. (Damaging a, Damageable a, Colliding a) => Impacting a