edge-0.8.16: Projectile/Pellet.hs
module Projectile.Pellet ( Pellet(..)
, new
, range
) 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 Common
velocityC = 600.0
rangeC = 300.0
punch = 0.3
range = rangeC
data Pellet =
Pellet { velocity :: Velocity
, center :: WrapPoint
, rangeLeft :: Double
, wrapMap :: WrapMap
, idealNewCenter :: Maybe WrapPoint
, impacted :: Bool
}
-- angle is radians
new :: WrapMap -> Angle -> WrapPoint -> Velocity -> Pellet
new wmap angle center' (vpx, vpy) =
let x = cos angle * velocityC in
let y = sin angle * velocityC in
Pellet { velocity = (x + vpx, y + vpy)
, center = center'
, rangeLeft = rangeC
, wrapMap = wmap
, idealNewCenter = Nothing
, impacted = False
}
instance Animation Pellet where
image self t = Color (makeColor8 172 172 172 255) (Circle 1.0)
instance M.Colliding Pellet where
collisionRadius b = 1.0
instance M.Moving Pellet where
velocity b = Projectile.Pellet.velocity b
instance M.Locatable Pellet where
center b = Projectile.Pellet.center b
instance SimpleTransient Pellet where
expired b = rangeLeft b <= 0.0
instance InternallyUpdating Pellet where
preUpdate self t = updateIdealTargetCenter t self
postUpdate self t =
let center' = case idealNewCenter self of
Nothing -> center self
Just x -> x in
self { center = center'
, idealNewCenter = Nothing
}
updateIdealTargetCenter :: Time -> Pellet -> Pellet
updateIdealTargetCenter t self =
let newLoc = M.newLocation (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 Pellet where
damageEnergy b = punch
instance Transient Pellet where
expired' self = if impacted self || rangeLeft self <= 0.0
then Just []
else Nothing
instance Damageable Pellet where
inflictDamage self d = if d > 0 then self { impacted = True }
else self