packages feed

edge-0.8: Projectile/Blade.hs

module Projectile.Blade ( Blade(..)
                         , new
                         , range
                         , 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
import Trigonometry
import Data.Maybe
import ResourceTracker
import GHC.Float

velocityC = 250.0
rangeC = 1500.0
punch = 4.0

range = rangeC
speed = velocityC

data Blade =
  Blade { velocity :: (Double, Double)
        , center :: WrapPoint
        , rangeLeft :: Double
        , wrapMap :: WrapMap
        , idealNewCenter :: Maybe WrapPoint
        , clock :: Double
        , resourceTracker :: ResourceTracker
        }

-- angle is radians
new :: WrapMap -> ResourceTracker -> Double -> WrapPoint -> (Double, Double) -> Blade
new wmap rt angle center' (vpx, vpy) =
  let x = cos angle * velocityC in
  let y = sin angle * velocityC in
  Blade { velocity = (x + vpx, y + vpy)
         , center = center'
         , rangeLeft = rangeC
         , wrapMap = wmap
         , idealNewCenter = Nothing
         , clock = 0.0
         , resourceTracker = rt
         }

instance Animation Blade where

  image self t = Rotate (double2Float deg) p
    where deg = radToDeg ((clock self * 4 * pi) `doubleRem` (2 * pi))
          p = fromMaybe
                (Color white
                  (Line [(-40, 0), (40, 0)]))
                (getImage rt "blade.bmp")
          rt = resourceTracker self
                             
instance M.Colliding Blade where

  collisionRadius self = 20.0

instance M.Moving Blade where

  velocity self = Projectile.Blade.velocity self

instance M.Locatable Blade where

  center self = Projectile.Blade.center self

instance SimpleTransient Blade where

  expired self = rangeLeft self <= 0.0

instance InternallyUpdating Blade 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
         , clock = clock self + t
         }

updateIdealTargetCenter :: Double -> Blade -> Blade
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
                                 - Data.WrapAround.distance (wrapMap self)
                                                            (center self)
                                                            (newLoc)
       }

instance Damaging Blade where

  damageEnergy b = punch

instance Transient Blade where

  expired' self = if rangeLeft self <= 0.0
                     then Just []
                     else Nothing

instance Damageable Blade where

  inflictDamage self d = self