packages feed

edge-0.8: Projectile/BulletSII.hs

module Projectile.BulletSII ( BulletSII(..)
                            , new
                            , 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

velocityC = 600.0
rangeC = 1000.0

speed = velocityC

data BulletSII =
  BulletSII { velocity :: (Double, Double)
            , center :: WrapPoint
            , rangeLeft :: Double
            , wrapMap :: WrapMap
            , idealNewCenter :: Maybe WrapPoint
            , impacted :: Bool
            , clock :: Double
            }

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

instance Animation BulletSII where

  image self t = let r = fromInteger (ceiling (clock self)) - clock self in
                           Color (c r)
                                   (Rotate 45.0
                                      (Circle 2.0))
    where c x | x < 0.10 = green
              | x < 0.20 = yellow
              | x < 0.30 = green
              | x < 0.40 = yellow
              | x < 0.50 = green
              | x < 0.60 = yellow
              | x < 0.70 = green
              | x < 0.80 = yellow
              | x < 0.90 = green
              | otherwise = yellow

instance M.Colliding BulletSII where

  collisionRadius b = 1.0

instance M.Moving BulletSII where

  velocity b = Projectile.BulletSII.velocity b

instance M.Locatable BulletSII where

  center b = Projectile.BulletSII.center b

instance SimpleTransient BulletSII where

  expired b = rangeLeft b <= 0.0

instance InternallyUpdating BulletSII 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
         }

updateIdealTargetCenter :: Double -> BulletSII -> BulletSII
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 - distance (wrapMap self)
                                                         (center self)
                                                         (newLoc)
       }

instance Damaging BulletSII where

  damageEnergy b = 1.0

instance Transient BulletSII where

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

instance Damageable BulletSII where

  inflictDamage self d = if d > 0 then self { impacted = True }
                                  else self