Refactor inverse shockwave

This commit is contained in:
2021-09-26 12:09:44 +01:00
parent a823d4c6df
commit 79b2692199
15 changed files with 87 additions and 94 deletions
+3 -3
View File
@@ -60,7 +60,7 @@ glareBetween :: Int -> Float -> Float -> Color -> Point2 -> Point2 -> World -> M
glareBetween 0 _ _ _ _ _ _ = Nothing
glareBetween t len wdth col a b w = Just $ Particle
{_ptDraw = const $ lowLightPic len wdth col (a,b) w
,_ptUpdate' = \ w' _ -> (w',glareBetween (t-1) len wdth col a b w')
,_ptUpdate = \ w' _ -> (w',glareBetween (t-1) len wdth col a b w')
}
lowLightPic :: Float -> Float -> Color -> (Point2, Point2) -> World -> Picture
@@ -81,7 +81,7 @@ flashFlareAt :: Color -> Float -> Point2 -> Particle
flashFlareAt col alphax (V2 x y) = Particle
{ _ptDraw = const $ setLayer 2 . setDepth (-0.9) . translate x y
$ circleSolidCol (withAlpha 0 col) (withAlpha alphax col) 30
, _ptUpdate' = ptTimer' 1
, _ptUpdate = ptTimer' 1
}
explosionFlashAt :: Point2 -> World -> World
@@ -109,7 +109,7 @@ muzzleFlashPt (V2 x y) = Particle
. setLayer 2
. translate x y
$ circleSolidCol (withAlpha 0 white) (withAlpha 0.2 white) 20
, _ptUpdate' = ptTimer' 1
, _ptUpdate = ptTimer' 1
}
laserScopeTargetGlow :: Color -> Point2 -> World -> World
+1 -1
View File
@@ -6,4 +6,4 @@ import Dodge.Data
{- A simple timer update for particles. -}
ptTimer' :: Int -> World -> Particle -> (World, Maybe Particle)
ptTimer' 0 w _ = (w, Nothing)
ptTimer' n w pt = (w, Just $ pt {_ptUpdate' = ptTimer' (n-1)})
ptTimer' n w pt = (w, Just $ pt {_ptUpdate = ptTimer' (n-1)})
+54 -61
View File
@@ -27,46 +27,36 @@ makeShockwaveAt
-> World
makeShockwaveAt is p rad dam push col = over particles (theShockwave :)
where
theShockwave = shockwaveAt is p rad dam push col 10
shockwaveAt
:: [Int] -- ^ IDs of invulnerable creatures.
-> Point2 -> Float -> Int -> Float -> Color -> Int -> Particle
shockwaveAt is p rad dam push col maxtime
= Shockwave'
theShockwave = Shockwave'
{ _ptDraw = drawShockwave
, _ptUpdate' = mvShockwave is
, _ptUpdate = mvShockwave is
, _btColor' = col
, _btPos' = p
, _btRad' = rad
, _btDam' = dam
, _btPush' = push
, _btMaxTime' = maxtime
, _btTimer' = maxtime
, _btMaxTime' = 10
, _btTimer' = 10
}
{-
Shockwave picture.
-}
{- Shockwave picture. -}
drawShockwave :: Particle -> Picture
drawShockwave pt = pic
drawShockwave pt = setDepth 20
. setLayer 1
. uncurryV translate (_btPos' pt)
. color (_btColor' pt)
$ thickCircle rad thickness
where
pic = setDepth 20 . setLayer 1 . uncurryV translate p
$ color (_btColor' pt) $ thickCircle rad thickness
p = _btPos' pt
r = _btRad' pt
thickness = tFraction**2 * r
rad = r - (3/4) * r * tFraction
tFraction = fromIntegral t / fromIntegral (_btMaxTime' pt)
t = _btTimer' pt
tFraction = fromIntegral (_btTimer' pt) / fromIntegral (_btMaxTime' pt)
mvShockwave
:: [Int] -- ^ IDs of invulnerable creatures.
-> World -> Particle -> (World, Maybe Particle)
mvShockwave is w pt
| _btTimer' pt <= 0 = (w, Nothing)
| otherwise
= (dams w , Just $ set btTimer' (t - 1) pt) -- $ set ptDraw (const pic) pt)
| _btTimer' pt <= 0 = ( w , Nothing)
| otherwise = (doDams w , Just $ pt & btTimer' -~ 1)
where
r = _btRad' pt
p = _btPos' pt
@@ -75,56 +65,59 @@ mvShockwave is w pt
t = _btTimer' pt
tFraction = fromIntegral t / fromIntegral (_btMaxTime' pt)
rad = r - (3/4) * r * tFraction
dams = over creatures (IM.map damCr) . flip (IM.foldr (damageBlocksBy 1)) hitBlocks
doDams = over creatures (IM.map damCr) . flip (IM.foldl' (flip $ damageBlocksBy 1)) hitBlocks
hitBlocks = wallsOnCirc p rad $ wallsNearPoint p w
damCr cr | _crID cr `elem` is = cr
| dist (_crPos cr) p < rad + _crRad cr
= over (crState . crDamage)
((:) $ PushDam dam (25 * push *.* safeNormalizeV (_crPos cr -.- p)))
cr
| otherwise = cr
-------------------------------------------------
{-
Create a shockwave going from an outside circle into a center point.
-}
damCr cr
| _crID cr `elem` is || dist (_crPos cr) p >= rad + _crRad cr = cr
| otherwise = cr & crState . crDamage %~
(PushDam dam (25 * push *.* safeNormalizeV (_crPos cr -.- p)) : )
{- Create a shockwave going from an outside circle into a center point. -}
inverseShockwaveAt
:: Point2 -- Center position
-> Float -- Radius
-> Int -- Damage
-> Float -- Push amount
-> Float -- Push amount parameter
-> World
-> World
inverseShockwaveAt p rad _ push pushexp = over particles (theShockwave :)
inverseShockwaveAt p rad dam push = over particles (theShockwave :)
where
theShockwave = Particle
{ _ptDraw = const blank
, _ptUpdate' = moveInverseShockWave 10 p rad push pushexp
theShockwave = Shockwave'
{ _ptDraw = drawInverseShockwave
, _ptUpdate = moveInverseShockwave
, _btColor' = cyan
, _btPos' = p
, _btRad' = rad
, _btDam' = dam
, _btPush' = push
, _btMaxTime' = 10
, _btTimer' = 10
}
moveInverseShockWave
:: Int -- ^ Timer
-> Point2 -- ^ Center position
-> Float -- ^ Radius
-> Float -- ^ Push amount
-> Float -- ^ Push amount parameter
-> World
moveInverseShockwave
:: World
-> Particle
-> (World, Maybe Particle)
moveInverseShockWave 0 _ _ _ _ w _ = (w, Nothing)
moveInverseShockWave t p r push pushexp w pt
= (dams w, Just $ newupdate $ newpic pt )
moveInverseShockwave w pt
| t <= 0 = ( w, Nothing)
| otherwise = (dams w, Just $ btTimer' -~ 1 $ pt )
where
newupdate = set ptUpdate' $ moveInverseShockWave (t-1) p r push pushexp
newpic = set ptDraw (const $ onLayer PtLayer $ uncurryV translate p
$ color cyan $ thickCircle rad thickness)
rad = r - (4/40) * r * fromIntegral (10 - t)
thickness = fromIntegral (10 - t) **2 * rad / 40
p = _btPos' pt
r = _btRad' pt
t = _btTimer' pt
rad = r - 0.1 * r * fromIntegral (10 - t)
dams = over creatures (IM.map damCr) . flip (foldr (damageBlocksBy 1)) hitBlocks
hitBlocks = wallsOnCirc p rad $ wallsNearPoint p w
damCr cr | dist (_crPos cr) p < rad + _crRad cr
= over (crState . crDamage)
((:) $ PushDam 1 (25 *.* safeNormalizeV (p -.- _crPos cr)))
cr
| otherwise = cr
damCr cr
| dist (_crPos cr) p >= rad + _crRad cr = cr
| otherwise = cr & crState . crDamage %~
(PushDam 1 (25 *.* safeNormalizeV (p -.- _crPos cr)) :)
drawInverseShockwave :: Particle -> Picture
drawInverseShockwave pt
= setLayer 1 $ onLayer PtLayer $ uncurryV translate p
$ color cyan $ thickCircle rad thickness
where
p = _btPos' pt
r = _btRad' pt
t = _btTimer' pt
rad = r - 0.1 * r * fromIntegral (10 - t)
thickness = fromIntegral (10 - t) **2 * rad / 40
+4 -4
View File
@@ -44,7 +44,7 @@ aFlameParticle
-> Particle
aFlameParticle t pos vel maycid = PtZ
{ _ptDraw = drawFlame vel
, _ptUpdate' = moveFlame vel
, _ptUpdate = moveFlame vel
, _btVel' = vel
, _btColor' = red
, _btPos' = pos
@@ -152,7 +152,7 @@ makeFlameletTimed (V2 x y) z vel maycid size time w = w
where
theFlamelet = PtZ
{ _ptDraw = drawFlameletZ rot
, _ptUpdate' = moveFlamelet
, _ptUpdate = moveFlamelet
, _btVel' = vel
, _btColor' = red
, _btPos' = V2 x y
@@ -307,7 +307,7 @@ makeTeslaArcAt :: Color -> Point2 -> Float -> Particle
makeTeslaArcAt col pos dir = LinearParticle
{ _ptPoints = [pos]
, _ptDraw = drawTeslaArc
, _ptUpdate' = moveTeslaArc pos dir
, _ptUpdate = moveTeslaArc pos dir
, _ptTimer = 2
, _ptColor = brightX 100 1.5 col
}
@@ -460,7 +460,7 @@ createSparkCol time col pos dir w
where
spark = BulletPt
{ _ptDraw = drawBul
, _ptUpdate' = mvGenBullet
, _ptUpdate = mvGenBullet
, _btVel' = rotateV dir (V2 5 0)
, _btColor' = col
, _btTrail' = [pos]