Files
loop/src/Dodge/EnergyBall.hs
T

100 lines
2.8 KiB
Haskell

{-# LANGUAGE LambdaCase #-}
module Dodge.EnergyBall (
updateEnergyBall,
makeFlamelet,
makeMovingEB,
) where
import Data.Maybe
import Dodge.Base.Collide
import Dodge.Damage
import Dodge.Data.World
import Dodge.SoundLogic
import Dodge.Spark
import Geometry
import LensHelp
import Linear.V3
import Picture
import RandomHelp
makeFlamelet :: Point3 -> Point3 -> Float -> Int -> World -> World
makeFlamelet p v s t =
cWorld . lWorld . energyBalls
.:~ EnergyBall
{ _ebVel = v
, _ebPos = p
, _ebTimer = t
, _ebType = FlameletBall s
}
updateEnergyBall :: World -> EnergyBall -> (World, Maybe EnergyBall)
updateEnergyBall w eb
| _ebTimer eb <= 0 = (w, Nothing)
| otherwise =
( ebEffect eb . ebFlicker eb $ ebDamage (eb ^. ebPos) (_ebType eb) w
, Just $ eb & ebTimer -~ 1 & ebPos . _xy .~ bp & ebVel . _xy .~ drag * bv
)
where
drag = case eb ^. ebType of
ExplosiveBall -> 0.9
_ -> 0.85
p = (eb ^. ebPos + eb ^. ebVel) ^. _xy
(bp, bv) = fromMaybe (p, eb ^. ebVel . _xy) $ bouncePoint (const True) 0 (eb ^. ebPos . _xy) p w
ebEffect :: EnergyBall -> World -> World
ebEffect eb = case _ebType eb of
ElectricalBall i ->
soundContinue (EBSound i) (eb ^. ebPos . _xy) elecCrackleS (Just 2)
. randSparkExtraVel
(eb ^. ebVel . _xy)
ElectricSpark
(state (randomR (3, 6)))
(state (randomR (0, 2 * pi)))
(eb ^. ebPos . _xy)
IncendiaryBall{}
| _ebTimer eb == 20 ->
soundStart (EBSound (-1)) (eb ^. ebPos . _xy) fireFadeS Nothing
_ -> id
makeMovingEB :: Point2 -> EnergyBallType -> Point2 -> World -> World
makeMovingEB v ebt p =
cWorld . lWorld . energyBalls
.:~ EnergyBall
{ _ebVel = v `v2z` 0
, _ebPos = p `v2z` 20
, _ebTimer = 20
, _ebType = ebt
}
ebFlicker :: EnergyBall -> World -> World
ebFlicker pt
| _ebTimer pt `mod` 7 == 0 =
cWorld . lWorld . lights
.:~ LSParam (pt ^. ebPos) 70 (0.5 * xyzV4 (ebColor pt))
| otherwise = id
ebColor :: EnergyBall -> Color
ebColor eb = case eb ^. ebType of
IncendiaryBall{} -> red
FlameletBall{} -> red
ElectricalBall{} -> cyan
ExplosiveBall -> white
FlashBall -> white
ebDamage :: Point3 -> EnergyBallType -> World -> World
ebDamage sp dt
| z > 0 && z < 25 = damageInCircle (const $ ebtToDamage (sp ^. _xy) dt) (sp ^. _xy) r
| otherwise = id
where
z = sp ^. _z
r = fromMaybe 5 $ dt ^? fbSize
ebtToDamage :: Point2 -> EnergyBallType -> Damage
ebtToDamage p = \case
FlameletBall{} -> Flaming 1
IncendiaryBall{} -> Flaming 10
ElectricalBall{} -> Electrical 10
ExplosiveBall -> Explosive 10 p
FlashBall -> Flashing 10 p