Start using streaming as the way to consume foldable objects

This commit is contained in:
2022-06-24 09:27:29 +01:00
parent 89dd8502ad
commit 86b1c2581b
6 changed files with 58 additions and 17 deletions
+12 -6
View File
@@ -19,10 +19,11 @@ module Dodge.Base.Collide
, collideCircWalls , collideCircWalls
-- , collideCircWalls' -- , collideCircWalls'
, circOnSomeWall , circOnSomeWall
-- , collidePointWalls , collidePointWalls
, collidePointWallsNorm , collidePointWallsNorm
, collidePointWalls' , collidePointWalls'
, collidePointWallsFilt' , collidePointWallsL
, collidePointWallsFilt
, overlapCircWallsReturnWall , overlapCircWallsReturnWall
, collideCircCrsPoint , collideCircCrsPoint
, collideCircCreatures , collideCircCreatures
@@ -370,15 +371,20 @@ collidePointWalls :: Point2 -> Point2 -> IM.IntMap Wall -> Point2
collidePointWalls p1 p2 = foldr findPoint p2 . fmap _wlLine collidePointWalls p1 p2 = foldr findPoint p2 . fmap _wlLine
where where
findPoint (x,y) p = fromMaybe p $ intersectSegSeg p1 p x y findPoint (x,y) p = fromMaybe p $ intersectSegSeg p1 p x y
collidePointWalls' :: Point2 -> Point2 -> IM.IntMap Wall -> Point2 collidePointWalls' :: (Foldable t, Functor t) => Point2 -> Point2 -> t Wall -> Point2
{-# INLINE collidePointWalls' #-} {-# INLINE collidePointWalls' #-}
collidePointWalls' p1 p2 = foldl' findPoint p2 . fmap _wlLine collidePointWalls' p1 p2 = foldl' findPoint p2 . fmap _wlLine
where where
findPoint p = fromMaybe p . uncurry (intersectSegSeg p1 p) findPoint p = fromMaybe p . uncurry (intersectSegSeg p1 p)
collidePointWallsFilt' :: (Wall -> Bool) -> Point2 -> Point2 -> IM.IntMap Wall -> Point2 collidePointWallsL :: Point2 -> Point2 -> L.Fold Wall Point2
{-# INLINE collidePointWallsFilt' #-} collidePointWallsL p1 p2 = L.Fold findPoint p2 id
collidePointWallsFilt' t p1 p2 = collidePointWalls p1 p2 . IM.filter t where
findPoint p = fromMaybe p . uncurry (intersectSegSeg p1 p) . _wlLine
collidePointWallsFilt :: (Wall -> Bool) -> Point2 -> Point2 -> IM.IntMap Wall -> Point2
{-# INLINE collidePointWallsFilt #-}
collidePointWallsFilt t p1 p2 = collidePointWalls' p1 p2 . IM.filter t
-- | Looks for first collision of a circle with walls. -- | Looks for first collision of a circle with walls.
-- If found, gives point and reflection velocity, reflection damped in normal. -- If found, gives point and reflection velocity, reflection damped in normal.
+5 -2
View File
@@ -27,7 +27,8 @@ import qualified Data.IntMap.Strict as IM
import qualified SDL import qualified SDL
--import Data.Monoid --import Data.Monoid
--import Data.Semigroup --import Data.Semigroup
--import qualified Control.Foldl as L import qualified Control.Foldl as L
import qualified Streaming.Prelude as S
{- Update the screen camera rotation and position, including any in rold scope/remote camera modifiers; {- Update the screen camera rotation and position, including any in rold scope/remote camera modifiers;
update where your avatar's view is from. -} update where your avatar's view is from. -}
updateCamera :: Configuration -> World -> World updateCamera :: Configuration -> World -> World
@@ -213,7 +214,9 @@ farWallDistDirection p w = foldl' (flip (m . f)) (0,0,0,0) vps
where where
--f q = g $ rotateV (negate $ _cameraRot w) $ collidePointWallsFilt' wlIsOpaque p q wos -.- p --f q = g $ rotateV (negate $ _cameraRot w) $ collidePointWallsFilt' wlIsOpaque p q wos -.- p
f q = g $ rotateV (negate $ _cameraRot w) f q = g $ rotateV (negate $ _cameraRot w)
$ collidePointWallsFilt' wlIsOpaque p q (wallsAlongLine p q w) -.- p -- $ collidePointWallsFilt wlIsOpaque p q (wallsAlongLine p q w) -.- p
-- $ L.purely S.fold_ (collidePointWallsL p q) (wallsAlongLineStream p q w) -.- p
$ runIdentity (L.purely S.fold_ (collidePointWallsL p q) (wallsAlongLineStream p q w)) -.- p
g (V2 x y) = (y, negate y, x, negate x) g (V2 x y) = (y, negate y, x, negate x)
m (a,b,c,d) (x,y,z,w') = (max a x, max b y, max c z, max d w') m (a,b,c,d) (x,y,z,w') = (max a x, max b y, max c z, max d w')
vps = concatMap _grViewpoints grs ++ extendedViewPoints p grs vps = concatMap _grViewpoints grs ++ extendedViewPoints p grs
+2 -2
View File
@@ -31,7 +31,7 @@ makePoisonExplosionAt
-> World -> World
makePoisonExplosionAt p w makePoisonExplosionAt p w
= soundMultiFrom [Explosion 0,Explosion 1] p bangS Nothing = soundMultiFrom [Explosion 0,Explosion 1] p bangS Nothing
$ foldr (makeGasCloud p) w $ foldl' (flip $ makeGasCloud p) w
$ replicateM 25 (randInCirc 2) & evalState $ _randGen w $ replicateM 25 (randInCirc 2) & evalState $ _randGen w
-- just change the number after replicateM to get more or less clouds -- just change the number after replicateM to get more or less clouds
-- suggested change: use random positions, offset from p, rather than velocities -- suggested change: use random positions, offset from p, rather than velocities
@@ -89,7 +89,7 @@ makeExplosionAt p w = w
times = randomRs (15,20) $ _randGen w times = randomRs (15,20) $ _randGen w
mF q z v size time = makeFlamelet q z v Nothing size time mF q z v size time = makeFlamelet q z v Nothing size time
newFs = zipWith5 mF fPs zs (fmap (3 *.*) fVs') sizes times newFs = zipWith5 mF fPs zs (fmap (3 *.*) fVs') sizes times
addFlames w' = foldr ($) w' newFs addFlames w' = foldl' (flip ($)) w' newFs
--pushAgainstWalls q = maybe q (uncurry (+.+)) $ reflectPointWalls p q wls --pushAgainstWalls q = maybe q (uncurry (+.+)) $ reflectPointWalls p q wls
pushAgainstWalls q = maybe q fst $ reflectPointWalls p q wls pushAgainstWalls q = maybe q fst $ reflectPointWalls p q wls
wls = wallsNearPoint p w wls = wallsNearPoint p w
+6 -7
View File
@@ -23,6 +23,7 @@ import Geometry
import qualified IntMapHelp as IM import qualified IntMapHelp as IM
import LensHelp import LensHelp
import Data.Foldable
import Data.Tuple import Data.Tuple
aFlameParticle aFlameParticle
:: Int -- ^ Timer :: Int -- ^ Timer
@@ -82,7 +83,7 @@ moveFlame rotd w pt
| otherwise = case thingsHitExceptCr (_ptCrIgnore pt) sp ep w of | otherwise = case thingsHitExceptCr (_ptCrIgnore pt) sp ep w of
((_,Left _):_) -> (doSound $ dodamage w , mvPt' 0.7) ((_,Left _):_) -> (doSound $ dodamage w , mvPt' 0.7)
((p,Right wl):_) -> (doSound $ dodamage w , rfl wl p) ((p,Right wl):_) -> (doSound $ dodamage w , rfl wl p)
_ -> (ptFlicker pt . damwls $ doSound damcrs , mvPt' 0.98) _ -> (ptFlicker pt $ doSound $ dodamage w , mvPt' 0.98)
where where
time = _ptTimer pt time = _ptTimer pt
doSound = soundContinue Flame (V2 x y) fireLoudS (Just 2) doSound = soundContinue Flame (V2 x y) fireLoudS (Just 2)
@@ -95,14 +96,11 @@ moveFlame rotd w pt
, _ptCrIgnore = Nothing , _ptCrIgnore = Nothing
, _ptVel = speed *.* vel } , _ptVel = speed *.* vel }
dodamage = damageInArea closeCrs closeWls pt dodamage = damageInArea closeCrs closeWls pt
damwls w' = foldr (\wl -> fst . hiteff [(ep,Right wl)]) w' $ IM.filter closeWls $ wallsNearPoint ep w
damcrs = foldr (\cr -> fst . hiteff [(ep,Left cr)]) w $ IM.filter closeCrs $ _creatures w
closeWls wl = uncurry circOnSeg (_wlLine wl) ep 5 closeWls wl = uncurry circOnSeg (_wlLine wl) ep 5
closeCrs cr = dist ep (_crPos cr) closeCrs cr = dist ep (_crPos cr)
< _crRad cr + 10 - min 9 (max 0 (fromIntegral time - 80)) < _crRad cr + 10 - min 9 (max 0 (fromIntegral time - 80))
+ 5 * angleCoeff (angleVV (ep -.- _crPos cr) rotd) + 5 * angleCoeff (angleVV (ep -.- _crPos cr) rotd)
angleCoeff x' = abs $ 1 - abs ( (x' * 2 - pi) / pi ) angleCoeff x' = abs $ 1 - abs ( (x' * 2 - pi) / pi )
hiteff = _ptHitEff pt pt
rfl wl p = Just $ pt rfl wl p = Just $ pt
{ _ptTimer = time - 1 { _ptTimer = time - 1
, _ptPos = pOut p , _ptPos = pOut p
@@ -203,11 +201,12 @@ damageInRadius size pt = damageInArea isClose closeWls pt
isClose cr = dist p (_crPos cr) < _crRad cr + size isClose cr = dist p (_crPos cr) < _crRad cr + size
damageInArea :: (Creature -> Bool) -> (Wall -> Bool) -> Particle -> World -> World damageInArea :: (Creature -> Bool) -> (Wall -> Bool) -> Particle -> World -> World
{-# INLINE damageInArea #-}
damageInArea crt wlt pt w = damwls damcrs damageInArea crt wlt pt w = damwls damcrs
where where
p = _ptPos pt p = _ptPos pt
damcrs = foldr (\cr -> fst . hiteff [(p,Left cr)]) w $ IM.filter crt $ _creatures w damcrs = foldl' (flip $ \cr -> fst . hiteff [(p,Left cr)]) w $ IM.filter crt $ _creatures w
damwls w' = foldr (\wl -> fst . hiteff [(p,Right wl)]) w' $ IM.filter wlt $ wallsNearPoint p w damwls w' = foldl' (flip $ \wl -> fst . hiteff [(p,Right wl)]) w' $ IM.filter wlt $ wallsNearPoint p w
hiteff = _ptHitEff pt pt hiteff = _ptHitEff pt pt
-- | At writing the radius is half the size of the effect area -- | At writing the radius is half the size of the effect area
@@ -234,7 +233,7 @@ makeGasCloud pos vel w = w
(col, g) = runState (takeOne [green,yellow]) $ _randGen w (col, g) = runState (takeOne [green,yellow]) $ _randGen w
{- Attach poison cloud damage to creatures near cloud. -} {- Attach poison cloud damage to creatures near cloud. -}
cloudPoisonDamage :: Cloud -> World -> World cloudPoisonDamage :: Cloud -> World -> World
cloudPoisonDamage c w = w & creatures %~ flip (foldr (IM.adjust doDam)) damagedCrs cloudPoisonDamage c w = w & creatures %~ flip (foldl' (flip $ IM.adjust doDam)) damagedCrs
where where
damagedCrs = IM.keys $ IM.filter f $ creaturesNearPoint clpos w damagedCrs = IM.keys $ IM.filter f $ creaturesNearPoint clpos w
f cr = dist3 (addZ 20 $ _crPos cr) (_clPos c) < _crRad cr + _clRad c + 10 f cr = dist3 (addZ 20 $ _crPos cr) (_clPos c) < _crRad cr + _clRad c + 10
+22
View File
@@ -3,6 +3,7 @@ module Dodge.Zone
, zoneOfLineIntMap , zoneOfLineIntMap
, wallsNearPoint , wallsNearPoint
, wallsAlongLine , wallsAlongLine
, wallsAlongLineStream
, zoneSize , zoneSize
, zoneOfPoint , zoneOfPoint
, wallsAlongCirc , wallsAlongCirc
@@ -30,10 +31,14 @@ import Geometry
import Geometry.Zone import Geometry.Zone
import qualified FoldlHelp as L import qualified FoldlHelp as L
import qualified Streaming.Prelude as S
import Streaming
import Data.Maybe import Data.Maybe
import Data.List import Data.List
import Data.IntMap.Merge.Strict
import qualified Data.IntMap.Strict as IM import qualified Data.IntMap.Strict as IM
import qualified Data.IntSet as IS import qualified Data.IntSet as IS
import Control.Lens
--flattenZones :: Zone (IM.IntMap a) -> IM.IntMap a --flattenZones :: Zone (IM.IntMap a) -> IM.IntMap a
--flattenZones = flattenIMIMIM . _znObjects --flattenZones = flattenIMIMIM . _znObjects
@@ -79,6 +84,9 @@ zoneOfLine (V2 aa ab) (V2 ba bb)
f (x,y) = [(p,r) | p <-[x-1,x,x+1] , r<-[y-1,y,y+1]] f (x,y) = [(p,r) | p <-[x-1,x,x+1] , r<-[y-1,y,y+1]]
--f (x,y) = [(p,r) | p <-[x-2..x+2] , r<-[y-2..y+2]] --f (x,y) = [(p,r) | p <-[x-2..x+2] , r<-[y-2..y+2]]
zoneOfLineStream :: Monad m => Point2 -> Point2 -> Stream (Of (Int,Int)) m ()
zoneOfLineStream = ddaSqStream zoneSize
zoneOfLineIntMap :: Point2 -> Point2 -> IM.IntMap IS.IntSet zoneOfLineIntMap :: Point2 -> Point2 -> IM.IntMap IS.IntSet
--{-# INLINE zoneOfLineIntMap #-} --{-# INLINE zoneOfLineIntMap #-}
--zoneOfLineIntMap = ddaExt zoneSize --zoneOfLineIntMap = ddaExt zoneSize
@@ -168,6 +176,20 @@ wallsAlongLine a b w =
Just val -> val Just val -> val
_ -> IM.empty _ -> IM.empty
restrictIMIM :: IM.IntMap (IM.IntMap a) -> IM.IntMap IS.IntSet -> IM.IntMap (IM.IntMap a)
restrictIMIM = merge dropMissing dropMissing (zipWithMatched $ const IM.restrictKeys)
wallsAlongLineStream :: Monad m => Point2 -> Point2 -> World -> Stream (Of Wall) m ()
wallsAlongLineStream sp ep w = flip S.for S.each $ S.mapMaybe f $ zoneOfLineStream sp ep
where
f (i,j) = w ^? wallsZone . znObjects . ix i . ix j
--wallsAlongLine :: Point2 -> Point2 -> World -> IM.IntMap Wall
----{-# INLINE wallsAlongLine #-}
--wallsAlongLine a b w = _walls w
-- where
-- kps = zoneOfLineIntMap a b
wallsAlongCirc :: Point2 -> Float -> World -> IM.IntMap Wall wallsAlongCirc :: Point2 -> Float -> World -> IM.IntMap Wall
wallsAlongCirc p r w = IM.unions [f y $ f x $ _znObjects $ _wallsZone w | (x,y) <- zoneOfCircle p r] wallsAlongCirc p r w = IM.unions [f y $ f x $ _znObjects $ _wallsZone w | (x,y) <- zoneOfCircle p r]
where where
+11
View File
@@ -3,9 +3,12 @@ module Geometry.Zone
( ddaExt ( ddaExt
, ddaExt' , ddaExt'
, ddaSq , ddaSq
, ddaSqStream
) where ) where
import Geometry.Data import Geometry.Data
import Streaming
import qualified Streaming.Prelude as S
import Data.Foldable import Data.Foldable
import qualified Data.IntMap.Strict as IM import qualified Data.IntMap.Strict as IM
import qualified Data.IntSet as IS import qualified Data.IntSet as IS
@@ -89,6 +92,14 @@ ddaSq s (V2 sx sy) (V2 ex ey) = IM.fromSet (const ys) xs
xs = IS.fromDistinctAscList [minx-1..maxx+1] xs = IS.fromDistinctAscList [minx-1..maxx+1]
ys = IS.fromDistinctAscList [miny-1..maxy+1] ys = IS.fromDistinctAscList [miny-1..maxy+1]
ddaSqStream :: Monad m => Float -> V2 Float -> V2 Float -> Stream (Of (Int,Int)) m ()
ddaSqStream s (V2 sx sy) (V2 ex ey) = S.each [(x,y) | x <- [minx..maxx], y <- [miny..maxy]]
where
maxMin a b | a >= b = (a,b)
| otherwise = (b,a)
(maxx,minx) = maxMin (divTo s sx) (divTo s ex)
(maxy,miny) = maxMin (divTo s sy) (divTo s ey)
-- | Determines which horizontal and vertical lines on a grid are crossed by a -- | Determines which horizontal and vertical lines on a grid are crossed by a
-- line. For each adds the x-y index of the square to the right or above the -- line. For each adds the x-y index of the square to the right or above the
-- crossed grid line. Also adds the index of the square containing the start -- crossed grid line. Also adds the index of the square containing the start