packages feed

edge-0.8.18: Projectile/Blade.hs

module Projectile.Blade ( Blade(..)
                        , new
                        -- , prj
                        , speed
                        ) where

import Combat ( Damageable(..), Damaging(..) )
import Animation ( Animation(..) )
import Updating
    ( SimpleTransient(..), Transient(..), InternallyUpdating(..) )
import Graphics.Gloss.Data.Picture ( Picture(Color, Line, Rotate) )
import Graphics.Gloss.Data.Color ( white )
import Data.WrapAround ( WP, WM, distance )
import qualified Moving as M
    ( Colliding(..), Moving(..), Locatable(..), newLocation )
import Common ( Velocity, Time )
import Math ( radToDeg, remF, appPair, zeroOrLess )
import GHC.Float ( double2Float )
import Data.Maybe ( fromMaybe )
import ResourceTracker ( getImage, RT )

velocityC = 250

rangeC = 1500

damE = 4

speed = velocityC

collisionR = 20

data Blade = Blade { velocity :: Velocity
                   , center :: WP
                   , rangeLeft :: Double
                   , wmap :: WM
                   , idealNewCenter :: Maybe WP
                   , clock :: Time
                   , rt :: RT
                   }

new a b c d (e, f) = Blade { velocity = (x + e, y + e)
                           , center = d
                           , rangeLeft = rangeC
                           , wmap = a
                           , idealNewCenter = Nothing
                           , clock = 0.0
                           , rt = b
                           }
  where (x, y) = appPair ((* velocityC) . ($ c)) (cos, sin)

instance Animation Blade where

  image s t = Rotate (double2Float deg) p
    where deg = radToDeg ((clock s * 4 * pi) `remF` (2 * pi))
          p = fromMaybe
                (Color white
                  (Line [(-40, 0), (40, 0)]))
                (getImage (rt s) "blade.bmp")

instance M.Colliding Blade where

  collisionRadius _ = collisionR

instance M.Moving Blade where

  velocity = velocity

instance M.Locatable Blade where

  center = center

instance SimpleTransient Blade where

  expired = zeroOrLess . rangeLeft

instance InternallyUpdating Blade where

  preUpdate s t = s { clock = clock s + t }

  postUpdate s t = s { center = a, rangeLeft = r }
    where a = M.newLocation (wmap s) (center s) (velocity s) t
          r = max 0 (rangeLeft s - distance (wmap s) (center s) a)

instance Damaging Blade where

  damageEnergy _ = damE

instance Transient Blade where

  expired' s = if (zeroOrLess . rangeLeft) s then Just [] else Nothing

instance Damageable Blade where

  inflictDamage s _ = s

-- -- | Func abstracting construction of 'Blade' 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))