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 import Common velocityC = 200.0 punch = 8.0 residualPunch = 0.1 detTime = 1.5 data Nuke = Nuke { velocity :: Velocity , center :: WrapPoint , wrapMap :: WrapMap , idealNewCenter :: Maybe WrapPoint , clock :: Time , initialBlastCompleted :: Bool , resourceTracker :: ResourceTracker } -- angle is radians new :: WrapMap -> ResourceTracker -> Angle -> WrapPoint -> Velocity -> 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 :: Time -> 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