packages feed

edge-0.8.16: Projectile/SWForward.hs

module Projectile.SWForward ( SWForward(..)
                            , new
                            ) 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 GHC.Float
import Common

velocityC = 700.0
rangeC = 1000.0

integrityMax = 60.0

punch = 6.0

radiusGrowth = 50.0

data SWForward =
  SWForward { velocity :: Velocity
            , center :: WrapPoint
            , rangeLeft :: Double
            , wrapMap :: WrapMap
            , idealNewCenter :: Maybe WrapPoint
            , integrity :: Double
            , clock :: Time
            , radius :: Double
            }

-- angle is radians
new :: WrapMap -> Angle -> WrapPoint -> Velocity -> SWForward
new wmap angle center' (vpx, vpy) =
  let x = cos angle * velocityC in
  let y = sin angle * velocityC in
  SWForward { velocity = (x + vpx, y + vpy)
            , center = center'
            , rangeLeft = rangeC
            , wrapMap = wmap
            , idealNewCenter = Nothing
            , clock = 0.0
            , integrity = integrityMax
            , radius = 2.0
            }

instance Animation SWForward where

  image self t = Color violet (Circle (double2Float (radius self)))

instance M.Colliding SWForward where

  collisionRadius self = radius self

instance M.Moving SWForward where

  velocity self = Projectile.SWForward.velocity self

instance M.Locatable SWForward where

  center self = Projectile.SWForward.center self

instance SimpleTransient SWForward where

  expired self = rangeLeft self <= 0.0 || integrity self <= 0.0

instance InternallyUpdating SWForward 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
         , radius = min 128.0 ((radius self) + radiusGrowth * t)
         }

updateIdealTargetCenter :: Time -> SWForward -> SWForward
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 SWForward where

  damageEnergy self = punch

instance Transient SWForward where

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

instance Damageable SWForward where

  inflictDamage self d = self { integrity = integrity self - d }