Cleanup, split CWorld into separate file

This commit is contained in:
2022-07-26 21:19:12 +01:00
parent c2707719fb
commit 6554d219dc
27 changed files with 1049 additions and 911 deletions
+267 -231
View File
@@ -1,165 +1,175 @@
{-# LANGUAGE BangPatterns #-}
{- |
Module : Dodge.Update
Description : Simulation update
-}
module Dodge.Update ( updateUniverse ) where
import Dodge.Magnet.Update
import Dodge.TmTm
module Dodge.Update (updateUniverse) where
import Color
import Dodge.DrWdWd
import Dodge.TractorBeam.Update
import Dodge.Prop.Update
import Dodge.LinearShockwave.Update
import Dodge.Shockwave.Update
import Dodge.Tesla.Arc
import Dodge.Laser.Update
import Dodge.PressPlate
import Dodge.ModificationEffect
import Dodge.CrGroupUpdate
import Dodge.Zoning.Cloud
import Dodge.Zoning.Creature
import Dodge.WorldEffect
import Dodge.Data
--import Dodge.Zone
import Control.Applicative
import Data.List
import qualified Data.Map.Strict as M
import Data.Maybe
import Dodge.Base
import Dodge.Beam
import Dodge.LightSource.Update
import Dodge.Projectile.Update
import Dodge.Bullet
import Dodge.CrGroupUpdate
import Dodge.Creature.Update
import Dodge.RadarSweep
import Dodge.PosEvent
import Dodge.Spark
import Dodge.CullBox
import Dodge.Data
import Dodge.Distortion
import Dodge.DrWdWd
import Dodge.EnergyBall
import Dodge.Flame
import Dodge.Bullet
import Dodge.Update.Cloud
import Dodge.Machine.Update
import Dodge.RadarBlip
import Dodge.Flare
import Dodge.Menu
import Dodge.CullBox
import Dodge.Distortion
import Dodge.SoundLogic
import Dodge.Update.WallDamage
import Dodge.Base
--import Dodge.Zone
import Dodge.Hammer
import Dodge.WallCreatureCollisions
import Dodge.Update.Camera
import Dodge.Inventory
import Sound.Data
import Dodge.Laser.Update
import Dodge.LightSource.Update
import Dodge.LinearShockwave.Update
import Dodge.Machine.Update
import Dodge.Magnet.Update
import Dodge.Menu
import Dodge.ModificationEffect
import Dodge.PosEvent
import Dodge.PressPlate
import Dodge.Projectile.Update
import Dodge.Prop.Update
import Dodge.RadarBlip
import Dodge.RadarSweep
import Dodge.Shockwave.Update
import Dodge.SoundLogic
import Dodge.Spark
import Dodge.Tesla.Arc
import Dodge.TmTm
import Dodge.TractorBeam.Update
import Dodge.Update.Camera
import Dodge.Update.Cloud
import Dodge.Update.WallDamage
import Dodge.WallCreatureCollisions
import Dodge.WorldEffect
import Dodge.Zoning.Cloud
import Dodge.Zoning.Creature
import Geometry
import LensHelp
import FoldableHelp
import Data.List
import Data.Maybe
import qualified IntMapHelp as IM
import qualified Data.Map.Strict as M
import Control.Applicative
import LensHelp
--import qualified Streaming.Prelude as S
import SDL
import Sound.Data
{- For most menus the only way to change the world is using event handling. -}
updateUniverse :: Universe -> Universe
updateUniverse u = case _menuLayers u of
(WaitScreen s i : _)
| i < 1 -> u & over uvWorld doWorldEvents
| otherwise -> u & menuLayers %~ ( (WaitScreen s (i-1) :) . tail )
(OptionScreen {_scOptionFlag = GameOverOptions} : _) -> u & uvWorld %~
( --updateParticles
(cWorld . radarBlips .~ [])
-- . updateIMl _props _pjUpdate
. updateLightSources
. updateClouds )
(WaitScreen s i : _)
| i < 1 -> u & over uvWorld doWorldEvents
| otherwise -> u & menuLayers %~ ((WaitScreen s (i -1) :) . tail)
(OptionScreen{_scOptionFlag = GameOverOptions} : _) ->
u & uvWorld
%~ (
--updateParticles
(cWorld . radarBlips .~ [])
-- . updateIMl _props _pjUpdate
. updateLightSources
. updateClouds
)
(_ : _) -> u
[] -> functionalUpdate u
[] -> functionalUpdate u
{- | The update step. -}
-- | The update step.
functionalUpdate :: Universe -> Universe
functionalUpdate w = checkEndGame
-- . updateRandGen
. over uvWorld (mouseButtons . each .~ True) -- to determine if the mouse button is held
. over uvWorld (cWorld . worldClock +~ 1)
. over uvWorld updateWorldSelect
. over uvWorld doRewind
. over uvWorld (hammers . each %~ moveHammerUp)
. over uvWorld updateDistortions
. over uvWorld updateCreatureSoundPositions
. over uvWorld ppEvents
. updateCamera
. colCrsWalls
. over uvWorld simpleCrSprings
. over uvWorld zoneCreatures
. over uvWorld (updateIMl (_doors . _cWorld) (doDrWdWd . _drMech) )
. over uvWorld doWorldEvents
. over uvWorld updateDelayedEvents
. over uvWorld (updateIMl (_modifications. _cWorld) (doModificationEffect . _mdUpdate) )
. over uvWorld updateSparks
. over uvWorld updateRadarSweeps
. over uvWorld updatePosEvents
. over uvWorld updateFlames
. over uvWorld updateShockwaves
. over uvWorld updateEnergyBalls
-- . over uvWorld updateParticles
. over uvWorld updateBullets
. over uvWorld updateRadarBlips
. over uvWorld updateFlares
. over uvWorld updateBeams
. over uvWorld updateLasers
. over uvWorld updateTeslaArcs
. over uvWorld updateTractorBeams
. over uvWorld (updateIMl' (_linearShockwaves . _cWorld) updateLinearShockwave)
. over uvWorld (updateIMl' (_props . _cWorld) updateProp )
. over uvWorld (updateIMl' (_projectiles . _cWorld) updateProjectile)
. over uvWorld updateLightSources
. over uvWorld updateClouds
. over uvWorld updateGusts
. over uvWorld zoneClouds
. over uvWorld (updateMIM (cWorld . magnets) (doMagnetUpdate . _mgUpdate) )
. over uvWorld (updateIMl' (_terminals . _cWorld) tmUpdate )
-- . updateIMl _machines mcChooseUpdate
. over uvWorld (updateIMl' (_machines . _cWorld) updateMachine )
. over uvWorld (updateIMl' (_creatures . _cWorld) updateCreature )
functionalUpdate w =
checkEndGame
-- . updateRandGen
. over uvWorld (mouseButtons . each .~ True) -- to determine if the mouse button is held
. over uvWorld (cWorld . worldClock +~ 1)
. over uvWorld updateWorldSelect
. over uvWorld doRewind
. over uvWorld (hammers . each %~ moveHammerUp)
. over uvWorld updateDistortions
. over uvWorld updateCreatureSoundPositions
. over uvWorld ppEvents
. updateCamera
. colCrsWalls
. over uvWorld simpleCrSprings
. over uvWorld zoneCreatures
. over uvWorld (updateIMl (_doors . _cWorld) (doDrWdWd . _drMech))
. over uvWorld doWorldEvents
. over uvWorld updateDelayedEvents
. over uvWorld (updateIMl (_modifications . _cWorld) (doModificationEffect . _mdUpdate))
. over uvWorld updateSparks
. over uvWorld updateRadarSweeps
. over uvWorld updatePosEvents
. over uvWorld updateFlames
. over uvWorld updateShockwaves
. over uvWorld updateEnergyBalls
-- . over uvWorld updateParticles
. over uvWorld updateBullets
. over uvWorld updateRadarBlips
. over uvWorld updateFlares
. over uvWorld updateBeams
. over uvWorld updateLasers
. over uvWorld updateTeslaArcs
. over uvWorld updateTractorBeams
. over uvWorld (updateIMl' (_linearShockwaves . _cWorld) updateLinearShockwave)
. over uvWorld (updateIMl' (_props . _cWorld) updateProp)
. over uvWorld (updateIMl' (_projectiles . _cWorld) updateProjectile)
. over uvWorld updateLightSources
. over uvWorld updateClouds
. over uvWorld updateGusts
. over uvWorld zoneClouds
. over uvWorld (updateMIM (cWorld . magnets) (doMagnetUpdate . _mgUpdate))
. over uvWorld (updateIMl' (_terminals . _cWorld) tmUpdate)
-- . updateIMl _machines mcChooseUpdate
. over uvWorld (updateIMl' (_machines . _cWorld) updateMachine)
. over uvWorld (updateIMl' (_creatures . _cWorld) updateCreature)
-- creatures should be updated early so that crOldPos is set before any position change
. over (uvWorld . cWorld . creatures) (fmap setOldPos)
. over uvWorld updateCreatureGroups
. over uvWorld updateWallDamages
. over uvWorld updateSeenWalls
. over uvWorld updateTerminal
. over uvWorld updateRBList
. updateBounds -- where should this go? next to update camera?
$ over uvWorld updateCloseObjects w
. over (uvWorld . cWorld . creatures) (fmap setOldPos)
. over uvWorld updateCreatureGroups
. over uvWorld updateWallDamages
. over uvWorld updateSeenWalls
. over uvWorld updateTerminal
. over uvWorld updateRBList
. updateBounds -- where should this go? next to update camera?
$ over uvWorld updateCloseObjects w
doWorldEvents :: World -> World
doWorldEvents w = foldr doWorldEffect (w & cWorld . worldEvents .~ []) (_worldEvents (_cWorld w))
doWorldEvents w = foldr doWdWd (w & cWorld . worldEvents .~ []) (_worldEvents (_cWorld w))
updateLasers :: World -> World
updateLasers w = w'
& cWorld . lasers .~ []
& cWorld . lasersToDraw .~ ls
updateLasers w =
w'
& cWorld . lasers .~ []
& cWorld . lasersToDraw .~ ls
where
(w',ls) = mapAccumR updateLaser w (_lasers (_cWorld w))
(w', ls) = mapAccumR updateLaser w (_lasers (_cWorld w))
zoneClouds :: World -> World
zoneClouds w = w
& cWorld . clZoning .~ mempty
& cWorld . clZoning %~ \zn ->
foldl' (flip zoneCloud) zn (_clouds (_cWorld w))
--runIdentity (S.fold_ (flip $ updateZoning (:)) (zn & znObjects .~ mempty) id (_clouds w))
zoneClouds w =
w
& cWorld . clZoning .~ mempty
& cWorld . clZoning %~ \zn ->
foldl' (flip zoneCloud) zn (_clouds (_cWorld w))
--runIdentity (S.fold_ (flip $ updateZoning (:)) (zn & znObjects .~ mempty) id (_clouds w))
updateWorldSelect :: World -> World
updateWorldSelect w = f . g $ case (w ^? mouseButtons . ix ButtonLeft, w ^? mouseButtons . ix ButtonRight) of
(Nothing ,Nothing) -> w
(Just False,Nothing) -> w & cWorld . lLine . _1 .~ mwp
(Just True ,Nothing) -> w & cWorld . lLine . _2 .~ mwp
(Nothing ,_) -> w
(Just False,_) -> w & cWorld . rLine . _1 .~ mwp
(Just True ,_) -> w & cWorld . rLine . _2 .~ mwp
(Nothing, Nothing) -> w
(Just False, Nothing) -> w & lLine . _1 .~ mwp
(Just True, Nothing) -> w & lLine . _2 .~ mwp
(Nothing, _) -> w
(Just False, _) -> w & rLine . _1 .~ mwp
(Just True, _) -> w & rLine . _2 .~ mwp
where
mwp = mouseWorldPos w
f | ButtonLeft `M.member` _mouseButtons w = cWorld . lSelect .~ mwp
f
| ButtonLeft `M.member` _mouseButtons w = lSelect .~ mwp
| otherwise = id
g | ButtonRight `M.member` _mouseButtons w = cWorld . rSelect .~ mwp
g
| ButtonRight `M.member` _mouseButtons w = rSelect .~ mwp
| otherwise = id
--mcChooseUpdate :: Machine -> Machine -> World -> World
@@ -167,31 +177,35 @@ updateWorldSelect w = f . g $ case (w ^? mouseButtons . ix ButtonLeft, w ^? mous
-- | _mcHP mc > 0 = _mcUpdate mc mc'
-- | otherwise = destroyMachine mc
displayTerminalLineString :: TerminalLineString -> World -> (String,Color)
displayTerminalLineString :: TerminalLineString -> World -> (String, Color)
displayTerminalLineString tls = case tls of
TerminalLineConst str col -> const (str,col)
TerminalLineConst str col -> const (str, col)
tmUpdate :: Terminal -> World -> World
tmUpdate tm w = case w ^? cWorld . terminals . ix (_tmID tm) . tmFutureLines . ix 0 of
Nothing -> w
Just tl | _tlPause tl > 0 -> w & pointTermParams . tmFutureLines . ix 0 . tlPause -~ 1
Just (TerminalLineDisplay _ f) -> w & pointTermParams %~
( ( tmFutureLines %~ tail )
. ( tmDisplayedLines .:~ displayTerminalLineString f w )
)
Just (TerminalLineEffect _ eff) -> w
& pointTermParams . tmFutureLines %~ tail
& doTmWdWd eff tm
Just (TerminalLineTerminalEffect _ eff) -> w
& pointTermParams . tmFutureLines %~ tail
& pointTermParams %~ doTmTm eff
Just (TerminalLineDisplay _ f) ->
w & pointTermParams
%~ ( (tmFutureLines %~ tail)
. (tmDisplayedLines .:~ displayTerminalLineString f w)
)
Just (TerminalLineEffect _ eff) ->
w
& pointTermParams . tmFutureLines %~ tail
& doTmWdWd eff tm
Just (TerminalLineTerminalEffect _ eff) ->
w
& pointTermParams . tmFutureLines %~ tail
& pointTermParams %~ doTmTm eff
where
pointTermParams = cWorld . terminals . ix (_tmID tm)
setOldPos :: Creature -> Creature
setOldPos cr = cr
& crOldPos .~ _crPos cr
& crOldDir .~ _crDir cr
setOldPos cr =
cr
& crOldPos .~ _crPos cr
& crOldDir .~ _crDir cr
-- hack
--updateRandGen :: World -> World
@@ -199,25 +213,30 @@ setOldPos cr = cr
doRewind :: World -> World
doRewind w = case _maybeWorld (_cWorld w) of
Just' cw -> w & cWorld .~ (cw & timeFlow .~ RewindingLastFrame)
Nothing' -> w & cWorld . timeFlow .~ NormalTimeFlow
Just' cw ->
w & cWorld .~ cw
& timeFlow .~ RewindingLastFrame
Nothing' -> w & timeFlow .~ NormalTimeFlow
zoneCreatures :: World -> World
zoneCreatures w = w
& cWorld . crZoning .~ mempty
& cWorld . crZoning %~ \zn -> foldl' (flip zoneCreature) zn (_creatures (_cWorld w))
-- foldl' (flip $ updateZoning (\cr -> IM.insert (_crID cr) cr))
zoneCreatures w =
w
& cWorld . crZoning .~ mempty
& cWorld . crZoning %~ \zn -> foldl' (flip zoneCreature) zn (_creatures (_cWorld w))
-- foldl' (flip $ updateZoning (\cr -> IM.insert (_crID cr) cr))
-- zn (_creatures w)
updateCreatureSoundPositions :: World -> World
updateCreatureSoundPositions w = M.foldlWithKey' insertSound w
. M.mapMaybeWithKey updateSound
$ _playingSounds w
updateCreatureSoundPositions w =
M.foldlWithKey' insertSound w
. M.mapMaybeWithKey updateSound
$ _playingSounds w
where
insertSound w' k s = w' & toPlaySounds %~ M.insertWith (const id) k s
updateSound (CrMouth cid) s = case w ^? cWorld . creatures . ix cid . crPos of
Just p -> Just s {_soundPos = p, _soundAngDist = Just (soundAngle p w,0)}
Nothing -> Just s {_soundTime = Just 0}
Just p -> Just s{_soundPos = p, _soundAngDist = Just (soundAngle p w, 0)}
Nothing -> Just s{_soundTime = Just 0}
updateSound _ _ = Nothing
--updateIMr :: (World -> IM.IntMap a) -> (a -> a -> World -> World) -> World -> World
@@ -229,15 +248,16 @@ updateIMl' :: (World -> IM.IntMap a) -> (a -> World -> World) -> World -> World
updateIMl' fim fup w = foldl' (flip fup) w (fim w)
updateCreatureGroups :: World -> World
updateCreatureGroups w = w & cWorld . creatureGroups %~
IM.mapMaybe (\cgp -> doCrGroupUpdate (_crGroupUpdate cgp) w cgp)
updateCreatureGroups w =
w & cWorld . creatureGroups
%~ IM.mapMaybe (\cgp -> doCrGroupUpdate (_crGroupUpdate cgp) w cgp)
updateDistortions :: World -> World
updateDistortions = cWorld . distortions %~ mapMaybe updateDistortion
updateLightSources :: World -> World
updateLightSources = cWorld . tempLightSources %~ f
where
where
f = mapMaybe (\b -> updateTempLightSource (_tlsUpdate b) b)
updateRadarBlips :: World -> World
@@ -249,104 +269,108 @@ updateFlares = cWorld . flares %~ mapMaybe updateFlare
updateTeslaArcs :: World -> World
updateTeslaArcs w = w' & cWorld . teslaArcs .~ catMaybes newtas
where
(w',newtas) = mapAccumR moveTeslaArc w $ _teslaArcs (_cWorld w)
(w', newtas) = mapAccumR moveTeslaArc w $ _teslaArcs (_cWorld w)
updateTractorBeams :: World -> World
updateTractorBeams w = w' & cWorld . tractorBeams .~ catMaybes newtas
where
(w',newtas) = mapAccumR updateTractorBeam w $ _tractorBeams (_cWorld w)
(w', newtas) = mapAccumR updateTractorBeam w $ _tractorBeams (_cWorld w)
{- Apply internal particle updates, delete 'Nothing's. -}
updateBullets :: World -> World
updateBullets w = updateInstantBullets $ set (cWorld . bullets) (catMaybes ps) w'
where
(w',ps) = mapAccumR updateBullet w $ _bullets (_cWorld w)
where
(w', ps) = mapAccumR updateBullet w $ _bullets (_cWorld w)
updateShockwaves :: World -> World
updateShockwaves w = w' & cWorld . shockwaves .~ catMaybes newflames
where
(w',newflames) = mapAccumR updateShockwave w $ _shockwaves (_cWorld w)
(w', newflames) = mapAccumR updateShockwave w $ _shockwaves (_cWorld w)
updateFlames :: World -> World
updateFlames w = w' & cWorld . flames .~ catMaybes newflames
where
(w',newflames) = mapAccumR moveFlame w $ _flames (_cWorld w)
(w', newflames) = mapAccumR moveFlame w $ _flames (_cWorld w)
updateEnergyBalls :: World -> World
updateEnergyBalls w = w' & cWorld . energyBalls .~ catMaybes newebs
where
(w',newebs) = mapAccumR moveEnergyBall w $ _energyBalls (_cWorld w)
(w', newebs) = mapAccumR moveEnergyBall w $ _energyBalls (_cWorld w)
updateRadarSweeps :: World -> World
updateRadarSweeps w = w' & cWorld . radarSweeps .~ catMaybes newradarSweeps
where
(w',newradarSweeps) = mapAccumR updateRadarSweep w $ _radarSweeps (_cWorld w)
(w', newradarSweeps) = mapAccumR updateRadarSweep w $ _radarSweeps (_cWorld w)
updateSparks :: World -> World
updateSparks w = w' & cWorld . sparks .~ catMaybes newsparks
where
(w',newsparks) = mapAccumR moveSpark w $ _sparks (_cWorld w)
(w', newsparks) = mapAccumR moveSpark w $ _sparks (_cWorld w)
updatePosEvents :: World -> World
updatePosEvents w = w' & cWorld . posEvents .~ catMaybes newposEvents
where
(w',newposEvents) = mapAccumR updatePosEvent w $ _posEvents (_cWorld w)
(w', newposEvents) = mapAccumR updatePosEvent w $ _posEvents (_cWorld w)
{- Apply internal particle updates, delete 'Nothing's. -}
--updateParticles :: World -> World
--updateParticles w = updateInstantParticles $ set particles (catMaybes ps) w'
-- where
-- where
-- (w',ps) = mapAccumR (\a b -> _ptUpdate b a b) w $ _particles w
updateBeams :: World -> World
updateBeams w = w
& cWorld . newBeams .~ WorldBeams [] [] [] []
& cWorld . beams .~ thebeams
& combineBeams thebeams
updateBeams w =
w
& cWorld . newBeams .~ WorldBeams [] [] [] []
& cWorld . beams .~ thebeams
& combineBeams thebeams
where
thebeams = _newBeams (_cWorld w)
combineBeams :: WorldBeams -> World -> World
combineBeams wbeams w = w''
& cWorld . beams . positronBeams .~ pbeams
& cWorld . beams . electronBeams .~ ebeams
combineBeams wbeams w =
w''
& cWorld . beams . positronBeams .~ pbeams
& cWorld . beams . electronBeams .~ ebeams
where
(w',pbeams) = mapAccumR (combineBeamBeams (_electronBeams wbeams)) w $ _positronBeams wbeams
(w'',ebeams) = mapAccumR (combineBeamBeams (_positronBeams wbeams)) w' $ _electronBeams wbeams
(w', pbeams) = mapAccumR (combineBeamBeams (_electronBeams wbeams)) w $ _positronBeams wbeams
(w'', ebeams) = mapAccumR (combineBeamBeams (_positronBeams wbeams)) w' $ _electronBeams wbeams
combineBeamBeams :: [Beam] -> World -> Beam -> (World,Beam)
combineBeamBeams :: [Beam] -> World -> Beam -> (World, Beam)
combineBeamBeams bms w bm = case intersectBeamBeams bm bms of
(ps,Nothing) -> (w, bm & bmFirstPoints .~ ps)
(ps,Just a) -> (doBeamCombine (_beamCombine (_bmType bm)) a w, bm & bmFirstPoints .~ ps)
(ps, Nothing) -> (w, bm & bmFirstPoints .~ ps)
(ps, Just a) -> (doBeamCombine (_beamCombine (_bmType bm)) a w, bm & bmFirstPoints .~ ps)
-- intersect a beam with a list of beams.
-- returns the (reversed) travel of the beam up to maybe an intersection point
intersectBeamBeams :: Beam -> [Beam]
-> ([Point2], Maybe (Point2,(Point2,Point2,Beam),(Point2,Point2,Beam)))
intersectBeamBeams ::
Beam ->
[Beam] ->
([Point2], Maybe (Point2, (Point2, Point2, Beam), (Point2, Point2, Beam)))
intersectBeamBeams bm bms = f [] $ _bmPoints bm
where
f ps (x:y:ys) = case intersectSegBeams x y bms of
Just (z,a) -> (z:x:ps, Just (z,(x,y,bm),a))
Nothing -> f (x:ps) (y:ys)
f ps [x] = (x:ps, Nothing)
f ps (x : y : ys) = case intersectSegBeams x y bms of
Just (z, a) -> (z : x : ps, Just (z, (x, y, bm), a))
Nothing -> f (x : ps) (y : ys)
f ps [x] = (x : ps, Nothing)
f _ _ = error "made an empty beam"
intersectSegBeams :: Point2 -> Point2 -> [Beam] -> Maybe (Point2,(Point2,Point2,Beam))
intersectSegBeams sp ep (bm:bms) = case intersectSegBeam sp ep bm of
intersectSegBeams :: Point2 -> Point2 -> [Beam] -> Maybe (Point2, (Point2, Point2, Beam))
intersectSegBeams sp ep (bm : bms) = case intersectSegBeam sp ep bm of
Nothing -> intersectSegBeams sp ep bms
--Just a@(z,_) -> maybe (Just a) Just $ intersectSegBeams sp z bms
Just a@(z,_) -> intersectSegBeams sp z bms <|> Just a
Just a@(z, _) -> intersectSegBeams sp z bms <|> Just a
intersectSegBeams _ _ _ = Nothing
intersectSegBeam :: Point2 -> Point2 -> Beam -> Maybe (Point2,(Point2,Point2,Beam))
intersectSegBeam :: Point2 -> Point2 -> Beam -> Maybe (Point2, (Point2, Point2, Beam))
intersectSegBeam sp ep bm = case intersectSegSegs' sp ep (_bmPoints bm) of
Nothing -> Nothing
Just (z,x,y) -> Just (z,(x,y,bm))
Just (z, x, y) -> Just (z, (x, y, bm))
intersectSegSegs' :: Point2 -> Point2 -> [Point2] -> Maybe (Point2,Point2,Point2)
intersectSegSegs' sp ep (x:y:ys) = case intersectSegSeg sp ep x y of
intersectSegSegs' :: Point2 -> Point2 -> [Point2] -> Maybe (Point2, Point2, Point2)
intersectSegSegs' sp ep (x : y : ys) = case intersectSegSeg sp ep x y of
--Just z -> maybe (Just (z,x,y)) Just $ intersectSegSegs' sp z (y:ys)
Just z -> intersectSegSegs' sp z (y:ys) <|> Just (z,x,y)
Nothing -> intersectSegSegs' sp ep (y:ys)
Just z -> intersectSegSegs' sp z (y : ys) <|> Just (z, x, y)
Nothing -> intersectSegSegs' sp ep (y : ys)
intersectSegSegs' _ _ _ = Nothing
--intersectSegSegs :: Point2 -> Point2 -> [Point2] -> Maybe Point2
@@ -362,7 +386,7 @@ intersectSegSegs' _ _ _ = Nothing
--intersectSegSegss _ _ _ = Nothing
--
--intersectSegsSegss :: [Point2] -> [[Point2]] -> Maybe Point2
--intersectSegsSegss (x:y:ys) ass = maybe
--intersectSegsSegss (x:y:ys) ass = maybe
-- (intersectSegsSegss (y:ys) ass)
-- Just
-- (intersectSegSegss x y ass)
@@ -370,8 +394,9 @@ intersectSegSegs' _ _ _ = Nothing
updateInstantBullets :: World -> World
updateInstantBullets w = case _instantBullets (_cWorld w) of
[] -> w
ps -> let (w',ps') = mapAccumR updateBullet (w & cWorld . instantBullets.~[]) ps
in updateInstantBullets $ w' & cWorld . bullets .++~ catMaybes ps'
ps ->
let (w', ps') = mapAccumR updateBullet (w & cWorld . instantBullets .~ []) ps
in updateInstantBullets $ w' & cWorld . bullets .++~ catMaybes ps'
--updateInstantParticles :: World -> World
--updateInstantParticles w = case _instantParticles w of
@@ -384,7 +409,7 @@ updateMIM f up = f %~ IM.mapMaybe (dbArg up)
-- Note that this updates the randgen
--updateCreatures :: World -> World
--updateCreatures w = appEndo f $ w
--updateCreatures w = appEndo f $ w
-- & creatures .~ IM.mapMaybe id m
-- & randGen .~ newg
-- where
@@ -399,8 +424,9 @@ ppEvents w = IM.foldl' (flip $ \pp -> doPressPlateEvent (_ppEvent pp) pp) w $ _p
updateSeenWalls :: World -> World
updateSeenWalls w = foldl' markWallSeen w (map (_wlID . snd) $ allVisibleWalls w)
-- where
-- f w' !i -- = w' & walls . ix i . wlSeen .~ True
-- where
-- f w' !i -- = w' & walls . ix i . wlSeen .~ True
-- = w' { _walls = IM.adjust mw i $ _walls w' }
-- mw wl = wl {_wlSeen = True}
@@ -408,12 +434,14 @@ markWallSeen :: World -> Int -> World
markWallSeen !w !i = w & cWorld . walls .~ IM.adjust markSeen i (_walls (_cWorld w))
markSeen :: Wall -> Wall
markSeen wl = wl {_wlSeen = True}
markSeen wl = wl{_wlSeen = True}
checkEndGame :: Universe -> Universe
checkEndGame uv = case _deathDelay (_cWorld w) of
Just x | x < 0 -> uv & menuLayers .~ [gameOverMenu]
& uvWorld . cWorld . deathDelay .~ Nothing
Just x
| x < 0 ->
uv & menuLayers .~ [gameOverMenu]
& uvWorld . cWorld . deathDelay .~ Nothing
Just _ -> uv & uvWorld . cWorld . deathDelay . _Just -~ 1
_ | _crHP (you w) < 1 -> uv & uvWorld . cWorld . deathDelay ?~ 50
_ -> uv
@@ -426,27 +454,33 @@ updateGusts w = w & cWorld . gusts %~ IM.mapMaybe (mvGust w)
mvGust :: World -> Gust -> Maybe Gust
mvGust _ gu
| _guTime gu < 0 = Nothing
| otherwise = Just $ gu
& guPos .+.+~ _guVel gu
& guTime -~ 1
| otherwise =
Just $
gu
& guPos .+.+~ _guVel gu
& guTime -~ 1
updateClouds :: World -> World
updateClouds w = w' & cWorld . clouds .~ catMaybes mclouds
where
-- cls = _clouds w
(w',mclouds) = mapAccumR updateCloud w (_clouds (_cWorld w))
-- cls = _clouds w
(w', mclouds) = mapAccumR updateCloud w (_clouds (_cWorld w))
cloudEffect :: Cloud -> World -> World
cloudEffect cl = case _clType cl of
GasCloud -> cloudPoisonDamage cl
SmokeCloud -> id
updateCloud :: World -> Cloud -> (World,Maybe Cloud)
updateCloud :: World -> Cloud -> (World, Maybe Cloud)
updateCloud w c
| _clTimer c < 1 = (w, Nothing)
| otherwise = (cloudEffect c w, Just $ c
& clPos .~ finalPos
& clVel .~ finalVel
& clTimer -~ 1
| otherwise =
( cloudEffect c w
, Just $
c
& clPos .~ finalPos
& clVel .~ finalVel
& clTimer -~ 1
)
where
newVel@(V3 _ _ nvz) = (0.95 *.*.* springVels) +.+.+ V3 0 0 (0.001 * vertVel)
@@ -459,14 +493,14 @@ updateCloud w c
newPos2 = stripZ newPos
hitWl = bouncePoint (const True) 1 oldPos2 newPos2 w
finalPos = addZ (min 74 npz) $ maybe newPos2 fst hitWl
-- allowing clouds at/above height 75 causes graphical glitches 22.05.23
-- allowing clouds at/above height 75 causes graphical glitches 22.05.23
finalVel = addZ nvz $ maybe newVel2 snd hitWl
clClSpringVel :: Cloud -> Point3 -> Cloud -> Point3
clClSpringVel a v b
| dist3 pa pb < radDist = v +.+.+ 0.1 *.*.* normalizeV3 (pa -.-.- pb)
| otherwise = v
where
where
pa = _clPos a
pb = _clPos b
radDist = (_clRad a + _clRad b) / 2
@@ -477,32 +511,34 @@ simpleCrSprings w = IM.foldl' (flip crSpring) w $ _creatures (_cWorld w)
-- note that this may in rare cases not push creatures away from each other
crSpring :: Creature -> World -> World
crSpring c w = foldl' (flip $ crCrSpring c) w cs
where
where
cs = crsNearPoint (_crPos c) w
crCrSpring :: Creature -> Creature -> World -> World
crCrSpring c1 c2
| id1 == id2 = id
| id1 == id2 = id
| vec == V2 0 0 = id
| diff >= comRad = id
| otherwise = cWorld . creatures %~
( over (ix id1 . crPos) (+.+ overlap1)
. over (ix id2 . crPos) (-.- overlap2)
)
where
id1 = _crID c1
id2 = _crID c2
vec = _crPos c1 -.- _crPos c2
| otherwise =
cWorld . creatures
%~ ( over (ix id1 . crPos) (+.+ overlap1)
. over (ix id2 . crPos) (-.- overlap2)
)
where
id1 = _crID c1
id2 = _crID c2
vec = _crPos c1 -.- _crPos c2
diff = magV vec
comRad = _crRad c1 + _crRad c2
comRad = _crRad c1 + _crRad c2
overlap1 = ((comRad - diff) * _crMass c2 * 0.5 / massT) *.* errorNormalizeV 55 vec
overlap2 = ((comRad - diff) * _crMass c1 * 0.5 / massT) *.* errorNormalizeV 56 vec
massT = _crMass c1 + _crMass c2
massT = _crMass c1 + _crMass c2
updateDelayedEvents :: World -> World
updateDelayedEvents w = let (neww,newde) = mapAccumR f w (_delayedEvents (_cWorld w))
in neww & cWorld . delayedEvents .~ catMaybes newde
updateDelayedEvents w =
let (neww, newde) = mapAccumR f w (_delayedEvents (_cWorld w))
in neww & cWorld . delayedEvents .~ catMaybes newde
where
f w' (i,g)
| i <= 0 = (w' & cWorld . worldEvents .:~ g, Nothing)
| otherwise = (w', Just (i-1,g))
f w' (i, g)
| i <= 0 = (w' & cWorld . worldEvents .:~ g, Nothing)
| otherwise = (w', Just (i -1, g))