edge-0.8.8: Projectile/Interceptor.hs
module Projectile.Interceptor ( Interceptor(..)
, new
, speed
) where
import Combat
import Animation
import Updating
import Graphics.Gloss.Data.Picture
import Graphics.Gloss.Data.Color
import Data.WrapAround
import qualified Moving as M
import GHC.Float
import Common
import Trigonometry ( doubleRem
, radToDeg
)
import Data.Maybe
import ResourceTracker
velocityC = 900.0
rangeC = 1200.0
integrityMax = 60.0
punch = 4.0
radiusC = 12.0
speed = velocityC
data Interceptor =
Interceptor { velocity :: Velocity
, center :: WrapPoint
, rangeLeft :: Double
, wrapMap :: WrapMap
, idealNewCenter :: Maybe WrapPoint
, impacted :: Bool
, clock :: Time
, angle :: Angle
, resourceTracker :: ResourceTracker
}
-- angle is radians
new :: WrapMap -> ResourceTracker -> Angle -> WrapPoint -> Velocity -> Interceptor
new wmap rt angle' center' (vpx, vpy) =
let x = cos angle' * velocityC in
let y = sin angle' * velocityC in
Interceptor { velocity = (x + vpx, y + vpy)
, center = center'
, rangeLeft = rangeC
, wrapMap = wmap
, idealNewCenter = Nothing
, clock = 0.0
, impacted = False
, angle = angle'
, resourceTracker = rt
}
instance Animation Interceptor where
image self t = Rotate a cpic
where rt = resourceTracker self
defImage x = fromMaybe
(Color white
(Circle r))
(getImage rt x)
p1 = defImage "interceptor-1.bmp"
p2 = defImage "interceptor-2.bmp"
p3 = defImage "interceptor-3.bmp"
rem = clock self `doubleRem` 0.3
cpic = if rem > 0.2
then p3
else if rem > 0.1
then p2
else p1
a = radToDeg (double2Float (angle self)) * (-1) - 90
r = double2Float radiusC
instance M.Colliding Interceptor where
collisionRadius self = radiusC
instance M.Moving Interceptor where
velocity self = Projectile.Interceptor.velocity self
instance M.Locatable Interceptor where
center self = Projectile.Interceptor.center self
instance SimpleTransient Interceptor where
expired self = impacted self || rangeLeft self <= 0.0
instance InternallyUpdating Interceptor where
preUpdate self t = let s' = updateIdealTargetCenter t self in
s' { clock = clock self + t }
postUpdate self t =
let center' = case idealNewCenter self of
Nothing -> center self
Just x -> x in
self { center = center'
, idealNewCenter = Nothing
}
updateIdealTargetCenter :: Time -> Interceptor -> Interceptor
updateIdealTargetCenter t self =
let newLoc = M.idealNewLocation (wrapMap self)
(center self)
(velocity self)
t in
self { idealNewCenter = Just (newLoc)
, rangeLeft = max 0.0 $ rangeLeft self - distance (wrapMap self)
(center self)
(newLoc)
}
instance Damaging Interceptor where
damageEnergy self = punch
instance Transient Interceptor where
expired' self = if impacted self || rangeLeft self <= 0.0
then Just []
else Nothing
instance Damageable Interceptor where
inflictDamage self d = if d > 0.0
then self { impacted = True }
else self