edge-0.8: Projectile/Nuke.hs
module Projectile.Nuke ( Nuke(..)
, new
) 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 ResourceTracker
import Data.Maybe
velocityC = 200.0
punch = 8.0
residualPunch = 0.1
detTime = 1.5
data Nuke =
Nuke { velocity :: (Double, Double)
, center :: WrapPoint
, wrapMap :: WrapMap
, idealNewCenter :: Maybe WrapPoint
, clock :: Double
, initialBlastCompleted :: Bool
, resourceTracker :: ResourceTracker
}
-- angle is radians
new :: WrapMap -> ResourceTracker -> Double -> WrapPoint -> (Double, Double) -> Nuke
new wmap rt angle center' (vpx, vpy) =
let x = cos angle * velocityC in
let y = sin angle * velocityC in
Nuke { velocity = (x + vpx, y + vpy)
, center = center'
, wrapMap = wmap
, idealNewCenter = Nothing
, clock = 0.0
, initialBlastCompleted = False
, resourceTracker = rt
}
instance Animation Nuke where
image self t =
let c = clock self in
if c < detTime
then Color green (Circle 2.0)
else if c < detTime + 0.05
then p0
else if c < detTime + 0.1
then p1
else if c < detTime + 0.15
then p2
else if c < detTime + 0.2
then p3
else Blank
where p0 = failImg (getImage rt "nuke-0.bmp")
p1 = failImg (getImage rt "nuke-1.bmp")
p2 = failImg (getImage rt "nuke-2.bmp")
p3 = failImg (getImage rt "nuke-3.bmp")
rt = resourceTracker self
failImg = \x -> Scale 2.0 2.0 (fromMaybe (Color white (Circle 125.0)) x)
instance M.Colliding Nuke where
collisionRadius self =
if clock self < detTime
then 2.0
else 200
instance M.Moving Nuke where
velocity b = Projectile.Nuke.velocity b
instance M.Locatable Nuke where
center b = Projectile.Nuke.center b
instance SimpleTransient Nuke where
expired self = clock self >= detTime + 0.5
instance InternallyUpdating Nuke where
preUpdate self t = let s' = updateIdealTargetCenter t self in
s' { clock = clock self + t
, velocity = if clock self >= detTime
then (0.0, 0.0)
else velocity self
}
postUpdate self t =
let center' = case idealNewCenter self of
Nothing -> center self
Just x -> x in
self { center = center'
, idealNewCenter = Nothing
, initialBlastCompleted = clock self >= detTime
}
updateIdealTargetCenter :: Double -> Nuke -> Nuke
updateIdealTargetCenter t self =
let newLoc = M.idealNewLocation (wrapMap self)
(center self)
(velocity self)
t in
self { idealNewCenter = Just (newLoc)
}
instance Damaging Nuke where
damageEnergy self =
let c = clock self in
if c < detTime
then 0.0
else if initialBlastCompleted self
then residualPunch
else punch
instance Transient Nuke where
expired' self = if clock self >= detTime + 0.5
then Just []
else Nothing
instance Damageable Nuke where
inflictDamage self _ = self