Files
loop/src/Dodge/WorldEvent/Explosion.hs
T
2022-07-19 13:15:13 +01:00

97 lines
3.5 KiB
Haskell

{-
Explosions: creation of shockwave and particles at a given point.
-}
module Dodge.WorldEvent.Explosion
( makeExplosionAt
, makeFlameExplosionAt
, makePoisonExplosionAt
, makeTeslaExplosionAt
) where
import Dodge.Data
import Dodge.EnergyBall
import Dodge.LightSource
import Dodge.Flame
import Dodge.Base.Collide
import Dodge.WorldEvent.SpawnParticle
--import Dodge.WorldEvent.Flash
import RandomHelp
import Dodge.SoundLogic
import Dodge.WorldEvent.Shockwave
import Geometry
--import Geometry.Vector3D
import Picture
import LensHelp
import Data.List
--import Data.Maybe
makePoisonExplosionAt
:: Point2 -- ^ Position
-> World
-> World
makePoisonExplosionAt p w
= soundMultiFrom [Explosion 0,Explosion 1] p bangS Nothing
$ foldl' (flip $ makeGasCloud p) w
$ replicateM 25 (randInCirc 2) & evalState $ _randGen w
-- just change the number after replicateM to get more or less clouds
-- suggested change: use random positions, offset from p, rather than velocities
-- so, p +.+ randomOffset
-- currently the clouds push away from each other rather hard if they are close
makeTeslaExplosionAt
:: Point2 -- ^ Position
-> World
-> World
makeTeslaExplosionAt = undefined
-- soundOncePos grenadeBang pos $ foldr ($) w listOfFunctions -- a bit shorter
-- where
-- xs = randomRs (0, 2*pi) $ _randGen w
-- j = newProjectileKey w
-- pks = [j..]
-- listOfFunctions = map
-- (\i -> over projectiles (IM.insert (pks!!i) (makeTeslaArcAt (pks!!i) pos (xs!!i))))
-- [1 .. 29]
makeFlameExplosionAt
:: Point2 -- ^ Position
-> World
-> World
makeFlameExplosionAt p w
= soundMultiFrom [Explosion 0,Explosion 1] p bangS Nothing w
& flames .++~ newFlames
where
newFlames = zipWith makeFlameWithVelAndTime velocities timers
makeFlameWithVelAndTime vel time = aFlameParticle time p vel
velocities = replicateM 15 (randInCirc 1) & evalState $ _randGen w
timers = randomRs (80,100) $ _randGen w
-- the ( Nthing :: Maybe Int ) here is "maybe" a creature id that the
-- particle passes through for the first frame of its existence
makeExplosionAt :: Point2 -> World -> World
makeExplosionAt p w = w
& soundMultiFrom [Explosion 0,Explosion 1] p bangS Nothing
& addFlames
& tempLightSources .:~ theTLS
& makeShockwaveAt [] p 50 50 1 white
where
theTLS = tlsTimeRadColPos 20 150 (V3 1 0.5 0) (addZ 20 p)
fVs = replicateM 100 (randInCirc 1) & evalState $ _randGen w
--fPs'' = replicateM 100 (fmap (15 *.*.*) randInHemisphere) & evalState $ _randGen w
fPs'' = replicateM 100 (fmap (15 *.*.*) randInHemisphere) & evalState $ _randGen w
(fPs',zs) = let (a,b,c) = unzip3 $ map fromV3 fPs''
in (zipWith V2 a b, c)
--fPs = map (pushAgainstWalls . (+.+) p . (*.*) 0.5) fPs'
fPs = map (pushAgainstWalls . (+.+) p) fPs'
inversePushOut v = (15 - magV v) * 0.01 *.* v
fVs' = zipWith (+.+) fVs $ map inversePushOut fPs'
sizes = randomRs (2,9) $ _randGen w
--times = randomRs (20,25) $ _randGen w
times = randomRs (15,20) $ _randGen w
mF q z v size time = makeFlamelet q z v size time
newFs = zipWith5 mF fPs zs (fmap (3 *.*) fVs') sizes times
addFlames w' = foldl' (flip ($)) w' newFs
--pushAgainstWalls q = maybe q (uncurry (+.+)) $ reflectPointWalls p q wls
--pushAgainstWalls q = maybe q fst $ reflectPointWalls p q wls
pushAgainstWalls q = maybe q fst $ bouncePoint (const True) 1 p q w
-- wls = wallsNearPoint p w