module Projectile.Pellet ( Pellet(..) , new , range ) 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 Common velocityC = 600.0 rangeC = 300.0 punch = 0.3 range = rangeC data Pellet = Pellet { velocity :: Velocity , center :: WrapPoint , rangeLeft :: Double , wrapMap :: WrapMap , idealNewCenter :: Maybe WrapPoint , impacted :: Bool } -- angle is radians new :: WrapMap -> Angle -> WrapPoint -> Velocity -> Pellet new wmap angle center' (vpx, vpy) = let x = cos angle * velocityC in let y = sin angle * velocityC in Pellet { velocity = (x + vpx, y + vpy) , center = center' , rangeLeft = rangeC , wrapMap = wmap , idealNewCenter = Nothing , impacted = False } instance Animation Pellet where image self t = Color (makeColor8 172 172 172 255) (Circle 1.0) instance M.Colliding Pellet where collisionRadius b = 1.0 instance M.Moving Pellet where velocity b = Projectile.Pellet.velocity b instance M.Locatable Pellet where center b = Projectile.Pellet.center b instance SimpleTransient Pellet where expired b = rangeLeft b <= 0.0 instance InternallyUpdating Pellet where preUpdate self t = updateIdealTargetCenter t self postUpdate self t = let center' = case idealNewCenter self of Nothing -> center self Just x -> x in self { center = center' , idealNewCenter = Nothing } updateIdealTargetCenter :: Time -> Pellet -> Pellet 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 Pellet where damageEnergy b = punch instance Transient Pellet where expired' self = if impacted self || rangeLeft self <= 0.0 then Just [] else Nothing instance Damageable Pellet where inflictDamage self d = if d > 0 then self { impacted = True } else self