edge-0.8: Projectile/BulletSII.hs
module Projectile.BulletSII ( BulletSII(..)
, 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
velocityC = 600.0
rangeC = 1000.0
speed = velocityC
data BulletSII =
BulletSII { velocity :: (Double, Double)
, center :: WrapPoint
, rangeLeft :: Double
, wrapMap :: WrapMap
, idealNewCenter :: Maybe WrapPoint
, impacted :: Bool
, clock :: Double
}
-- angle is radians
new :: WrapMap -> Double -> WrapPoint -> (Double, Double) -> BulletSII
new wmap angle center' (vpx, vpy) =
let x = cos angle * velocityC in
let y = sin angle * velocityC in
BulletSII { velocity = (x + vpx, y + vpy)
, center = center'
, rangeLeft = rangeC
, wrapMap = wmap
, idealNewCenter = Nothing
, impacted = False
, clock = 0.0
}
instance Animation BulletSII where
image self t = let r = fromInteger (ceiling (clock self)) - clock self in
Color (c r)
(Rotate 45.0
(Circle 2.0))
where c x | x < 0.10 = green
| x < 0.20 = yellow
| x < 0.30 = green
| x < 0.40 = yellow
| x < 0.50 = green
| x < 0.60 = yellow
| x < 0.70 = green
| x < 0.80 = yellow
| x < 0.90 = green
| otherwise = yellow
instance M.Colliding BulletSII where
collisionRadius b = 1.0
instance M.Moving BulletSII where
velocity b = Projectile.BulletSII.velocity b
instance M.Locatable BulletSII where
center b = Projectile.BulletSII.center b
instance SimpleTransient BulletSII where
expired b = rangeLeft b <= 0.0
instance InternallyUpdating BulletSII 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 :: Double -> BulletSII -> BulletSII
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 BulletSII where
damageEnergy b = 1.0
instance Transient BulletSII where
expired' self = if impacted self || rangeLeft self <= 0.0
then Just []
else Nothing
instance Damageable BulletSII where
inflictDamage self d = if d > 0 then self { impacted = True }
else self