Files
loop/src/Dodge/Spark.hs
T
2025-06-24 09:42:51 +01:00

118 lines
3.0 KiB
Haskell

module Dodge.Spark (
updateSpark,
sparkRandDir,
randDirSpark,
randSpark,
randSparkExtraVel,
makeSpark,
) where
import Control.Monad.State
import Dodge.Damage
import Dodge.Data.World
import Dodge.WorldEvent.ThingsHit
import Geometry
import LensHelp
import System.Random
-- should probably reduce spark speed more if it is very fast
updateSpark :: World -> Spark -> (World, Maybe Spark)
updateSpark w sk
| magV (_skVel sk) < 1 = (w, Nothing)
| otherwise = case thingHit sp ep w of
Nothing -> (w & randGen .~ g, Just $ sk & skPos .~ ep & skVel *~ 0.9
& skVel %~ rotateV a
& skOldPos .~ sp)
Just (hp, hthing) ->
( sparkDam sk hthing w
, Just $ sk & skPos .~ hp & skOldPos .~ sp & skVel .~ 0
)
where
(a,g) = randomR (-x,x) (_randGen w)
x = 1
sp = _skPos sk
ep = sp + _skVel sk
sparkDam :: Spark -> Either Creature Wall -> World -> World
sparkDam = damageCrWl . sparkToDamage
sparkToDamage :: Spark -> [Damage]
sparkToDamage sp = case _skType sp of
ElectricSpark -> [Electrical 10]
FireSpark -> [Flaming 1]
NormalSpark -> [Sparking 10]
makeSpark :: SparkType -> Point2 -> Float -> World -> World
makeSpark st p d =
cWorld . lWorld . sparks
.:~ Spark
{ _skVel = rotateV d (V2 5 0)
, _skPos = p
, _skOldPos = p
, _skType = st
}
randDirSpark :: State StdGen Float -> Point2 -> World -> World
randDirSpark randdir pos w =
w
& randGen .~ g
& cWorld . lWorld . sparks
.:~ Spark
{ _skVel = rotateV dir (V2 5 0)
, _skPos = pos
, _skOldPos = pos
, _skType = NormalSpark
}
where
(dir, g) = randdir `runState` _randGen w
randSpark ::
SparkType ->
State StdGen Float ->
State StdGen Float ->
Point2 ->
World ->
World
randSpark dt randspeed randdir pos w =
w
& randGen .~ g
& cWorld . lWorld . sparks
.:~ Spark
{ _skVel = rotateV dir (V2 speed 0)
, _skPos = pos
, _skOldPos = pos
, _skType = dt
}
where
((dir, speed), g) = (`runState` _randGen w) $ do
d <- randdir
x <- randspeed
return (d, x)
randSparkExtraVel ::
Point2 ->
SparkType ->
State StdGen Float ->
State StdGen Float ->
Point2 ->
World ->
World
randSparkExtraVel v dt randspeed randdir pos w =
w
& randGen .~ g
& cWorld . lWorld . sparks
.:~ Spark
{ _skVel = v + rotateV dir (V2 speed 0)
, _skPos = pos
, _skOldPos = pos
, _skType = dt
}
where
((dir, speed), g) = (`runState` _randGen w) $ do
d <- randdir
x <- randspeed
return (d, x)
sparkRandDir :: Float -> Point2 -> Float -> World -> World
sparkRandDir a pos dir = randDirSpark (state $ randomR (dir - a, dir + a)) pos