packages feed

edge-0.8.16: Unit/Simple/Turret.hs

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

import Data.WrapAround
import Animation
import Graphics.Gloss.Data.Picture
import Graphics.Gloss.Data.Color
import GHC.Float
import Math
import ResourceTracker
import Updating
import qualified Moving as M
import Combat
import qualified Projectile.BulletSI as P.BulletSI
import AfterEffect
import qualified AfterEffect.SimpleExplosion as SimpleExplosion
import Data.Maybe
import Sound.ALUT
import Common

radialVelocity = pi/6 -- radians per second

velocityMagnitude = 40

kamikazeDamage = 6.0

maxIntegrity = 2.0

data Turret = Turret { turretAngle :: Angle -- radians
                     , velocity :: Velocity
                     , center :: WrapPoint
                     , idealTargetLocation :: Maybe WrapPoint
                     , wrapMap :: WrapMap
                     , launchTube :: [Projectile]
                     , sinceLastShot :: Time
                     , integrity :: Double
                     , animDefault0 :: Picture
                     , resourceTracker :: ResourceTracker

                     -- Sound
                     , queueShotSound :: Bool
                     , shotSoundSource :: Maybe Source
                     }

instance Audible Turret where

  processAudio self lcenter =
    do self' <- if isNothing (shotSoundSource self)
                  then initializeShotSoundSource self
                  else return self
       if not (queueShotSound self)
               then return self'
               else do let (x, y) = vectorRelation
                                      (wrapMap self)
                                      (lcenter)
                                      (center self)
                       let s = fromJust $ shotSoundSource self
                       sourcePosition s $= (Vertex3 (double2Float x)
                                                    (double2Float (-y))
                                                    0)
                       play [s]
                       return self' { queueShotSound = False }

  terminateAudio self =
    if isNothing (shotSoundSource self)
      then return self
      else do stop [fromJust (shotSoundSource self)]
              return self

initializeShotSoundSource self =
  do [source] <- genObjectNames 1
     buffer source $= getSound (resourceTracker self) "energy-shot-02.wav"
     -- ...
     sourceRelative source $= Listener
     referenceDistance source $= audioReferenceDistance
--     maxDistance source $= audioMaxDistance
     rolloffFactor source $= audioRolloffFactor
     return self { shotSoundSource = Just source }

new :: ResourceTracker
        -> WrapMap
        -> WrapPoint
        -> Angle
        -> Angle
        -> Turret
new rt wmap center' tAngle mAngle =
  let pic = fromMaybe
             (Scale 0.20 0.20
                (Color white
                  (Text "Error! Missing image!")))
                    (getImage rt "turret.bmp") in
  Turret { center = center'
         , turretAngle = tAngle
         , idealTargetLocation = Nothing
         , velocity = velocity'
         , wrapMap = wmap
         , launchTube = []
         , sinceLastShot = 0.0
         , integrity = maxIntegrity
         , animDefault0 = pic
         , resourceTracker = rt

         , queueShotSound = False
         , shotSoundSource = Nothing
         }
  where velocity' =( sin mAngle * velocityMagnitude
                   , cos mAngle * velocityMagnitude
                   )  

updateAngle t self
 = self { turretAngle = turretAngle self - radialVelocity * t}

instance Animation Turret where
  image self _ = Rotate
                   (double2Float
                      (radToDeg ((turretAngle self)) * (-1) - 90))
                   (animDefault0 self)

instance M.Locatable Turret where
  center = center

instance M.Moving Turret where
  velocity = velocity

instance M.Colliding Turret where
  collisionRadius _ = 16.0

instance InternallyUpdating Turret where

  preUpdate self t = (updateFiringInformation t
                        . updateIdealTargetLocation t
                        . updateAngle t) self

  postUpdate self t =
    let center' = fromMaybe (center self) (idealTargetLocation self) in
    self { center = center'
         , idealTargetLocation = Nothing
         }

updateFiringInformation t self =
  let sinceLastShot' = sinceLastShot self + t in
    if sinceLastShot' >= 1.5
      then self { sinceLastShot = 0.0
                , launchTube = launchTube self ++ projectiles
                , queueShotSound = True
                }
      else self { sinceLastShot = sinceLastShot' }
  where projectiles = map projectile [ 0.0, pi / 2, pi, 3 * pi / 2 ]
        projectile x = Projectile ( P.BulletSI.new
                                     (wrapMap self)
                                     (turretAngle self + x)
                                     (center self)
                                     (velocity self) )


updateIdealTargetLocation :: Time -> Turret -> Turret
updateIdealTargetLocation t self =
  self { idealTargetLocation = Just (M.newLocation (wrapMap self)
                                                        (center self)
                                                        (velocity self)
                                                        t)
        }

instance Launcher Turret where

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

instance Transient Turret where

  expired' self = if integrity self > 0.0
                    then Nothing
                    else Just [aeffect]
    where aeffect = AfterEffect (SimpleExplosion.new (resourceTracker self)
                                                     (wrapMap self)
                                                     (center self)
                                                     (velocity self))

instance Damageable Turret where

  inflictDamage self d = self { integrity = max 0.0 (integrity self - d) }

instance Damaging Turret where

  damageEnergy self = kamikazeDamage