module Projectile.Interceptor ( Interceptor(..) , 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 import GHC.Float import Common import Trigonometry ( doubleRem , radToDeg ) import Data.Maybe import ResourceTracker velocityC = 900.0 rangeC = 1200.0 integrityMax = 60.0 punch = 4.0 radiusC = 12.0 speed = velocityC data Interceptor = Interceptor { velocity :: Velocity , center :: WrapPoint , rangeLeft :: Double , wrapMap :: WrapMap , idealNewCenter :: Maybe WrapPoint , impacted :: Bool , clock :: Time , angle :: Angle , resourceTracker :: ResourceTracker } -- angle is radians new :: WrapMap -> ResourceTracker -> Angle -> WrapPoint -> Velocity -> Interceptor new wmap rt angle' center' (vpx, vpy) = let x = cos angle' * velocityC in let y = sin angle' * velocityC in Interceptor { velocity = (x + vpx, y + vpy) , center = center' , rangeLeft = rangeC , wrapMap = wmap , idealNewCenter = Nothing , clock = 0.0 , impacted = False , angle = angle' , resourceTracker = rt } instance Animation Interceptor where image self t = Rotate a cpic where rt = resourceTracker self defImage x = fromMaybe (Color white (Circle r)) (getImage rt x) p1 = defImage "interceptor-1.bmp" p2 = defImage "interceptor-2.bmp" p3 = defImage "interceptor-3.bmp" rem = clock self `doubleRem` 0.3 cpic = if rem > 0.2 then p3 else if rem > 0.1 then p2 else p1 a = radToDeg (double2Float (angle self)) * (-1) - 90 r = double2Float radiusC instance M.Colliding Interceptor where collisionRadius self = radiusC instance M.Moving Interceptor where velocity self = Projectile.Interceptor.velocity self instance M.Locatable Interceptor where center self = Projectile.Interceptor.center self instance SimpleTransient Interceptor where expired self = impacted self || rangeLeft self <= 0.0 instance InternallyUpdating Interceptor 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 :: Time -> Interceptor -> Interceptor 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 Interceptor where damageEnergy self = punch instance Transient Interceptor where expired' self = if impacted self || rangeLeft self <= 0.0 then Just [] else Nothing instance Damageable Interceptor where inflictDamage self d = if d > 0.0 then self { impacted = True } else self