4 import qualified Data
.Set
as Set
5 import Data
.IntMap
(IntMap
)
6 import qualified Data
.IntMap
as IM
8 import qualified Data
.Stream
as Sm
17 data structure to hide the details of spatial search
18 and collision semantics
20 at first it will be inefficient, hopefully later it
21 can be replaced with a real spatial search structure
22 like a quadtree (somehow)
26 data Spatial
= Spatial
{
27 piecemap
:: IntMap Piece
,
28 collisions
:: TwoIntSet
32 internalInteractions
:: Spatial
->([(Piece
,Piece
)], [(Piece
,Piece
)], Spatial
)
33 internalInteractions
(Spatial pm cols
) = (os
, ds
, Spatial pm
' cols
') where
34 os
= map f
(Set
.elems diff
)
40 s1
= Set
.fromList intpairs
41 f
(Two
(n
,m
)) = (l n
, l m
)
42 l x
= fromMaybe (error emsg
) (IM
.lookup x pm
)
44 intpairs
= map (\(p
,q
) -> Two
(key p
, key q
)) overlaps
45 overlaps
= computeCollisions pm
47 moveEverything
:: Spatial
-> Spatial
48 moveEverything s
= s
{ piecemap
= m
' } where
50 m
' = IM
.filter f
. IM
.map g
. IM
.filter h
$ m
51 h
= isJust . absolute m
54 graphics
= Sm
.tail (graphics p
),
55 wakeup
= IM
.map Sm
.tail (wakeup p
)
60 allPieces
:: Spatial
-> [Piece
]
61 allPieces s
= IM
.elems (piecemap s
)
63 pokePiece
:: Piece
-> Collision
-> Spatial
-> (Spatial
, [Operation
])
64 pokePiece p c s
= (s
', rs
) where
66 (p
',rs
) = (transfer p
) p c
69 then IM
.delete (key p
') m
70 else IM
.insert (key p
') p
' m
71 s
' = s
{ piecemap
= m
' }
73 spawnPieces
:: [Piece
] -> Spatial
-> Spatial
74 spawnPieces ps s
= s
' where
80 snapShotPieces
:: Spatial
-> [(Image
, Coord
)]
81 snapShotPieces s
= catMaybes mbyImgXys
where
82 pcs
= sort (allPieces s
)
84 f p
= absolute (piecemap s
) p
>>= \xy
-> return (Sm
.head (graphics p
), xy
)
88 -- this will crash if there is cyclic dependency in
89 -- relative piece positions
90 absolute :: IntMap Piece
-> Piece
-> Maybe Coord
92 x
<- listToMaybe (path p
)
101 absoluteBound
:: IntMap Piece
-> Piece
-> Bound
102 absoluteBound m p
= (o
+ xy
, wh
) where
103 o
= fromMaybe (error emsg
) (absolute m p
)
105 emsg
= "absoluteBound of nowhere"
108 areColliding
:: IntMap Piece
-> Piece
-> Piece
-> Bool
109 areColliding m p1 p2
= overlap
(absoluteBound m p1
) (absoluteBound m p2
)
111 computeCollisions
:: IntMap Piece
-> [(Piece
, Piece
)]
112 computeCollisions m
=
115 (x
:xs
) <- tails (IM
.elems m
),