diff options
author | 3gg <3gg@shellblade.net> | 2023-08-23 08:47:16 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2023-08-23 08:47:16 -0700 |
commit | 5a395dbb9491cee0a921553b331923d492a16fc4 (patch) | |
tree | 0269494df7669a676cbfe3d60f6fe72a4c4ecbcb | |
parent | 9fc42bcc1b35cb337016e88f4b1969b6e3baafdf (diff) |
Better physics and Vector class rename.
-rw-r--r-- | Demos/Pong/Pong.hs | 59 | ||||
-rw-r--r-- | Spear.cabal | 2 | ||||
-rw-r--r-- | Spear/Math/Vector.hs | 12 | ||||
-rw-r--r-- | Spear/Math/Vector/Vector.hs (renamed from Spear/Math/Vector/Class.hs) | 20 | ||||
-rw-r--r-- | Spear/Math/Vector/Vector2.hs | 16 | ||||
-rw-r--r-- | Spear/Math/Vector/Vector3.hs | 8 | ||||
-rw-r--r-- | Spear/Math/Vector/Vector4.hs | 8 | ||||
-rw-r--r-- | Spear/Window.hs | 1 |
8 files changed, 67 insertions, 59 deletions
diff --git a/Demos/Pong/Pong.hs b/Demos/Pong/Pong.hs index fd7fbeb..0e24a42 100644 --- a/Demos/Pong/Pong.hs +++ b/Demos/Pong/Pong.hs | |||
@@ -16,18 +16,15 @@ import Spear.Step | |||
16 | 16 | ||
17 | -- Configuration | 17 | -- Configuration |
18 | 18 | ||
19 | padSize = vec2 0.05 0.02 | 19 | padSize = vec2 0.07 0.02 |
20 | 20 | ballSize = 0.012 | |
21 | ballSize = 0.01 | 21 | ballSpeed = 0.6 |
22 | 22 | initialBallVelocity = vec2 1 1 | |
23 | ballVelocity = vec2 0.3 0.3 | 23 | maxBounceAngle = 65 * pi/180 |
24 | 24 | playerSpeed = 1.0 | |
25 | playerSpeed = 0.7 | 25 | enemySpeed = 1.5 |
26 | |||
27 | initialEnemyPos = vec2 0.5 0.9 | 26 | initialEnemyPos = vec2 0.5 0.9 |
28 | |||
29 | initialPlayerPos = vec2 0.5 0.1 | 27 | initialPlayerPos = vec2 0.5 0.1 |
30 | |||
31 | initialBallPos = vec2 0.5 0.5 | 28 | initialBallPos = vec2 0.5 0.5 |
32 | 29 | ||
33 | -- Game events | 30 | -- Game events |
@@ -66,7 +63,7 @@ padBox = AABB2 (-padSize) padSize | |||
66 | obj2 = obj2FromVectors unitx2 unity2 | 63 | obj2 = obj2FromVectors unitx2 unity2 |
67 | 64 | ||
68 | newWorld = | 65 | newWorld = |
69 | [ GameObject ballBox (obj2 initialBallPos) $ stepBall ballVelocity, | 66 | [ GameObject ballBox (obj2 initialBallPos) $ stepBall initialBallVelocity, |
70 | GameObject padBox (obj2 initialEnemyPos) stepEnemy, | 67 | GameObject padBox (obj2 initialEnemyPos) stepEnemy, |
71 | GameObject padBox (obj2 initialPlayerPos) stepPlayer | 68 | GameObject padBox (obj2 initialPlayerPos) stepPlayer |
72 | ] | 69 | ] |
@@ -75,19 +72,37 @@ newWorld = | |||
75 | 72 | ||
76 | stepBall vel = collideBall vel .> moveBall | 73 | stepBall vel = collideBall vel .> moveBall |
77 | 74 | ||
75 | -- TODO: in collideBall and paddleBounce, we should an apply an offset to the | ||
76 | -- ball when collision is detected. | ||
78 | collideBall :: Vector2 -> Step [GameObject] e GameObject (Vector2, GameObject) | 77 | collideBall :: Vector2 -> Step [GameObject] e GameObject (Vector2, GameObject) |
79 | collideBall vel = step $ \_ dt gos _ ball -> | 78 | collideBall vel = step $ \_ dt gos _ ball -> |
80 | let (AABB2 pmin pmax) = aabb ball `aabbAdd` pos ball | 79 | let (AABB2 pmin pmax) = aabb ball `aabbAdd` pos ball |
81 | collideCol = x pmin < 0 || x pmax > 1 | 80 | collideSide = x pmin < 0 || x pmax > 1 |
82 | collideRow = y pmin < 0 || y pmax > 1 || any (collide ball) (tail gos) | 81 | collideBack = y pmin < 0 || y pmax > 1 |
83 | negx v@(Vector2 x y) = if collideCol then vec2 (-x) y else v | 82 | collidePaddle = any (collide ball) (tail gos) |
84 | negy v@(Vector2 x y) = if collideRow then vec2 x (-y) else v | 83 | flipX v@(Vector2 x y) = if collideSide then vec2 (-x) y else v |
85 | vel' = negx . negy $ vel | 84 | flipY v@(Vector2 x y) = if collideBack then vec2 x (-y) else v |
86 | delta = dt -- A small delta to apply when collision occurs. | 85 | vel' = normalise . (\v -> foldl (paddleBounce ball) v (tail gos)) . flipX . flipY $ vel |
87 | adjustX = if collideCol then scale delta (vec2 (x vel) 0) else vec2 0 0 | 86 | -- A small delta to apply when collision occurs. |
88 | adjustY = if collideRow then scale delta (vec2 0 (y vel)) else vec2 0 0 | 87 | delta = 1 + if collideSide || collideBack || collidePaddle then 2*dt else 0 |
89 | in ((vel' + adjustX + adjustY, ball), collideBall vel') | 88 | in ((scale ballSpeed (scale delta vel'), ball), collideBall vel') |
90 | 89 | ||
90 | paddleBounce :: GameObject -> Vector2 -> GameObject -> Vector2 | ||
91 | paddleBounce ball v paddle = | ||
92 | if collide ball paddle | ||
93 | then | ||
94 | let (AABB2 pmin pmax) = aabb paddle `aabbAdd` pos paddle | ||
95 | center = (x pmin + x pmax) / 2 | ||
96 | -- Normalized offset of the ball from the paddle's center, [-1, +1]. | ||
97 | -- It's outside the [-1, +1] range if there is no collision. | ||
98 | offset = (x (pos ball) - center) / ((x pmax - x pmin) / 2) | ||
99 | angle = offset * maxBounceAngle | ||
100 | -- When it bounces off of a paddle, y vel is flipped. | ||
101 | ysign = -(signum (y v)) | ||
102 | in vec2 (sin angle) (ysign * cos angle) | ||
103 | else v | ||
104 | |||
105 | collide :: GameObject -> GameObject -> Bool | ||
91 | collide go1 go2 = | 106 | collide go1 go2 = |
92 | let (AABB2 (Vector2 xmin1 ymin1) (Vector2 xmax1 ymax1)) = | 107 | let (AABB2 (Vector2 xmin1 ymin1) (Vector2 xmax1 ymax1)) = |
93 | aabb go1 `aabbAdd` pos go1 | 108 | aabb go1 `aabbAdd` pos go1 |
@@ -112,7 +127,7 @@ movePad :: Step s e GameObject GameObject | |||
112 | movePad = step $ \elapsed _ _ _ pad -> | 127 | movePad = step $ \elapsed _ _ _ pad -> |
113 | let p = vec2 px 0.9 | 128 | let p = vec2 px 0.9 |
114 | px = | 129 | px = |
115 | double2Float (sin elapsed * 0.5 + 0.5) | 130 | double2Float (sin (elapsed * enemySpeed) * 0.5 + 0.5) |
116 | * (1 - 2 * x padSize) | 131 | * (1 - 2 * x padSize) |
117 | + x padSize | 132 | + x padSize |
118 | in (setPos p pad, movePad) | 133 | in (setPos p pad, movePad) |
diff --git a/Spear.cabal b/Spear.cabal index 824f352..7025fcd 100644 --- a/Spear.cabal +++ b/Spear.cabal | |||
@@ -52,7 +52,7 @@ library | |||
52 | Spear.Math.Triangle | 52 | Spear.Math.Triangle |
53 | Spear.Math.Utils | 53 | Spear.Math.Utils |
54 | Spear.Math.Vector | 54 | Spear.Math.Vector |
55 | Spear.Math.Vector.Class | 55 | Spear.Math.Vector.Vector |
56 | Spear.Math.Vector.Vector2 | 56 | Spear.Math.Vector.Vector2 |
57 | Spear.Math.Vector.Vector3 | 57 | Spear.Math.Vector.Vector3 |
58 | Spear.Math.Vector.Vector4 | 58 | Spear.Math.Vector.Vector4 |
diff --git a/Spear/Math/Vector.hs b/Spear/Math/Vector.hs index dd5e496..b43f7ec 100644 --- a/Spear/Math/Vector.hs +++ b/Spear/Math/Vector.hs | |||
@@ -1,13 +1,13 @@ | |||
1 | module Spear.Math.Vector | 1 | module Spear.Math.Vector |
2 | ( | 2 | ( |
3 | module Spear.Math.Vector.Vector2 | 3 | module Spear.Math.Vector.Vector |
4 | , module Spear.Math.Vector.Vector2 | ||
4 | , module Spear.Math.Vector.Vector3 | 5 | , module Spear.Math.Vector.Vector3 |
5 | , module Spear.Math.Vector.Vector4 | 6 | , module Spear.Math.Vector.Vector4 |
6 | , module Spear.Math.Vector.Class | ||
7 | ) | 7 | ) |
8 | where | 8 | where |
9 | 9 | ||
10 | import Spear.Math.Vector.Vector2 | 10 | import Spear.Math.Vector.Vector |
11 | import Spear.Math.Vector.Vector3 | 11 | import Spear.Math.Vector.Vector2 |
12 | import Spear.Math.Vector.Vector4 | 12 | import Spear.Math.Vector.Vector3 |
13 | import Spear.Math.Vector.Class | 13 | import Spear.Math.Vector.Vector4 |
diff --git a/Spear/Math/Vector/Class.hs b/Spear/Math/Vector/Vector.hs index 19ddfac..35b04e2 100644 --- a/Spear/Math/Vector/Class.hs +++ b/Spear/Math/Vector/Vector.hs | |||
@@ -1,10 +1,10 @@ | |||
1 | module Spear.Math.Vector.Class | 1 | module Spear.Math.Vector.Vector |
2 | where | 2 | where |
3 | 3 | ||
4 | class (Fractional a, Ord a) => VectorClass a where | 4 | class (Fractional a, Ord a) => Vector a where |
5 | -- | Create a vector from the given list. | 5 | -- | Create a vector from the given list. |
6 | fromList :: [Float] -> a | 6 | fromList :: [Float] -> a |
7 | 7 | ||
8 | -- | Return the vector's x coordinate. | 8 | -- | Return the vector's x coordinate. |
9 | x :: a -> Float | 9 | x :: a -> Float |
10 | x _ = 0 | 10 | x _ = 0 |
@@ -23,21 +23,21 @@ class (Fractional a, Ord a) => VectorClass a where | |||
23 | 23 | ||
24 | -- | Return the vector's ith coordinate. | 24 | -- | Return the vector's ith coordinate. |
25 | (!) :: a -> Int -> Float | 25 | (!) :: a -> Int -> Float |
26 | 26 | ||
27 | -- | Compute the given vectors' dot product. | 27 | -- | Compute the given vectors' dot product. |
28 | dot :: a -> a -> Float | 28 | dot :: a -> a -> Float |
29 | 29 | ||
30 | -- | Compute the given vector's squared norm. | 30 | -- | Compute the given vector's squared norm. |
31 | normSq :: a -> Float | 31 | normSq :: a -> Float |
32 | 32 | ||
33 | -- | Compute the given vector's norm. | 33 | -- | Compute the given vector's norm. |
34 | norm :: a -> Float | 34 | norm :: a -> Float |
35 | 35 | ||
36 | -- | Multiply the given vector with the given scalar. | 36 | -- | Multiply the given vector with the given scalar. |
37 | scale :: Float -> a -> a | 37 | scale :: Float -> a -> a |
38 | 38 | ||
39 | -- | Negate the given vector. | 39 | -- | Negate the given vector. |
40 | neg :: a -> a | 40 | neg :: a -> a |
41 | 41 | ||
42 | -- | Normalise the given vector. | 42 | -- | Normalise the given vector. |
43 | normalise :: a -> a \ No newline at end of file | 43 | normalise :: a -> a |
diff --git a/Spear/Math/Vector/Vector2.hs b/Spear/Math/Vector/Vector2.hs index dfb4fb9..5bbb632 100644 --- a/Spear/Math/Vector/Vector2.hs +++ b/Spear/Math/Vector/Vector2.hs | |||
@@ -14,10 +14,10 @@ module Spear.Math.Vector.Vector2 | |||
14 | ) | 14 | ) |
15 | where | 15 | where |
16 | 16 | ||
17 | import Spear.Math.Vector.Class | 17 | import Spear.Math.Vector.Vector |
18 | 18 | ||
19 | import Foreign.C.Types (CFloat) | 19 | import Foreign.C.Types (CFloat) |
20 | import Foreign.Storable | 20 | import Foreign.Storable |
21 | 21 | ||
22 | type Right2 = Vector2 | 22 | type Right2 = Vector2 |
23 | type Up2 = Vector2 | 23 | type Up2 = Vector2 |
@@ -50,7 +50,7 @@ instance Ord Vector2 where | |||
50 | min (Vector2 ax ay) (Vector2 bx by) = Vector2 (Prelude.min ax bx) (Prelude.min ay by) | 50 | min (Vector2 ax ay) (Vector2 bx by) = Vector2 (Prelude.min ax bx) (Prelude.min ay by) |
51 | 51 | ||
52 | 52 | ||
53 | instance VectorClass Vector2 where | 53 | instance Vector Vector2 where |
54 | {-# INLINABLE fromList #-} | 54 | {-# INLINABLE fromList #-} |
55 | fromList (ax:ay:_) = Vector2 ax ay | 55 | fromList (ax:ay:_) = Vector2 ax ay |
56 | 56 | ||
@@ -104,27 +104,19 @@ instance Storable Vector2 where | |||
104 | pokeByteOff ptr sizeFloat ay | 104 | pokeByteOff ptr sizeFloat ay |
105 | 105 | ||
106 | 106 | ||
107 | -- | Get the vector's x coordinate. | ||
108 | |||
109 | |||
110 | |||
111 | -- | Unit vector along the X axis. | 107 | -- | Unit vector along the X axis. |
112 | unitx2 = Vector2 1 0 | 108 | unitx2 = Vector2 1 0 |
113 | 109 | ||
114 | |||
115 | -- | Unit vector along the Y axis. | 110 | -- | Unit vector along the Y axis. |
116 | unity2 = Vector2 0 1 | 111 | unity2 = Vector2 0 1 |
117 | 112 | ||
118 | |||
119 | -- | Zero vector. | 113 | -- | Zero vector. |
120 | zero2 = Vector2 0 0 | 114 | zero2 = Vector2 0 0 |
121 | 115 | ||
122 | |||
123 | -- | Create a vector from the given values. | 116 | -- | Create a vector from the given values. |
124 | vec2 :: Float -> Float -> Vector2 | 117 | vec2 :: Float -> Float -> Vector2 |
125 | vec2 ax ay = Vector2 ax ay | 118 | vec2 ax ay = Vector2 ax ay |
126 | 119 | ||
127 | |||
128 | -- | Compute a vector perpendicular to the given one, satisfying: | 120 | -- | Compute a vector perpendicular to the given one, satisfying: |
129 | -- | 121 | -- |
130 | -- perp (Vector2 0 1) = Vector2 1 0 | 122 | -- perp (Vector2 0 1) = Vector2 1 0 |
diff --git a/Spear/Math/Vector/Vector3.hs b/Spear/Math/Vector/Vector3.hs index 429df0f..82deba2 100644 --- a/Spear/Math/Vector/Vector3.hs +++ b/Spear/Math/Vector/Vector3.hs | |||
@@ -18,10 +18,10 @@ module Spear.Math.Vector.Vector3 | |||
18 | where | 18 | where |
19 | 19 | ||
20 | 20 | ||
21 | import Spear.Math.Vector.Class | 21 | import Spear.Math.Vector.Vector |
22 | 22 | ||
23 | import Foreign.C.Types (CFloat) | 23 | import Foreign.C.Types (CFloat) |
24 | import Foreign.Storable | 24 | import Foreign.Storable |
25 | 25 | ||
26 | type Right3 = Vector3 | 26 | type Right3 = Vector3 |
27 | type Up3 = Vector3 | 27 | type Up3 = Vector3 |
@@ -76,7 +76,7 @@ instance Ord Vector3 where | |||
76 | min (Vector3 ax ay az) (Vector3 bx by bz) = Vector3 (Prelude.min ax bx) (Prelude.min ay by) (Prelude.min az bz) | 76 | min (Vector3 ax ay az) (Vector3 bx by bz) = Vector3 (Prelude.min ax bx) (Prelude.min ay by) (Prelude.min az bz) |
77 | 77 | ||
78 | 78 | ||
79 | instance VectorClass Vector3 where | 79 | instance Vector Vector3 where |
80 | {-# INLINABLE fromList #-} | 80 | {-# INLINABLE fromList #-} |
81 | fromList (ax:ay:az:_) = Vector3 ax ay az | 81 | fromList (ax:ay:az:_) = Vector3 ax ay az |
82 | 82 | ||
diff --git a/Spear/Math/Vector/Vector4.hs b/Spear/Math/Vector/Vector4.hs index 4314b51..325eefc 100644 --- a/Spear/Math/Vector/Vector4.hs +++ b/Spear/Math/Vector/Vector4.hs | |||
@@ -12,10 +12,10 @@ module Spear.Math.Vector.Vector4 | |||
12 | where | 12 | where |
13 | 13 | ||
14 | 14 | ||
15 | import Spear.Math.Vector.Class | 15 | import Spear.Math.Vector.Vector |
16 | 16 | ||
17 | import Foreign.C.Types (CFloat) | 17 | import Foreign.C.Types (CFloat) |
18 | import Foreign.Storable | 18 | import Foreign.Storable |
19 | 19 | ||
20 | 20 | ||
21 | -- | Represents a vector in 3D. | 21 | -- | Represents a vector in 3D. |
@@ -73,7 +73,7 @@ instance Ord Vector4 where | |||
73 | Vector4 (Prelude.max ax bx) (Prelude.max ay by) (Prelude.max az bz) (Prelude.min aw bw) | 73 | Vector4 (Prelude.max ax bx) (Prelude.max ay by) (Prelude.max az bz) (Prelude.min aw bw) |
74 | 74 | ||
75 | 75 | ||
76 | instance VectorClass Vector4 where | 76 | instance Vector Vector4 where |
77 | {-# INLINABLE fromList #-} | 77 | {-# INLINABLE fromList #-} |
78 | fromList (ax:ay:az:aw:_) = Vector4 ax ay az aw | 78 | fromList (ax:ay:az:aw:_) = Vector4 ax ay az aw |
79 | 79 | ||
diff --git a/Spear/Window.hs b/Spear/Window.hs index ec90a2f..336910b 100644 --- a/Spear/Window.hs +++ b/Spear/Window.hs | |||
@@ -31,6 +31,7 @@ where | |||
31 | import Control.Concurrent.MVar | 31 | import Control.Concurrent.MVar |
32 | import Control.Exception | 32 | import Control.Exception |
33 | import Control.Monad (foldM, unless, void, when) | 33 | import Control.Monad (foldM, unless, void, when) |
34 | import Data.Functor ((<&>)) | ||
34 | import Data.Maybe (fromJust, fromMaybe, isJust) | 35 | import Data.Maybe (fromJust, fromMaybe, isJust) |
35 | import qualified Graphics.UI.GLFW as GLFW | 36 | import qualified Graphics.UI.GLFW as GLFW |
36 | import Spear.Game | 37 | import Spear.Game |