From a502bf0a62c38a789c1325d6f1082d5ff2af612c Mon Sep 17 00:00:00 2001 From: Marc Sunet Date: Thu, 30 Aug 2012 19:32:58 +0200 Subject: Simplified collision interface --- Spear.cabal | 12 ++-- Spear.lkshs | 10 +-- Spear/Collision.hs | 159 +++++++++++++++++++++++++++++++++++++++-- Spear/Collision/Collision.hs | 80 --------------------- Spear/Collision/Collisioner.hs | 82 --------------------- Spear/Collision/Types.hs | 6 -- Spear/Math/QuadTree.hs | 2 +- Spear/Scene/GameObject.hs | 3 +- Spear/Scene/Loader.hs | 2 +- Spear/Scene/Scene.hs | 4 +- 10 files changed, 170 insertions(+), 190 deletions(-) delete mode 100644 Spear/Collision/Collision.hs delete mode 100644 Spear/Collision/Collisioner.hs delete mode 100644 Spear/Collision/Types.hs diff --git a/Spear.cabal b/Spear.cabal index bc9f429..a893ce3 100644 --- a/Spear.cabal +++ b/Spear.cabal @@ -19,13 +19,11 @@ library exposed-modules: Spear.Scene.GameObject Spear.Math.QuadTree Spear.Physics.Types Spear.App Spear.App.Application Spear.App.Input Spear.Assets.Image Spear.Assets.Model Spear.Collision - Spear.Math.AABB Spear.Collision.Collision - Spear.Collision.Collisioner Spear.Math.Circle Spear.Math.Triangle - Spear.Collision.Types Spear.Game Spear.GLSL Spear.Math.Camera - Spear.Math.Entity Spear.Math.Matrix3 Spear.Math.Matrix4 - Spear.Math.MatrixUtils Spear.Math.Plane Spear.Math.Quaternion - Spear.Math.Vector3 Spear.Math.Vector4 Spear.Physics - Spear.Physics.Rigid Spear.Render.AnimatedModel + Spear.Math.AABB Spear.Math.Circle Spear.Math.Triangle Spear.Game + Spear.GLSL Spear.Math.Camera Spear.Math.Entity Spear.Math.Matrix3 + Spear.Math.Matrix4 Spear.Math.MatrixUtils Spear.Math.Plane + Spear.Math.Quaternion Spear.Math.Vector3 Spear.Math.Vector4 + Spear.Physics Spear.Physics.Rigid Spear.Render.AnimatedModel Spear.Render.Material Spear.Render.Model Spear.Render.Program Spear.Render.StaticModel Spear.Render.Texture Spear.Scene.Graph Spear.Scene.Light Spear.Scene.Loader Spear.Scene.Scene diff --git a/Spear.lkshs b/Spear.lkshs index 38c6f2c..1f6f16e 100644 --- a/Spear.lkshs +++ b/Spear.lkshs @@ -1,18 +1,18 @@ Version of session file format: 1 Time of storage: - "Thu Aug 30 19:22:08 CEST 2012" -Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 2, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 357) 139)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 653) 954 -Population: [(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/GameObject.hs" 447)),[SplitP LeftP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs" 0)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Just (ModuleName ["Spear","Render","Renderable"]),Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0,6],[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Render/Program.hs" 248)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])] + "Thu Aug 30 19:32:45 CEST 2012" +Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 353) 140)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 653) 954 +Population: [(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Collision.hs" 3278)),[SplitP LeftP]),(Just (ErrorsSt ErrorsState),[SplitP RightP,SplitP TopP]),(Just (FilesSt FilesState),[SplitP RightP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/GameObject.hs" 402)),[SplitP LeftP]),(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Scene/Loader.hs" 296)),[SplitP LeftP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 328 (PackageScope False,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([[0]],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (BufferSt (BufferState "/home/jeanne/programming/haskell/Spear/Spear/Render/Program.hs" 248)),[SplitP LeftP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])] Window size: (1820,939) Completion size: (750,399) Workspace: Just "/home/jeanne/programming/haskell/Spear/Spear.lkshw" -Active pane: Just "Modules" +Active pane: Just "Collision.hs" Toolbar visible: True FindbarState: (False,FindState {entryStr = "", entryHist = ["VAO","'VAO'","\170","\\","^","scale","Vector4.","asdad","translv","Vector3.","Vector.","copy_tr"], replaceStr = "V3.", replaceHist = [], caseSensitive = True, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) Recently opened files: - ["/home/jeanne/programming/haskell/Spear/Spear/Updatable.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Texture.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/VAO.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Uniform.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Texture.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Management.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Buffer.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/Error.hs"] + ["/home/jeanne/programming/haskell/Spear/Spear/Math/QuadTree.hs","/home/jeanne/programming/haskell/Spear/Spear/Scene/Scene.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Types.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Collisioner.hs","/home/jeanne/programming/haskell/Spear/Spear/Collision/Collision.hs","/home/jeanne/programming/haskell/Spear/Spear/Updatable.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/main.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Utils.hs","/home/jeanne/programming/haskell/Spear/Spear/Render/Texture.hs","/home/jeanne/programming/haskell/Spear/demos/simple-scene/Game/GameObject/Player.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL.hs","/home/jeanne/programming/haskell/Spear/Spear/GLSL/VAO.hs"] Recently opened workspaces: ["/home/jeanne/programming/haskell/hagen/hagen.lkshw","/home/jeanne/programming/haskell/foo/foo.lkshw","/home/jeanne/programming/haskell/Spear/Spear.lkshw","/home/jeanne/programming/haskell/nexus/nexus.lkshw","/home/jeanne/leksah.lkshw"] \ No newline at end of file diff --git a/Spear/Collision.hs b/Spear/Collision.hs index 975f3cf..0dbebdb 100644 --- a/Spear/Collision.hs +++ b/Spear/Collision.hs @@ -1,10 +1,161 @@ module Spear.Collision ( - module Spear.Collision.Collision -, module Spear.Collision.Types + -- * Collision tests + CollisionType(..) +, Collisionable(..) + -- * Collisioners +, Collisioner(..) + -- ** Construction +, aabbCollisioner +, sphereCollisioner +, buildAABB + -- ** Collision test +, collide + -- ** Manipulation +, move + -- * Helpers +, aabbFromCircle ) where -import Spear.Collision.Collision -import Spear.Collision.Types +import Spear.Math.AABB +import Spear.Math.Circle +import Spear.Math.Plane +import Spear.Math.Vector2 + + +-- | Encodes several collision situations. +data CollisionType = NoCollision | Collision | FullyContains | FullyContainedBy + deriving (Eq, Show) + + +class Collisionable a where + collideBox :: AABB -> a -> CollisionType + collideSphere :: Circle -> a -> CollisionType + + +instance Collisionable AABB where + + collideBox box1@(AABB min1 max1) box2@(AABB min2 max2) + | min1 > max2 = NoCollision + | max1 < min2 = NoCollision + | box1 `aabbpt` min2 && box1 `aabbpt` max2 = FullyContains + | box2 `aabbpt` min1 && box2 `aabbpt` max1 = FullyContainedBy + | (x max1) < (x min2) = NoCollision + | (x min1) > (x max2) = NoCollision + | (y max1) < (y min2) = NoCollision + | (y min1) > (y max2) = NoCollision + | otherwise = Collision + + collideSphere sphere@(Circle c r) aabb@(AABB min max) + | test == FullyContains || test == FullyContainedBy = test + | normSq (c - boxC) > (l + r)^2 = NoCollision + | otherwise = Collision + where + test = aabb `collideBox` aabbFromCircle sphere + boxC = min + (max-min)/2 + l = norm $ min + (vec2 (x boxC) (y min)) - min + + + +instance Collisionable Circle where + + collideBox box sphere = case collideSphere sphere box of + FullyContains -> FullyContainedBy + FullyContainedBy -> FullyContains + x -> x + + collideSphere s1@(Circle c1 r1) s2@(Circle c2 r2) + | distance_centers <= sub_radii = if (r1 > r2) then FullyContains else FullyContainedBy + | distance_centers <= sum_radii = Collision + | otherwise = NoCollision + where + distance_centers = normSq $ c1 - c2 + sum_radii = (r1 + r2)^2 + sub_radii = (r1 - r2)^2 + + +aabbPoints :: AABB -> [Vector2] +aabbPoints (AABB min max) = [p1,p2,p3,p4,p5,p6,p7,p8] + where + p1 = vec2 (x min) (y min) + p2 = vec2 (x min) (y min) + p3 = vec2 (x min) (y max) + p4 = vec2 (x min) (y max) + p5 = vec2 (x max) (y min) + p6 = vec2 (x max) (y min) + p7 = vec2 (x max) (y max) + p8 = vec2 (x max) (y max) + + +-- | A collisioner component. +data Collisioner + -- | An axis-aligned bounding box. + = AABBCol { getBox :: {-# UNPACK #-} !AABB } + -- | A bounding sphere. + | CircleCol { getCircle :: {-# UNPACK #-} !Circle } + + +-- | Create a collisioner from the specified box. +aabbCollisioner :: AABB -> Collisioner +aabbCollisioner = AABBCol + + +-- | Create a collisioner from the specified circle. +sphereCollisioner :: Circle -> Collisioner +sphereCollisioner = CircleCol + + +-- | Create the minimal AABB fully containing the specified collisioners. +buildAABB :: [Collisioner] -> AABB +buildAABB cols = aabb $ generatePoints cols + + +-- | Create the minimal AABB collisioner fully containing the specified circle. +boxFromSphere :: Circle -> Collisioner +boxFromSphere = AABBCol . aabbFromCircle + + +generatePoints :: [Collisioner] -> [Vector2] +generatePoints = foldr generate [] + where + generate (AABBCol (AABB min max)) acc = p1:p2:p3:p4:p5:p6:p7:p8:acc + where + p1 = vec2 (x min) (y min) + p2 = vec2 (x min) (y min) + p3 = vec2 (x min) (y max) + p4 = vec2 (x min) (y max) + p5 = vec2 (x max) (y min) + p6 = vec2 (x max) (y min) + p7 = vec2 (x max) (y max) + p8 = vec2 (x max) (y max) + + generate (CircleCol (Circle c r)) acc = p1:p2:p3:p4:acc + where + p1 = c + unitx * (vec2 r r) + p2 = c - unitx * (vec2 r r) + p3 = c + unity * (vec2 r r) + p4 = c - unity * (vec2 r r) + + +-- | Collide the given collisioners. +collide :: Collisioner -> Collisioner -> CollisionType +collide (AABBCol box1) (AABBCol box2) = collideBox box1 box2 +collide (CircleCol s1) (CircleCol s2) = collideSphere s1 s2 +collide (AABBCol box) (CircleCol sphere) = collideBox box sphere +collide (CircleCol sphere) (AABBCol box) = collideSphere sphere box + + +-- | Move the collisioner. +move :: Vector2 -> Collisioner -> Collisioner +move v (AABBCol (AABB min max)) = AABBCol (AABB (min+v) (max+v)) +move v (CircleCol (Circle c r)) = CircleCol (Circle (c+v) r) + + +-- | Create the minimal box fully containing the specified circle. +aabbFromCircle :: Circle -> AABB +aabbFromCircle (Circle c r) = AABB bot top + where + bot = c - (vec2 r r) + top = c + (vec2 r r) diff --git a/Spear/Collision/Collision.hs b/Spear/Collision/Collision.hs deleted file mode 100644 index 60c2f03..0000000 --- a/Spear/Collision/Collision.hs +++ /dev/null @@ -1,80 +0,0 @@ -module Spear.Collision.Collision -( - Collisionable(..) -, aabbFromCircle -) -where - - -import Spear.Collision.Types -import Spear.Math.AABB -import Spear.Math.Circle -import Spear.Math.Plane -import Spear.Math.Vector2 - - -class Collisionable a where - collideBox :: AABB -> a -> CollisionType - collideSphere :: Circle -> a -> CollisionType - - -instance Collisionable AABB where - - collideBox box1@(AABB min1 max1) box2@(AABB min2 max2) - | min1 > max2 = NoCollision - | max1 < min2 = NoCollision - | box1 `aabbpt` min2 && box1 `aabbpt` max2 = FullyContains - | box2 `aabbpt` min1 && box2 `aabbpt` max1 = FullyContainedBy - | (x max1) < (x min2) = NoCollision - | (x min1) > (x max2) = NoCollision - | (y max1) < (y min2) = NoCollision - | (y min1) > (y max2) = NoCollision - | otherwise = Collision - - collideSphere sphere@(Circle c r) aabb@(AABB min max) - | test == FullyContains || test == FullyContainedBy = test - | normSq (c - boxC) > (l + r)^2 = NoCollision - | otherwise = Collision - where - test = aabb `collideBox` aabbFromCircle sphere - boxC = min + (max-min)/2 - l = norm $ min + (vec2 (x boxC) (y min)) - min - - - -instance Collisionable Circle where - - collideBox box sphere = case collideSphere sphere box of - FullyContains -> FullyContainedBy - FullyContainedBy -> FullyContains - x -> x - - collideSphere s1@(Circle c1 r1) s2@(Circle c2 r2) - | distance_centers <= sub_radii = if (r1 > r2) then FullyContains else FullyContainedBy - | distance_centers <= sum_radii = Collision - | otherwise = NoCollision - where - distance_centers = normSq $ c1 - c2 - sum_radii = (r1 + r2)^2 - sub_radii = (r1 - r2)^2 - - -aabbPoints :: AABB -> [Vector2] -aabbPoints (AABB min max) = [p1,p2,p3,p4,p5,p6,p7,p8] - where - p1 = vec2 (x min) (y min) - p2 = vec2 (x min) (y min) - p3 = vec2 (x min) (y max) - p4 = vec2 (x min) (y max) - p5 = vec2 (x max) (y min) - p6 = vec2 (x max) (y min) - p7 = vec2 (x max) (y max) - p8 = vec2 (x max) (y max) - - --- | Create the minimal box fully containing the specified circle. -aabbFromCircle :: Circle -> AABB -aabbFromCircle (Circle c r) = AABB bot top - where - bot = c - (vec2 r r) - top = c + (vec2 r r) diff --git a/Spear/Collision/Collisioner.hs b/Spear/Collision/Collisioner.hs deleted file mode 100644 index dd41d61..0000000 --- a/Spear/Collision/Collisioner.hs +++ /dev/null @@ -1,82 +0,0 @@ -module Spear.Collision.Collisioner -( - Collisioner(..) -, CollisionType(..) -, aabbCollisioner -, sphereCollisioner -, buildAABB -, collide -, move -) -where - - -import Spear.Collision.Collision as C -import Spear.Collision.Types -import Spear.Math.AABB -import Spear.Math.Circle -import Spear.Math.Vector2 - - --- | A collisioner component. -data Collisioner - -- | An axis-aligned bounding box. - = AABBCol { getBox :: {-# UNPACK #-} !AABB } - -- | A bounding sphere. - | CircleCol { getCircle :: {-# UNPACK #-} !Circle } - - --- | Create a 'Collisioner' from the specified box. -aabbCollisioner :: AABB -> Collisioner -aabbCollisioner = AABBCol - - --- | Create a 'Collisioner' from the specified circle. -sphereCollisioner :: Circle -> Collisioner -sphereCollisioner = CircleCol - - --- | Create the minimal 'AABB' fully containing the specified collisioners. -buildAABB :: [Collisioner] -> AABB -buildAABB cols = aabb $ generatePoints cols - - --- | Create the minimal 'AABB' collisioner fully containing the specified circle. -boxFromSphere :: Circle -> Collisioner -boxFromSphere = AABBCol . aabbFromCircle - - -generatePoints :: [Collisioner] -> [Vector2] -generatePoints = foldr generate [] - where - generate (AABBCol (AABB min max)) acc = p1:p2:p3:p4:p5:p6:p7:p8:acc - where - p1 = vec2 (x min) (y min) - p2 = vec2 (x min) (y min) - p3 = vec2 (x min) (y max) - p4 = vec2 (x min) (y max) - p5 = vec2 (x max) (y min) - p6 = vec2 (x max) (y min) - p7 = vec2 (x max) (y max) - p8 = vec2 (x max) (y max) - - generate (CircleCol (Circle c r)) acc = p1:p2:p3:p4:acc - where - p1 = c + unitx * (vec2 r r) - p2 = c - unitx * (vec2 r r) - p3 = c + unity * (vec2 r r) - p4 = c - unity * (vec2 r r) - - --- | Collide the given collisioners. -collide :: Collisioner -> Collisioner -> CollisionType -collide (AABBCol box1) (AABBCol box2) = collideBox box1 box2 -collide (CircleCol s1) (CircleCol s2) = collideSphere s1 s2 -collide (AABBCol box) (CircleCol sphere) = collideBox box sphere -collide (CircleCol sphere) (AABBCol box) = collideSphere sphere box - - --- | Move the collisioner. -move :: Vector2 -> Collisioner -> Collisioner -move v (AABBCol (AABB min max)) = AABBCol (AABB (min+v) (max+v)) -move v (CircleCol (Circle c r)) = CircleCol (Circle (c+v) r) diff --git a/Spear/Collision/Types.hs b/Spear/Collision/Types.hs deleted file mode 100644 index 61b224f..0000000 --- a/Spear/Collision/Types.hs +++ /dev/null @@ -1,6 +0,0 @@ -module Spear.Collision.Types -where - --- | Encodes several collision situations. -data CollisionType = NoCollision | Collision | FullyContains | FullyContainedBy - deriving (Eq, Show) diff --git a/Spear/Math/QuadTree.hs b/Spear/Math/QuadTree.hs index 2e92265..e553c88 100644 --- a/Spear/Math/QuadTree.hs +++ b/Spear/Math/QuadTree.hs @@ -9,7 +9,7 @@ module Spear.Math.QuadTree ) where -import Spear.Collision.Types +import Spear.Collision import Spear.Math.AABB import Spear.Math.Vector2 diff --git a/Spear/Scene/GameObject.hs b/Spear/Scene/GameObject.hs index cfc825d..9886f35 100644 --- a/Spear/Scene/GameObject.hs +++ b/Spear/Scene/GameObject.hs @@ -23,8 +23,7 @@ module Spear.Scene.GameObject where -import Spear.Collision.Collision -import Spear.Collision.Collisioner as Col +import Spear.Collision as Col import Spear.GLSL import Spear.Math.AABB import qualified Spear.Math.Camera as Cam diff --git a/Spear/Scene/Loader.hs b/Spear/Scene/Loader.hs index 081b927..820ad51 100644 --- a/Spear/Scene/Loader.hs +++ b/Spear/Scene/Loader.hs @@ -19,7 +19,7 @@ where import Spear.Assets.Model as Model -import Spear.Collision.Collisioner +import Spear.Collision import qualified Spear.GLSL as GLSL import Spear.Math.Matrix3 as M3 import Spear.Math.Matrix4 as M4 diff --git a/Spear/Scene/Scene.hs b/Spear/Scene/Scene.hs index 0dfa459..b8366f3 100644 --- a/Spear/Scene/Scene.hs +++ b/Spear/Scene/Scene.hs @@ -13,14 +13,14 @@ module Spear.Scene.Scene -- * Update and render , update , updateM -, collide +, Spear.Scene.Scene.collide , collideM , render ) where -import Spear.Collision.Types +import Spear.Collision import Spear.Game (Game) import Spear.Math.AABB import Spear.Math.QuadTree as QT -- cgit v1.2.3