packages feed

edge-0.8: Projectile/Nuke.hs

module Projectile.Nuke ( Nuke(..)
                            , 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 ResourceTracker
import Data.Maybe

velocityC = 200.0

punch = 8.0
residualPunch = 0.1

detTime = 1.5

data Nuke =
  Nuke { velocity :: (Double, Double)
       , center :: WrapPoint
       , wrapMap :: WrapMap
       , idealNewCenter :: Maybe WrapPoint
       , clock :: Double
       , initialBlastCompleted :: Bool
       , resourceTracker :: ResourceTracker
       }

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

instance Animation Nuke where
  image self t =
    let c = clock self in
    if c < detTime
      then Color green (Circle 2.0)
      else if c < detTime + 0.05
             then p0
             else if c < detTime + 0.1
               then p1
               else if c < detTime + 0.15
                      then p2
                      else if c < detTime + 0.2
                        then p3
                        else Blank
    where p0 = failImg (getImage rt "nuke-0.bmp")
          p1 = failImg (getImage rt "nuke-1.bmp")
          p2 = failImg (getImage rt "nuke-2.bmp")
          p3 = failImg (getImage rt "nuke-3.bmp")
          rt = resourceTracker self
          failImg = \x -> Scale 2.0 2.0 (fromMaybe (Color white (Circle 125.0)) x)


instance M.Colliding Nuke where

  collisionRadius self =
    if clock self < detTime
      then 2.0
      else 200

instance M.Moving Nuke where

  velocity b = Projectile.Nuke.velocity b

instance M.Locatable Nuke where

  center b = Projectile.Nuke.center b

instance SimpleTransient Nuke where

  expired self = clock self >= detTime + 0.5

instance InternallyUpdating Nuke where

  preUpdate self t = let s' = updateIdealTargetCenter t self in
                     s' { clock = clock self + t
                        , velocity = if clock self >= detTime
                                       then (0.0, 0.0)
                                       else velocity self
                        }

  postUpdate self t =
    let center' = case idealNewCenter self of
                    Nothing -> center self
                    Just x -> x in
    self { center = center'
         , idealNewCenter = Nothing
         , initialBlastCompleted = clock self >= detTime
         }

updateIdealTargetCenter :: Double -> Nuke -> Nuke
updateIdealTargetCenter t self =
  let newLoc = M.idealNewLocation (wrapMap self)
                                  (center self)
                                  (velocity self)
                                   t in
  self { idealNewCenter = Just (newLoc)
       }

instance Damaging Nuke where

  damageEnergy self =
    let c = clock self in
    if c < detTime
      then 0.0
      else if initialBlastCompleted self
             then residualPunch
             else punch

instance Transient Nuke where

  expired' self = if clock self >= detTime + 0.5
                     then Just []
                     else Nothing

instance Damageable Nuke where

  inflictDamage self _ = self