edge-0.8.18: Projectile/Interceptor.hs
module Projectile.Interceptor ( Interceptor(..)
, new
-- , prj
, speed
) where
import Combat ( Damageable(..), Damaging(..) )
import Animation ( Animation(..), reorient )
import Updating
( SimpleTransient(..), Transient(..), InternallyUpdating(..) )
import Graphics.Gloss.Data.Picture ( Picture(Circle, Color) )
import Graphics.Gloss.Data.Color ( white )
import Data.WrapAround ( WP, WM, distance )
import qualified Moving as M
( Colliding(..), Moving(..), Locatable(..), newLocation )
import Common ( Velocity, Angle, Time )
import Math ( remF, appPair, zeroOrLess, moreThanZero )
import GHC.Float ( double2Float )
import ResourceTracker ( RT, getImage )
import Data.Maybe ( fromMaybe )
velocityC = 900
rangeC = 1200
damE = 4
radiusC = 12.0
speed = velocityC
data Interceptor = Interceptor { velocity :: Velocity
, center :: WP
, rangeLeft :: Double
, wrapMap :: WM
, impacted :: Bool
, clock :: Time
, rt :: RT
, angle :: Angle
}
new a r b c (d, e) = Interceptor { velocity = (x + d, y + e)
, center = c
, rangeLeft = rangeC
, wrapMap = a
, impacted = False
, clock = 0.0
, rt = r
, angle = b
}
where (x, y) = appPair ((* velocityC) . ($ b)) (cos, sin)
instance Animation Interceptor where
image s t = reorient (angle s) c
where f x = fromMaybe (Color white (Circle r)) (getImage (rt s) x)
p1 = f "interceptor-1.bmp"
p2 = f "interceptor-2.bmp"
p3 = f "interceptor-3.bmp"
g = ((clock s `remF` 0.3) >)
c = if g 0.2 then p3 else if g 0.1 then p2 else p1
r = double2Float radiusC
instance M.Colliding Interceptor where
collisionRadius _ = radiusC
instance M.Moving Interceptor where
velocity = velocity
instance M.Locatable Interceptor where
center = center
instance SimpleTransient Interceptor where
expired s = impacted s || (zeroOrLess . rangeLeft) s
instance InternallyUpdating Interceptor where
preUpdate s t = s { clock = clock s + t }
postUpdate s t = s { center = a, rangeLeft = r }
where a = M.newLocation (wrapMap s) (center s) (velocity s) t
r = max 0 (rangeLeft s - distance (wrapMap s) (center s) a)
instance Damaging Interceptor where
damageEnergy _ = damE
instance Transient Interceptor where
expired' s = if impacted s || (zeroOrLess . rangeLeft) s then Just [] else Nothing
instance Damageable Interceptor where
inflictDamage s d = if moreThanZero d then s { impacted = True } else s
-- -- | Func abstracting construction of 'Interceptor' projectile
-- prj :: (M.Moving a)
-- => a -- ^ object receiving projectile
-- -> (a -> WM) -- ^ func which retrieves WM from object
-- -> Angle -- ^ firing angle
-- -> Projectile
-- prj a f b = Projectile (new (f a) b (M.center a) (M.velocity a))