packages feed

HGE2D 0.1.7.4 → 0.1.8.0

raw patch · 3 files changed

+117/−1 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ HGE2D.Geometry: distanceBB :: (Positioned a, HasBoundingBox b) => a -> b -> Double
+ HGE2D.Geometry: distanceBBSqr :: (Positioned a, HasBoundingBox b) => a -> b -> Double
+ HGE2D.QuadTree: NN :: QuadDir
+ HGE2D.QuadTree: NP :: QuadDir
+ HGE2D.QuadTree: PN :: QuadDir
+ HGE2D.QuadTree: PP :: QuadDir
+ HGE2D.QuadTree: QuadBranch :: (QuadTree a) -> (QuadTree a) -> (QuadTree a) -> (QuadTree a) -> BoundingBox -> QuadTree a
+ HGE2D.QuadTree: QuadEmpty :: QuadTree a
+ HGE2D.QuadTree: QuadLeaf :: a -> QuadTree a
+ HGE2D.QuadTree: buildQuadTree :: (Positioned a) => BoundingBox -> [a] -> QuadTree a
+ HGE2D.QuadTree: calcQuadDir :: (Positioned a) => a -> BoundingBox -> QuadDir
+ HGE2D.QuadTree: data QuadDir
+ HGE2D.QuadTree: data (Positioned a) => QuadTree a
+ HGE2D.QuadTree: nearestQuad :: (Positioned a, Positioned b) => a -> QuadTree b -> Maybe b
+ HGE2D.QuadTree: quadTreeToList :: (Positioned a) => QuadTree a -> [a]

Files

