aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Spear.lkshw2
-rw-r--r--Spear/Collision/Collisioner.hs15
-rw-r--r--Spear/Math/Entity.hs1
-rw-r--r--Spear/Math/Spatial2.hs5
-rw-r--r--Spear/Physics/Rigid.hs2
-rw-r--r--Spear/Scene/GameObject.hs197
6 files changed, 169 insertions, 53 deletions
diff --git a/Spear.lkshw b/Spear.lkshw
index 142cfb0..d448954 100644
--- a/Spear.lkshw
+++ b/Spear.lkshw
@@ -1,7 +1,7 @@
1Version of workspace file format: 1Version of workspace file format:
2 1 2 1
3Time of storage: 3Time of storage:
4 "Tue Aug 28 22:48:22 CEST 2012" 4 "Wed Aug 29 11:39:26 CEST 2012"
5Name of the workspace: 5Name of the workspace:
6 "Spear" 6 "Spear"
7File paths of contained packages: 7File paths of contained packages:
diff --git a/Spear/Collision/Collisioner.hs b/Spear/Collision/Collisioner.hs
index 19114e6..dd41d61 100644
--- a/Spear/Collision/Collisioner.hs
+++ b/Spear/Collision/Collisioner.hs
@@ -5,7 +5,8 @@ module Spear.Collision.Collisioner
5, aabbCollisioner 5, aabbCollisioner
6, sphereCollisioner 6, sphereCollisioner
7, buildAABB 7, buildAABB
8, collide 8, collide
9, move
9) 10)
10where 11where
11 12
@@ -20,9 +21,9 @@ import Spear.Math.Vector2
20-- | A collisioner component. 21-- | A collisioner component.
21data Collisioner 22data Collisioner
22 -- | An axis-aligned bounding box. 23 -- | An axis-aligned bounding box.
23 = AABBCol { getBox :: !AABB } 24 = AABBCol { getBox :: {-# UNPACK #-} !AABB }
24 -- | A bounding sphere. 25 -- | A bounding sphere.
25 | CircleCol { getSphere :: !Circle } 26 | CircleCol { getCircle :: {-# UNPACK #-} !Circle }
26 27
27 28
28-- | Create a 'Collisioner' from the specified box. 29-- | Create a 'Collisioner' from the specified box.
@@ -42,7 +43,7 @@ buildAABB cols = aabb $ generatePoints cols
42 43
43-- | Create the minimal 'AABB' collisioner fully containing the specified circle. 44-- | Create the minimal 'AABB' collisioner fully containing the specified circle.
44boxFromSphere :: Circle -> Collisioner 45boxFromSphere :: Circle -> Collisioner
45boxFromSphere = AABBCol . aabbFromCircle 46boxFromSphere = AABBCol . aabbFromCircle
46 47
47 48
48generatePoints :: [Collisioner] -> [Vector2] 49generatePoints :: [Collisioner] -> [Vector2]
@@ -73,3 +74,9 @@ collide (AABBCol box1) (AABBCol box2) = collideBox box1 box2
73collide (CircleCol s1) (CircleCol s2) = collideSphere s1 s2 74collide (CircleCol s1) (CircleCol s2) = collideSphere s1 s2
74collide (AABBCol box) (CircleCol sphere) = collideBox box sphere 75collide (AABBCol box) (CircleCol sphere) = collideBox box sphere
75collide (CircleCol sphere) (AABBCol box) = collideSphere sphere box 76collide (CircleCol sphere) (AABBCol box) = collideSphere sphere box
77
78
79-- | Move the collisioner.
80move :: Vector2 -> Collisioner -> Collisioner
81move v (AABBCol (AABB min max)) = AABBCol (AABB (min+v) (max+v))
82move v (CircleCol (Circle c r)) = CircleCol (Circle (c+v) r)
diff --git a/Spear/Math/Entity.hs b/Spear/Math/Entity.hs
index 022868b..f4e6515 100644
--- a/Spear/Math/Entity.hs
+++ b/Spear/Math/Entity.hs
@@ -23,6 +23,7 @@ instance S.Spatial2 Entity where
23 rotate a ent = ent { transform = transform ent * M.rot a } 23 rotate a ent = ent { transform = transform ent * M.rot a }
24 pos = M.position . transform 24 pos = M.position . transform
25 fwd = M.forward . transform 25 fwd = M.forward . transform
26 up = M.up . transform
26 right = M.right . transform 27 right = M.right . transform
27 transform (Entity t) = t 28 transform (Entity t) = t
28 setTransform t (Entity _) = Entity t 29 setTransform t (Entity _) = Entity t
diff --git a/Spear/Math/Spatial2.hs b/Spear/Math/Spatial2.hs
index 3c60412..51fa050 100644
--- a/Spear/Math/Spatial2.hs
+++ b/Spear/Math/Spatial2.hs
@@ -32,7 +32,10 @@ class Spatial2 s where
32 32
33 -- | Get the spatial's forward vector. 33 -- | Get the spatial's forward vector.
34 fwd :: s -> Vector2 34 fwd :: s -> Vector2
35 35
36 -- | Get the spatial's up vector.
37 up :: s -> Vector2
38
36 -- | Get the spatial's right vector. 39 -- | Get the spatial's right vector.
37 right :: s -> Vector2 40 right :: s -> Vector2
38 41
diff --git a/Spear/Physics/Rigid.hs b/Spear/Physics/Rigid.hs
index 396cae4..cc153ec 100644
--- a/Spear/Physics/Rigid.hs
+++ b/Spear/Physics/Rigid.hs
@@ -45,6 +45,8 @@ instance Spatial2 RigidBody where
45 45
46 fwd _ = unity 46 fwd _ = unity
47 47
48 up _ = unity
49
48 right _ = unitx 50 right _ = unitx
49 51
50 transform body = M3.transform unitx unity $ position body 52 transform body = M3.transform unitx unity $ position body
diff --git a/Spear/Scene/GameObject.hs b/Spear/Scene/GameObject.hs
index be1c050..1d5fed2 100644
--- a/Spear/Scene/GameObject.hs
+++ b/Spear/Scene/GameObject.hs
@@ -1,24 +1,30 @@
1module Spear.Scene.GameObject 1module Spear.Scene.GameObject
2( 2(
3 GameObject 3 GameObject
4, CollideGO
5, UpdateGO
6 -- * Construction 4 -- * Construction
7, goNew 5, goNew
8 -- * Accessors
9, goData
10 -- * Manipulation 6 -- * Manipulation
11, goUpdate 7, goUpdate
12, withGO 8, goAABB
13 -- * Rendering 9 -- * Rendering
14, goRender 10, goRender
11 -- * Collision
12, goCollide
15) 13)
16where 14where
17 15
18 16
19import Spear.Collision.Collision 17import Spear.Collision.Collision
20import Spear.Collision.Collisioner 18import Spear.Collision.Collisioner as Col
19import Spear.GLSL.Uniform
21import Spear.Math.AABB 20import Spear.Math.AABB
21import qualified Spear.Math.Camera as Cam
22import qualified Spear.Math.Matrix3 as M3
23import qualified Spear.Math.Matrix4 as M4
24import Spear.Math.MatrixUtils
25import qualified Spear.Math.Spatial2 as S2
26import Spear.Math.Vector2 as V2
27import Spear.Math.Vector3 as V3
22import Spear.Render.AnimatedModel as AM 28import Spear.Render.AnimatedModel as AM
23import Spear.Render.Program 29import Spear.Render.Program
24import Spear.Render.StaticModel as SM 30import Spear.Render.StaticModel as SM
@@ -26,64 +32,161 @@ import Spear.Render.StaticModel as SM
26import Data.List (foldl') 32import Data.List (foldl')
27 33
28 34
29-- | Collide a game object. 35-- | Game style.
30type CollideGO a 36data GameStyle
31 = GameObject a -- ^ Collider 37 = RPG -- ^ RPG or RTS style game.
32 -> GameObject a -- ^ Old game object 38 | PLT -- ^ Platformer or space invaders style game.
33 -> GameObject a -- ^ New game object
34
35-- | Update a game object.
36type UpdateGO a = Float -> GameObject a -> GameObject a
37 39
38 40
39-- | An object in the game scene. 41-- | An object in the game scene.
40data GameObject a = GameObject 42data GameObject = GameObject
41 { renderer :: !(Either StaticModelRenderer AnimatedModelRenderer) 43 { gameStyle :: GameStyle
44 , renderer :: !(Either StaticModelRenderer AnimatedModelRenderer)
42 , collisioner :: !Collisioner 45 , collisioner :: !Collisioner
43 , goData :: !a 46 , transform :: M3.Matrix3
44 , goUpdt :: UpdateGO a 47 , goUpdate :: Float -> GameObject
45 , goCol :: CollideGO a
46 } 48 }
47 49
48 50
49-- | Create a new game object. 51instance S2.Spatial2 GameObject where
50goNew :: Either StaticModelResource AnimatedModelResource 52
51 -> Collisioner -> a -> UpdateGO a -> CollideGO a -> GameObject a 53 move v go = go
52 54 { collisioner = Col.move v $ collisioner go
53goNew (Left smr) = GameObject (Left $ staticModelRenderer smr) 55 , transform = M3.translv v * transform go
54goNew (Right amr) = GameObject (Right $ animatedModelRenderer amr) 56 }
55 57
56 58 moveFwd s go =
57-- | Render the game object. 59 let m = transform go
58goRender :: StaticProgramUniforms -> AnimatedProgramUniforms -> GameObject a -> IO () 60 v = V2.scale s $ M3.forward m
59goRender spu apu go = 61 in go
60 case renderer go of 62 { collisioner = Col.move v $ collisioner go
61 Left smr -> SM.render spu smr 63 , transform = M3.translv v * m
62 Right amr -> AM.render apu amr 64 }
65
66 moveBack s go =
67 let m = transform go
68 v = V2.scale (-s) $ M3.forward m
69 in go
70 { collisioner = Col.move v $ collisioner go
71 , transform = M3.translv v * m
72 }
73
74 strafeLeft s go =
75 let m = transform go
76 v = V2.scale (-s) $ M3.right m
77 in go
78 { collisioner = Col.move v $ collisioner go
79 , transform = M3.translv v * m
80 }
81
82 strafeRight s go =
83 let m = transform go
84 v = V2.scale s $ M3.right m
85 in go
86 { collisioner = Col.move v $ collisioner go
87 , transform = M3.translv v * m
88 }
89
90 rotate angle go = go { transform = transform go * M3.rot angle }
91
92 pos go = M3.position . transform $ go
93
94 fwd go = M3.forward . transform $ go
95
96 up go = M3.up . transform $ go
97
98 right go = M3.right . transform $ go
99
100 transform go = Spear.Scene.GameObject.transform go
101
102 setTransform mat go = go { transform = mat }
103
104 setPos pos go =
105 let m = transform go
106 in go { transform = M3.transform (M3.right m) (M3.forward m) pos }
63 107
64 108
65-- | Update the game object. 109-- | Create a new game object.
66goUpdate :: Float -> GameObject a -> GameObject a 110goNew :: GameStyle
67goUpdate dt go = 111 -> Either StaticModelResource AnimatedModelResource
68 case renderer go of 112 -> Collisioner
69 Left smr -> goUpdt go dt $ go 113 -> GameObject
70 Right amr -> goUpdt go dt $ go { renderer = Right $ AM.update dt amr } 114
115goNew style (Left smr) col =
116 goUpdate' style (Left $ SM.staticModelRenderer smr) col M3.id 0
117
118goNew style (Right amr) col =
119 goUpdate' style (Right $ AM.animatedModelRenderer amr) col M3.id 0
120
121
122goUpdate' :: GameStyle
123 -> Either StaticModelRenderer AnimatedModelRenderer
124 -> Collisioner
125 -> M3.Matrix3
126 -> Float
127 -> GameObject
128goUpdate' style rend col mat dt =
129 let rend' = case rend of
130 Left _ -> rend
131 Right amr -> Right $ AM.update dt amr
132 in
133 GameObject
134 { gameStyle = style
135 , renderer = rend
136 , collisioner = col
137 , transform = mat
138 , goUpdate = goUpdate' style rend' col mat
139 }
71 140
72 141
73-- | Apply the given function to the game object's data. 142-- | Render the game object.
74withGO :: GameObject a -> (a -> a) -> GameObject a 143goRender :: StaticProgram -> AnimatedProgram -> Cam.Camera -> GameObject -> IO ()
75withGO go f = go { goData = f $ goData go } 144goRender sprog aprog cam go =
145 let spu = staticProgramUniforms sprog
146 apu = animatedProgramUniforms aprog
147 mat = S2.transform go
148 style = gameStyle go
149 in case renderer go of
150 Left smr -> goRender' style spu mat cam (SM.bind spu smr) (SM.render spu smr)
151 Right amr -> goRender' style apu mat cam (AM.bind apu amr) (AM.render apu amr)
152
153
154type Bind = IO ()
155
156type Render = IO ()
157
158
159goRender' :: ProgramUniforms u
160 => GameStyle
161 -> u
162 -> M3.Matrix3
163 -> Cam.Camera
164 -> Bind
165 -> Render
166 -> IO ()
167goRender' style uniforms model cam bindRenderer render =
168 let view = M4.inverseTransform $ Cam.transform cam
169 modelview = case style of
170 RPG -> view * rpgTransform 0 model
171 PLT -> view * pltTransform model
172 normalmat = fastNormalMatrix modelview
173 in do
174 uniformMat4 (projLoc uniforms) $ Cam.projection cam
175 uniformMat4 (modelviewLoc uniforms) modelview
176 uniformMat3 (normalmatLoc uniforms) normalmat
177 bindRenderer
178 render
76 179
77 180
78-- | Collide the game object with the given list of game objects. 181-- | Collide the game object with the given list of game objects.
79goCollide :: [GameObject a] -> GameObject a -> GameObject a 182goCollide :: [GameObject] -> GameObject -> [GameObject]
80goCollide gos go = foldl' collide' go gos 183goCollide gos go = foldl' collide' [] gos
81 where 184 where
82 collide' go1 go2 = goCol go1 go2 go1 185 collide' gos target = target:gos
83 186
84 187
85-- | Get the object's bounding box. 188-- | Get the game object's bounding box.
86goAABB :: GameObject a -> AABB 189goAABB :: GameObject -> AABB
87goAABB go = 190goAABB go =
88 case collisioner go of 191 case collisioner go of
89 (AABBCol box) -> box 192 (AABBCol box) -> box