edge-0.8.18: Unit/Smart/Tank.hs
module Unit.Smart.Tank ( Tank(..)
, new
) where
import Data.WrapAround ( WP, WM )
import Animation
( Audible(..), Animation(..), termSndSrc, reorient, handSndSrc )
import Graphics.Gloss.Data.Picture ()
import Graphics.Gloss.Data.Color ()
import GHC.Float ()
import Math ( moreThanZero )
import ResourceTracker ( ResourceTracker, protectedGetImage )
import Updating
( Transient(..), Observant(..), InternallyUpdating(..) )
import qualified Moving as M
( Moving(..),
Locatable(..),
Colliding(..),
newVelocity,
newLocation )
import Combat
( Projectile, Launcher(..), Damaging(..), Damageable(..) )
import qualified Projectile.BulletSI as P.BulletSI ( prj )
import AfterEffect ( AfterEffect(AfterEffect) )
import qualified AfterEffect.SimpleExplosion as SimpleExplosion
( new )
import Data.Maybe ()
import Universe ( Arena )
import qualified Universe as U ()
import Sound.ALUT ( Source )
import Common ( Velocity, Time, Angle )
import UnitUtil ( adjAngle, firingAngle )
import Unit ( firing )
radialVelocity = pi/6
maxVelocityMag = 40
kamikazeDamage = 10
maxIntegrity = 3
accelerationRate = 30
collisionR = 20
data Tank = Tank { angle :: Angle -- radians
, velocity :: Velocity
, center :: WP
, wmap :: WM
, launchTube :: [Projectile]
, sinceLastShot :: Time
, integrity :: Double
, vision :: Maybe Arena
, rt :: ResourceTracker
, queueShotSnd :: Bool
, shotSndSrc :: Maybe Source
}
instance Audible Tank 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 :: ResourceTracker
-> WM
-> WP
-> Angle
-> Tank
new a b c d =
Tank { center = c
, angle = d
, velocity = (0.0, 0.0)
, wmap = b
, launchTube = []
, sinceLastShot = 0.0
, integrity = maxIntegrity
, vision = Nothing
, rt = a
, queueShotSnd = False
, shotSndSrc = Nothing
}
instance Observant Tank where
updateVision s a = s { vision = Just a }
updateAngle t s = adjAngle s t vision (\x y -> x { angle = y }) angle (pi / 6) radialVelocity
updateVelocity t s = s { velocity = M.newVelocity
(velocity s)
accelerationRate
(angle s)
maxVelocityMag
t
}
instance Animation Tank where
image s _ = reorient (angle s) (protectedGetImage (rt s) "tank.bmp")
instance M.Locatable Tank where
center = center
instance M.Moving Tank where
velocity = velocity
instance M.Colliding Tank where
collisionRadius _ = collisionR
instance InternallyUpdating Tank where
preUpdate s t = (updateFiringInformation t
. updateVelocity t
. updateAngle t) s
postUpdate s t =
s { center = M.newLocation (wmap s) (center s) (velocity 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 = P.BulletSI.prj s wmap (firingAngle s vision angle)
instance Launcher Tank where
deployProjectiles s = (launchTube s, s { launchTube = [] })
instance Transient Tank where
expired' s = if moreThanZero (integrity s) then Nothing else Just [a]
where a = AfterEffect
(SimpleExplosion.new (rt s)(wmap s) (center s) (velocity s))
instance Damageable Tank where
inflictDamage s d = s { integrity = max 0 (integrity s - d) }
instance Damaging Tank where
damageEnergy s = kamikazeDamage