HGE2D.cabal view
@@ -2,7 +2,7 @@ --  see http://haskell.org/cabal/users-guide/  name:                HGE2D-version:             0.1.7.4+version:             0.1.8.0 synopsis:            2D game engine written in Haskell description:         See README and examples/ for further information license:             MIT@@ -36,6 +36,7 @@     HGE2D.Geometry     HGE2D.Collision     HGE2D.Physical+    HGE2D.QuadTree     HGE2D.Settings   -- other-modules:   -- other-extensions:
src/HGE2D/Geometry.hs view
@@ -51,6 +51,23 @@     p1 = getPos x     p2 = getPos y +-- | Distance between a position and a bounding box+distanceBB :: (Positioned a, HasBoundingBox b) => a -> b -> Double+distanceBB p bb = sqrt $ distanceBBSqr p bb++-- | Squared distance between a position and a bounding box+--   Faster than calculating the distance. Can be used to e.g. compare distances cheaply+distanceBBSqr :: (Positioned a, HasBoundingBox b) => a -> b -> Double+distanceBBSqr p bb = dx * dx + dy * dy+  where+      dx = max 0 $ abs (xP - xBB) - w / 2.0+      dy = max 0 $ abs (yP - yBB) - h / 2.0+      xP = getX p+      yP = getY p+      xBB = fst $ centerBB $ getBB bb+      yBB = snd $ centerBB $ getBB bb+      (w, h) = sizeBB $ getBB bb+ -- | Calculate the direction vector between two positions direction :: (Positioned a, Positioned b) => a -> b -> RealPosition direction x y = (newX, newY)
+ src/HGE2D/QuadTree.hs view
@@ -0,0 +1,98 @@+module HGE2D.QuadTree where++import HGE2D.Datas+import HGE2D.Collision+import HGE2D.Geometry+import HGE2D.Classes++import Data.List++-- | A QuadTree for faster search queries+data (Positioned a) => QuadTree a = QuadEmpty   -- empty node+                                   | QuadLeaf a -- node with one position+                                   | QuadBranch (QuadTree a) (QuadTree a) (QuadTree a) (QuadTree a) BoundingBox -- branch which holds several subtrees++-- | Posibble directions within a branch (negative x && negative y | negative x && positive y ...)+data QuadDir = NN | NP | PN | PP++--------------------------------------------------------------------------------++---TODO can drop bb param?++-- | Builds a QuadTree from a list of elements with positions+--   The BoundingBox should be the BoundingBox of the elements+buildQuadTree :: (Positioned a) => BoundingBox -> [a] -> QuadTree a+buildQuadTree _ []    = QuadEmpty+buildQuadTree _ [x]   = QuadLeaf x+buildQuadTree bb xs   = QuadBranch nn np pn pp bb+  where+    nn = buildQuadTree bbnn $ filter isnn xs+    np = buildQuadTree bbnp $ filter isnp xs+    pn = buildQuadTree bbpn $ filter ispn xs+    pp = buildQuadTree bbpp $ filter ispp xs++    bbnn = bbFromList [center, (bbMin bb)]+    bbnp = bbFromList [center, (fst $ bbMin bb, snd $ bbMax bb)]+    bbpn = bbFromList [center, (fst $ bbMax bb, snd $ bbMin bb)]+    bbpp = bbFromList [center, (bbMax bb)]++    center = centerBB bb++    isnn x = getX x <= getX center  && getY x <= getY center+    isnp x = getX x <= getX center  && getY x >  getY center+    ispn x = getX x >  getX center  && getY x <= getY center+    ispp x = getX x >  getX center  && getY x >  getY center++--------------------------------------------------------------------------------++-- | Helper function to decide into which sub-node a position belongs+calcQuadDir :: (Positioned a) => a -> BoundingBox -> QuadDir+calcQuadDir p bb+  | (getX p) <  (getX $ centerBB bb)  && (getY p) <  (getY $ centerBB bb) = NN+  | (getX p) <  (getX $ centerBB bb)  && (getY p) >= (getY $ centerBB bb) = NP+  | (getX p) >= (getX $ centerBB bb)  && (getY p) <  (getY $ centerBB bb) = PN+  | otherwise                                                             = PP++--------------------------------------------------------------------------------++-- | Finds the nearest within the tree to the search position (if there is any)+nearestQuad :: (Positioned a, Positioned b) => a -> QuadTree b -> Maybe b+nearestQuad _ QuadEmpty       = Nothing+nearestQuad _ (QuadLeaf x)    = Just x+nearestQuad search (QuadBranch nn np pn pp bb) = foldResults best nodesToCheck+  where+    foldResults best []     = best+    foldResults best [x]    | mustCheck best x = minimumBy (\ a b -> compare (mayDist a) (mayDist b)) [best, nearestQuad search x]+                            | otherwise = best+    foldResults best (x:xs) = foldResults (foldResults best [x]) xs+++    nodesToCheck = case calcQuadDir search bb of+        NN -> [    np, pn, pp]+        NP -> [nn,     pn, pp]+        PN -> [nn, np,     pp]+        PP -> [nn, np, pn    ]+++    best = case calcQuadDir search bb of+        NN -> nearestQuad search nn+        NP -> nearestQuad search np+        PN -> nearestQuad search pn+        PP -> nearestQuad search pp++    ---TODO define these outside?+    mayDist p = case p of+        Nothing -> 1e300 ---TODO use double max+        Just x  -> distanceSqr search x++    mustCheck _ QuadEmpty                   = False+    mustCheck best (QuadLeaf x)             = distanceSqr search x < mayDist best+    mustCheck best (QuadBranch _ _ _ _ bb)  = isInsideRP search bb || distanceBBSqr search bb < mayDist best++--------------------------------------------------------------------------------++-- | Puts the elements of a QuadTree into a list+quadTreeToList :: (Positioned a) => QuadTree a -> [a]+quadTreeToList QuadEmpty = []+quadTreeToList (QuadLeaf x) = [x]+quadTreeToList (QuadBranch nn np pn pp _) = (quadTreeToList nn) ++ (quadTreeToList np) ++ (quadTreeToList pn) ++ (quadTreeToList pp)