edge-0.9.1.0: Projectile/BulletMII.hs
{-|
Module : Projectile.BulletMII
Description : Bullet projectile
Copyright : (c) Christopher Howard, 2016
License : GPL-3
Maintainer : ch.howard@zoho.com
-}
module Projectile.BulletMII ( BulletMII(..)
, new
, prj
) where
import Prelude ((+), max, (-), (||), Maybe(..), Bool(..), ($), cos, sin, (.), (<), otherwise, (*), Double)
import Graphics.Gloss.Data.Picture ( Picture(Circle, Color) )
import Graphics.Gloss.Data.Color ( yellow, red, green )
import Data.WrapAround ( WP, WM, distance )
import GHC.Float (double2Float)
import Combat
import Animation
import Updating
import qualified Moving as M
( Moving(..), Locatable(..), Colliding(..), newLocation )
import Common
import Math
velocityC = 400.0
rangeC = 700.0
damE = 2
collisionR = 4
data BulletMII =
BulletMII { velocity :: Velocity
, center :: WP
, rangeLeft :: Double
, wrapMap :: WM
, idealNewCenter :: Maybe WP
, impacted :: Bool
, clock :: Time
}
new a b c (d, e) =
BulletMII { velocity = (x + d, y + e)
, center = c
, rangeLeft = rangeC
, wrapMap = a
, idealNewCenter = Nothing
, impacted = False
, clock = 0.0
}
where (x, y) = appPair ((* velocityC) . ($ b)) (cos, sin)
instance Animation BulletMII where
image s t = (Color (c r) . Circle) (double2Float collisionR)
where c x | x < 0.10 = red
| otherwise = yellow
r = remF (clock s) 0.2
instance M.Colliding BulletMII where
collisionRadius _ = collisionR
instance M.Moving BulletMII where
velocity = velocity
instance M.Locatable BulletMII where
center = center
instance SimpleTransient BulletMII where
expired = zeroOrLess . rangeLeft
instance InternallyUpdating BulletMII 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 - Data.WrapAround.distance (wrapMap s) (center s) a)
instance Damaging BulletMII where
damageEnergy _ = damE
instance Transient BulletMII where
expired' s = if impacted s || zeroOrLess (rangeLeft s) then Just [] else Nothing
instance Damageable BulletMII where
inflictDamage s d = if moreThanZero d then s { impacted = True } else s
-- | Func abstracting construction of 'BulletMII' 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))