packages feed

edge-0.8.18: Unit/Simple/Turret.hs

module Unit.Simple.Turret ( Turret(..)
                          , new
                          ) where

import Data.WrapAround (WP, WM)
import Animation (Audible(..), Animation(..), handSndSrc, termSndSrc, reorient)
import Math (appPair)
import ResourceTracker (RT, protectedGetImage)
import Updating (InternallyUpdating(..), Transient(..))
import qualified Moving as M (Locatable(..)
                             , Moving(..)
                             , Colliding(..)
                             , newLocation')
import Combat (Launcher(..), Damageable(..), Damaging(..), Projectile(..))
import qualified Projectile.BulletSI as P.BulletSI (prj)
import AfterEffect (AfterEffect(..))
import qualified AfterEffect.SimpleExplosion as SimpleExplosion (new)
import Sound.ALUT (Source(..))
import Common (Angle, Velocity, Time)
import Unit (firing)

radVelocity = pi/6 -- radians per second

velMagnitude = 40

kamikazeDmg = 6.0

maxInteg = 2.0

cRadius = 16

data Turret = Turret { tAngle :: Angle
                     , velocity :: Velocity
                     , center :: WP
                     , wmap :: WM
                     , launchTube :: [Projectile]
                     , sinceLastShot :: Time
                     , integrity :: Double
                     , rt :: RT
                     , queueShotSnd :: Bool
                     , shotSndSrc :: Maybe Source
                     }

instance Audible Turret where

  processAudio s a = handSndSrc s
                       queueShotSnd
                       shotSndSrc
                       (\a -> a { queueShotSnd = False })
                       rt
                       "energy-shot-02.wav"
                       (\a b -> a { shotSndSrc = Just b })
                       a (wmap s) (M.center)

  terminateAudio s = termSndSrc s shotSndSrc

new a b c d e = Turret { center = c
                       , tAngle = d
                       , velocity = appPair (* velMagnitude) (sin e, cos e)
                       , wmap = b
                       , launchTube = []
                       , sinceLastShot = 0
                       , integrity = maxInteg
                       , rt = a
                       , queueShotSnd = False
                       , shotSndSrc = Nothing
                       }

updateAngle t s = s { tAngle = tAngle s - radVelocity * t}

instance Animation Turret where
  image s _ = reorient (tAngle s) (protectedGetImage (rt s) "turret.bmp")

instance M.Locatable Turret where
  center = center

instance M.Moving Turret where
  velocity = velocity

instance M.Colliding Turret where
  collisionRadius _ = cRadius

instance InternallyUpdating Turret where

  preUpdate s t = (updateFiringInformation t . updateAngle t) s

  postUpdate s t = s { center = M.newLocation' s (wmap s) t }

updateFiringInformation t s = firing s sinceLastShot 1.5
                                (\x y -> x { sinceLastShot = y })
                                (\x y -> x { launchTube = y })
                                (\x y -> x { queueShotSnd = y })
                                p t launchTube
  where p = map f [ 0.0, pi / 2, pi, 3 * pi / 2 ]
        f x = P.BulletSI.prj s wmap (tAngle s + x)

instance Launcher Turret where

  deployProjectiles s = (launchTube s, s { launchTube = [] })

instance Transient Turret where

  expired' s = if integrity s > 0 then Nothing else Just [a]
    where a = AfterEffect (SimpleExplosion.new (rt s)
                                               (wmap s)
                                               (center s)
                                               (velocity s))

instance Damageable Turret where

  inflictDamage s d = s { integrity = max 0 (integrity s - d) }

instance Damaging Turret where

  damageEnergy s = kamikazeDmg