packages feed

edge-0.8.16: Projectile/SWSide.hs

module Projectile.SWSide ( SWSide(..)
                            , 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 = 3.0

radiusGrowth = 30.0

data SWSide =
  SWSide { 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 -> SWSide
new wmap angle center' (vpx, vpy) =
  let x = cos angle * velocityC in
  let y = sin angle * velocityC in
  SWSide { velocity = (x + vpx, y + vpy)
         , center = center'
         , rangeLeft = rangeC
         , wrapMap = wmap
         , idealNewCenter = Nothing
         , clock = 0.0
         , integrity = integrityMax
         , radius = 2.0
         }

instance Animation SWSide where

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

instance M.Colliding SWSide where

  collisionRadius self = radius self

instance M.Moving SWSide where

  velocity self = Projectile.SWSide.velocity self

instance M.Locatable SWSide where

  center self = Projectile.SWSide.center self

instance SimpleTransient SWSide where

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

instance InternallyUpdating SWSide 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 -> SWSide -> SWSide
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 SWSide where

  damageEnergy self = punch

instance Transient SWSide where

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

instance Damageable SWSide where

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