{-| Module : Unit.Smart.Tank Description : Basic tank Copyright : (c) Christopher Howard, 2016 License : GPL-3 Maintainer : ch.howard@zoho.com -} module Unit.Smart.Tank ( Tank(..) , new ) where import Prelude ((.), Maybe(..), max, (-), pi, Bool(..), (/), Double) import Data.WrapAround ( WP, WM ) import Sound.ALUT ( Source ) import Animation import Math import ResourceTracker import Updating import qualified Moving as M ( Moving(..), Locatable(..), Colliding(..), newVelocity, newLocation ) import Combat import qualified Projectile.BulletSI as P.BulletSI ( prj ) import AfterEffect ( AfterEffect(AfterEffect) ) import qualified AfterEffect.SimpleExplosion as SimpleExplosion ( new ) import Universe ( Arena ) import qualified Universe as U () import Common import UnitUtil import Unit 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