@inglorious/engine 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -36
- package/package.json +10 -22
- package/src/engine/ai/movement/dynamic/align.js +63 -63
- package/src/engine/ai/movement/dynamic/arrive.js +42 -43
- package/src/engine/ai/movement/dynamic/evade.js +38 -38
- package/src/engine/ai/movement/dynamic/face.js +19 -20
- package/src/engine/ai/movement/dynamic/flee.js +45 -45
- package/src/engine/ai/movement/dynamic/look-where-youre-going.js +16 -17
- package/src/engine/ai/movement/dynamic/match-velocity.js +51 -50
- package/src/engine/ai/movement/dynamic/pursue.js +38 -38
- package/src/engine/ai/movement/dynamic/seek.js +44 -44
- package/src/engine/ai/movement/dynamic/wander.js +31 -32
- package/src/engine/ai/movement/kinematic/align.js +37 -37
- package/src/engine/ai/movement/kinematic/arrive.js +42 -42
- package/src/engine/ai/movement/kinematic/face.js +19 -20
- package/src/engine/ai/movement/kinematic/flee.js +26 -26
- package/src/engine/ai/movement/kinematic/seek.js +26 -26
- package/src/engine/ai/movement/kinematic/seek.test.js +42 -42
- package/src/engine/ai/movement/kinematic/wander-as-seek.js +31 -31
- package/src/engine/ai/movement/kinematic/wander.js +27 -27
- package/src/engine/animation/sprite.js +101 -0
- package/src/engine/animation/ticker.js +38 -0
- package/src/engine/behaviors/camera.js +68 -0
- package/src/engine/behaviors/controls/dynamic/modern.js +76 -0
- package/src/engine/behaviors/controls/dynamic/shooter.js +84 -0
- package/src/engine/behaviors/controls/dynamic/tank.js +69 -0
- package/src/engine/behaviors/controls/event-handlers.js +17 -0
- package/src/engine/behaviors/controls/kinematic/modern.js +76 -0
- package/src/engine/behaviors/controls/kinematic/shooter.js +82 -0
- package/src/engine/behaviors/controls/kinematic/tank.js +67 -0
- package/src/engine/behaviors/debug/collision.js +35 -0
- package/src/engine/behaviors/fps.js +29 -0
- package/src/engine/behaviors/fsm.js +33 -0
- package/src/{game/decorators → engine/behaviors}/fsm.test.js +49 -56
- package/src/engine/behaviors/game.js +15 -0
- package/src/engine/behaviors/input/controls.js +37 -0
- package/src/engine/behaviors/input/gamepad.js +114 -0
- package/src/engine/behaviors/input/input.js +48 -0
- package/src/engine/behaviors/input/keyboard.js +64 -0
- package/src/engine/behaviors/input/mouse.js +91 -0
- package/src/engine/behaviors/physics/bouncy.js +25 -0
- package/src/engine/behaviors/physics/clamped.js +36 -0
- package/src/{game/decorators/collisions.js → engine/behaviors/physics/collidable.js} +20 -24
- package/src/engine/behaviors/physics/jumpable.js +145 -0
- package/src/engine/behaviors/ui/button.js +17 -0
- package/src/engine/collision/detection.js +110 -115
- package/src/engine/core/api.js +34 -0
- package/src/engine/core/dev-tools.js +135 -0
- package/src/engine/core/engine.js +119 -0
- package/src/engine/core/loop.js +15 -0
- package/src/engine/{loop → core/loops}/animation-frame.js +25 -26
- package/src/engine/{loop → core/loops}/elapsed.js +22 -23
- package/src/engine/{loop → core/loops}/fixed.js +27 -28
- package/src/engine/{loop → core/loops}/flash.js +13 -14
- package/src/engine/{loop → core/loops}/lag.js +26 -27
- package/src/engine/core/select.js +26 -0
- package/src/engine/core/store.js +178 -0
- package/src/engine/core/store.test.js +110 -0
- package/src/engine/movement/dynamic/modern.js +21 -24
- package/src/engine/movement/dynamic/tank.js +43 -43
- package/src/engine/movement/kinematic/modern.js +16 -16
- package/src/engine/movement/kinematic/modern.test.js +27 -27
- package/src/engine/movement/kinematic/tank.js +27 -27
- package/src/engine/physics/bounds.js +138 -0
- package/src/engine/physics/position.js +43 -0
- package/src/engine/physics/position.test.js +80 -0
- package/src/engine/systems/sprite-animation.js +27 -0
- package/src/main.js +10 -5
- package/src/renderers/canvas/absolute-position.js +18 -0
- package/src/renderers/canvas/camera.js +13 -0
- package/src/renderers/canvas/canvas-renderer.js +68 -0
- package/src/{ui → renderers}/canvas/character.js +38 -35
- package/src/{ui → renderers}/canvas/form/button.js +25 -25
- package/src/{ui → renderers}/canvas/fps.js +18 -18
- package/src/renderers/canvas/image/hitmask.js +51 -0
- package/src/{ui → renderers}/canvas/image/image.js +34 -37
- package/src/{ui → renderers}/canvas/image/sprite.js +49 -49
- package/src/{ui → renderers}/canvas/image/tilemap.js +66 -64
- package/src/{ui → renderers}/canvas/mouse.js +37 -37
- package/src/renderers/canvas/rendering-system.js +79 -0
- package/src/{ui → renderers}/canvas/shapes/circle.js +29 -31
- package/src/{ui → renderers}/canvas/shapes/rectangle.js +27 -31
- package/src/renderers/react/game/character/index.jsx +20 -0
- package/src/{ui → renderers}/react/game/cursor/index.jsx +20 -20
- package/src/{ui → renderers}/react/game/form/fields/field/index.jsx +56 -56
- package/src/{ui → renderers}/react/game/form/fields/index.jsx +12 -12
- package/src/{ui → renderers}/react/game/form/index.jsx +22 -22
- package/src/{ui → renderers}/react/game/fps/index.jsx +16 -16
- package/src/{ui → renderers}/react/game/game.jsx +72 -71
- package/src/{ui → renderers}/react/game/index.jsx +29 -29
- package/src/{ui → renderers}/react/game/platform/index.jsx +30 -30
- package/src/{ui → renderers}/react/game/scene/index.jsx +27 -25
- package/src/{ui → renderers}/react/game/sprite/index.jsx +60 -58
- package/src/{ui → renderers}/react/game/stats/index.jsx +22 -22
- package/src/{ui → renderers}/react/hocs/with-absolute-position/index.jsx +20 -20
- package/src/{ui → renderers}/react/index.jsx +9 -9
- package/src/utils/algorithms/decision-tree.js +24 -24
- package/src/utils/algorithms/decision-tree.test.js +153 -102
- package/src/utils/algorithms/path-finding.js +155 -155
- package/src/utils/algorithms/path-finding.test.js +151 -151
- package/src/utils/data-structures/array.js +83 -83
- package/src/utils/data-structures/array.test.js +173 -173
- package/src/utils/data-structures/board.js +159 -159
- package/src/utils/data-structures/board.test.js +242 -242
- package/src/utils/data-structures/boolean.js +9 -9
- package/src/utils/data-structures/heap.js +164 -164
- package/src/utils/data-structures/heap.test.js +103 -103
- package/src/utils/data-structures/object.js +138 -102
- package/src/utils/data-structures/object.test.js +218 -121
- package/src/utils/data-structures/objects.js +66 -48
- package/src/utils/data-structures/objects.test.js +99 -99
- package/src/utils/data-structures/tree.js +36 -36
- package/src/utils/data-structures/tree.test.js +33 -33
- package/src/utils/functions/functions.js +19 -19
- package/src/utils/functions/functions.test.js +23 -23
- package/src/utils/math/geometry/circle.js +70 -117
- package/src/utils/math/geometry/circle.test.js +97 -97
- package/src/utils/math/geometry/hitmask.js +70 -39
- package/src/utils/math/geometry/hitmask.test.js +155 -84
- package/src/utils/math/geometry/line.js +35 -35
- package/src/utils/math/geometry/line.test.js +49 -49
- package/src/utils/math/geometry/point.js +78 -71
- package/src/utils/math/geometry/point.test.js +81 -81
- package/src/utils/math/geometry/rectangle.js +76 -45
- package/src/utils/math/geometry/rectangle.test.js +42 -42
- package/src/utils/math/geometry/segment.js +80 -80
- package/src/utils/math/geometry/segment.test.js +183 -183
- package/src/utils/math/geometry/triangle.js +15 -15
- package/src/utils/math/geometry/triangle.test.js +11 -11
- package/src/utils/math/linear-algebra/2d.js +28 -28
- package/src/utils/math/linear-algebra/2d.test.js +17 -17
- package/src/utils/math/linear-algebra/quaternion.js +22 -22
- package/src/utils/math/linear-algebra/quaternion.test.js +25 -25
- package/src/utils/math/linear-algebra/quaternions.js +20 -20
- package/src/utils/math/linear-algebra/quaternions.test.js +29 -29
- package/src/utils/math/linear-algebra/vector.js +327 -302
- package/src/utils/math/linear-algebra/vector.test.js +265 -257
- package/src/utils/math/linear-algebra/vectors.js +122 -122
- package/src/utils/math/linear-algebra/vectors.test.js +65 -65
- package/src/utils/math/linear-interpolation.js +9 -0
- package/src/utils/math/numbers.js +90 -90
- package/src/utils/math/numbers.test.js +137 -137
- package/src/utils/math/rng.js +44 -44
- package/src/utils/math/rng.test.js +39 -39
- package/src/utils/math/statistics.js +43 -43
- package/src/utils/math/statistics.test.js +47 -47
- package/src/utils/math/trigonometry.js +89 -89
- package/src/utils/math/trigonometry.test.js +52 -52
- package/src/utils/physics/acceleration.js +61 -63
- package/src/utils/physics/friction.js +28 -30
- package/src/utils/physics/friction.test.js +42 -44
- package/src/utils/physics/gravity.js +69 -71
- package/src/utils/physics/gravity.test.js +77 -80
- package/src/utils/physics/jump.js +31 -41
- package/src/utils/physics/velocity.js +36 -38
- package/src/engine/loop.js +0 -15
- package/src/engine/store.js +0 -174
- package/src/engine/store.test.js +0 -256
- package/src/engine.js +0 -74
- package/src/game/animation.js +0 -26
- package/src/game/bounds.js +0 -66
- package/src/game/decorators/character.js +0 -5
- package/src/game/decorators/clamp-to-bounds.js +0 -15
- package/src/game/decorators/controls/dynamic/modern.js +0 -48
- package/src/game/decorators/controls/dynamic/shooter.js +0 -47
- package/src/game/decorators/controls/dynamic/tank.js +0 -55
- package/src/game/decorators/controls/kinematic/modern.js +0 -49
- package/src/game/decorators/controls/kinematic/shooter.js +0 -45
- package/src/game/decorators/controls/kinematic/tank.js +0 -52
- package/src/game/decorators/debug/collisions.js +0 -32
- package/src/game/decorators/double-jump.js +0 -70
- package/src/game/decorators/fps.js +0 -30
- package/src/game/decorators/fsm.js +0 -27
- package/src/game/decorators/game.js +0 -11
- package/src/game/decorators/image/image.js +0 -5
- package/src/game/decorators/image/sprite.js +0 -5
- package/src/game/decorators/image/tilemap.js +0 -5
- package/src/game/decorators/input/controls.js +0 -27
- package/src/game/decorators/input/gamepad.js +0 -74
- package/src/game/decorators/input/input.js +0 -41
- package/src/game/decorators/input/keyboard.js +0 -49
- package/src/game/decorators/input/mouse.js +0 -65
- package/src/game/decorators/jump.js +0 -72
- package/src/game/decorators/platform.js +0 -5
- package/src/game/decorators/ui/button.js +0 -21
- package/src/game/sprite.js +0 -119
- package/src/ui/canvas/absolute-position.js +0 -17
- package/src/ui/canvas/image/hitmask.js +0 -37
- package/src/ui/canvas.js +0 -81
- package/src/ui/react/game/character/index.jsx +0 -30
- package/src/utils/math/geometry/platform.js +0 -42
- package/src/utils/math/geometry/platform.test.js +0 -133
- /package/src/{ui → renderers}/react/game/character/character.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/cursor/cursor.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/form/fields/field/field.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/form/fields/fields.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/form/form.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/platform/platform.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/scene/scene.module.scss +0 -0
- /package/src/{ui → renderers}/react/game/sprite/sprite.module.css +0 -0
- /package/src/{ui → renderers}/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -0
|
@@ -1,71 +1,69 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import('@inglorious/utils/math/linear-algebra/types').Vector3} Vector3
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/* eslint-disable no-magic-numbers */
|
|
6
|
-
|
|
7
|
-
import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const DEFAULT_JUMP = 0 // Default maximum jump height.
|
|
11
|
-
const DEFAULT_LEAP = 0 // Default maximum leap distance.
|
|
12
|
-
const DEFAULT_SPEED = 0 // Default maximum speed.
|
|
13
|
-
const NO_VELOCITY = 0 // No initial velocity.
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Applies gravity to an object based on its current velocity and position.
|
|
17
|
-
*
|
|
18
|
-
* @see https://youtu.be/hG9SzQxaCm8
|
|
19
|
-
*
|
|
20
|
-
* Projectile equations:
|
|
21
|
-
* 1. a(t) = g
|
|
22
|
-
* 2. v(t) = g*t + v_0
|
|
23
|
-
* 3. y(t) = 1/2*g*t^2 + v_0*t + y_0
|
|
24
|
-
*
|
|
25
|
-
* Known values:
|
|
26
|
-
* 1. y_0 = 0
|
|
27
|
-
* 2. v(t_h) = 0 -> 2. 0 = g*t_h + v_0 -> v_0 = -g*t_h
|
|
28
|
-
* 3. y_h = h -> 3. h = 1/2*g*t_h^2 (-g*t_h)*t_h = -1/2*g*t_h^2 -> g = -2*h/t_h^2
|
|
29
|
-
* 4. v_0 = -g*t_h = (-2*h/t_h^2)*t_h = 2*h/t_h
|
|
30
|
-
*
|
|
31
|
-
* Transforming time into space:
|
|
32
|
-
* 1. t_h = x_h/v_x
|
|
33
|
-
* 2. v0 = 2*h/t_h = 2*h*v_x/x_h
|
|
34
|
-
* 3. g = -2*h/t_h^2 = -2*h*v_x^2/x_h^2
|
|
35
|
-
*
|
|
36
|
-
* Euler's Integration:
|
|
37
|
-
* 1. v += a * dt
|
|
38
|
-
* 2. p += v * dt + 1/2 * a * dt * dt
|
|
39
|
-
*
|
|
40
|
-
* @param {Object} params - Parameters for gravity calculation.
|
|
41
|
-
* @param {number} params.maxJump - Maximum jump height. Defaults to 0.
|
|
42
|
-
* @param {number} params.maxLeap - Maximum leap distance. Defaults to 0.
|
|
43
|
-
* @param {number} params.maxSpeed - Maximum speed. Defaults to 0.
|
|
44
|
-
* @param {number} params.vy - Current vertical velocity. Defaults to 0.
|
|
45
|
-
* @param {Vector3} params.position - Current position vector.
|
|
46
|
-
* @param {
|
|
47
|
-
* @
|
|
48
|
-
* @
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
vy
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return { ay, vy, position: [x, py, z] }
|
|
71
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('@inglorious/utils/math/linear-algebra/types').Vector3} Vector3
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint-disable no-magic-numbers */
|
|
6
|
+
|
|
7
|
+
import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
8
|
+
|
|
9
|
+
const DEFAULT_DT = 1 // Default delta time for the applyGravity function.
|
|
10
|
+
const DEFAULT_JUMP = 0 // Default maximum jump height.
|
|
11
|
+
const DEFAULT_LEAP = 0 // Default maximum leap distance.
|
|
12
|
+
const DEFAULT_SPEED = 0 // Default maximum speed.
|
|
13
|
+
const NO_VELOCITY = 0 // No initial velocity.
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Applies gravity to an object based on its current velocity and position.
|
|
17
|
+
*
|
|
18
|
+
* @see https://youtu.be/hG9SzQxaCm8
|
|
19
|
+
*
|
|
20
|
+
* Projectile equations:
|
|
21
|
+
* 1. a(t) = g
|
|
22
|
+
* 2. v(t) = g*t + v_0
|
|
23
|
+
* 3. y(t) = 1/2*g*t^2 + v_0*t + y_0
|
|
24
|
+
*
|
|
25
|
+
* Known values:
|
|
26
|
+
* 1. y_0 = 0
|
|
27
|
+
* 2. v(t_h) = 0 -> 2. 0 = g*t_h + v_0 -> v_0 = -g*t_h
|
|
28
|
+
* 3. y_h = h -> 3. h = 1/2*g*t_h^2 (-g*t_h)*t_h = -1/2*g*t_h^2 -> g = -2*h/t_h^2
|
|
29
|
+
* 4. v_0 = -g*t_h = (-2*h/t_h^2)*t_h = 2*h/t_h
|
|
30
|
+
*
|
|
31
|
+
* Transforming time into space:
|
|
32
|
+
* 1. t_h = x_h/v_x
|
|
33
|
+
* 2. v0 = 2*h/t_h = 2*h*v_x/x_h
|
|
34
|
+
* 3. g = -2*h/t_h^2 = -2*h*v_x^2/x_h^2
|
|
35
|
+
*
|
|
36
|
+
* Euler's Integration:
|
|
37
|
+
* 1. v += a * dt
|
|
38
|
+
* 2. p += v * dt + 1/2 * a * dt * dt
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} params - Parameters for gravity calculation.
|
|
41
|
+
* @param {number} params.maxJump - Maximum jump height. Defaults to 0.
|
|
42
|
+
* @param {number} params.maxLeap - Maximum leap distance. Defaults to 0.
|
|
43
|
+
* @param {number} params.maxSpeed - Maximum speed. Defaults to 0.
|
|
44
|
+
* @param {number} params.vy - Current vertical velocity. Defaults to 0.
|
|
45
|
+
* @param {Vector3} params.position - Current position vector. Defaults to a zero vector.
|
|
46
|
+
* @param {number} dt - Time delta for the calculation. Defaults to 1.
|
|
47
|
+
* @returns {Object} Updated acceleration, velocity, and position.
|
|
48
|
+
* @throws {Error} If maxLeap is not provided.
|
|
49
|
+
*/
|
|
50
|
+
export function applyGravity(params, dt = DEFAULT_DT) {
|
|
51
|
+
let {
|
|
52
|
+
maxJump = DEFAULT_JUMP,
|
|
53
|
+
maxLeap = DEFAULT_LEAP,
|
|
54
|
+
maxSpeed = DEFAULT_SPEED,
|
|
55
|
+
vy = NO_VELOCITY,
|
|
56
|
+
position = zero(),
|
|
57
|
+
} = params
|
|
58
|
+
|
|
59
|
+
if (!maxLeap) {
|
|
60
|
+
throw new Error("Missing maxLeap")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const ay = (-2 * maxJump * maxSpeed ** 2) / maxLeap ** 2
|
|
64
|
+
vy += ay * dt
|
|
65
|
+
const [x, y, z] = position
|
|
66
|
+
const py = y + vy * dt + 0.5 * ay * dt * dt
|
|
67
|
+
|
|
68
|
+
return { ay, vy, position: [x, py, z] }
|
|
69
|
+
}
|
|
@@ -1,80 +1,77 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { applyGravity } from "./gravity.js"
|
|
4
|
-
|
|
5
|
-
test("it should
|
|
6
|
-
const params = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
expect(applyGravity(params
|
|
15
|
-
ay: -
|
|
16
|
-
vy: 10,
|
|
17
|
-
position: [0,
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test("it should
|
|
22
|
-
const params = {
|
|
23
|
-
|
|
24
|
-
maxSpeed: 10,
|
|
25
|
-
vy: 10,
|
|
26
|
-
position: [0, 10, 0],
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
position: [0, -10, 0],
|
|
79
|
-
})
|
|
80
|
-
})
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import { applyGravity } from "./gravity.js"
|
|
4
|
+
|
|
5
|
+
test("it should apply gravity based on input parameters", () => {
|
|
6
|
+
const params = {
|
|
7
|
+
maxJump: 10,
|
|
8
|
+
maxLeap: 10,
|
|
9
|
+
maxSpeed: 10,
|
|
10
|
+
vy: 10,
|
|
11
|
+
position: [0, 10, 0],
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
expect(applyGravity(params)).toStrictEqual({
|
|
15
|
+
ay: -20,
|
|
16
|
+
vy: -10,
|
|
17
|
+
position: [0, -10, 0],
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test("it should compute no gravity when max jump height is not set", () => {
|
|
22
|
+
const params = {
|
|
23
|
+
maxLeap: 10,
|
|
24
|
+
maxSpeed: 10,
|
|
25
|
+
vy: 10,
|
|
26
|
+
position: [0, 10, 0],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
expect(applyGravity(params)).toStrictEqual({
|
|
30
|
+
ay: -0,
|
|
31
|
+
vy: 10,
|
|
32
|
+
position: [0, 20, 0],
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test("it should compute no gravity when max movement speed is not set", () => {
|
|
37
|
+
const params = {
|
|
38
|
+
maxJump: 10,
|
|
39
|
+
maxLeap: 10,
|
|
40
|
+
vy: 10,
|
|
41
|
+
position: [0, 10, 0],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
expect(applyGravity(params)).toStrictEqual({
|
|
45
|
+
ay: -0,
|
|
46
|
+
vy: 10,
|
|
47
|
+
position: [0, 20, 0],
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test("it should apply no gravity when no time has passed", () => {
|
|
52
|
+
const params = {
|
|
53
|
+
maxJump: 10,
|
|
54
|
+
maxLeap: 10,
|
|
55
|
+
maxSpeed: 10,
|
|
56
|
+
vy: 10,
|
|
57
|
+
position: [0, 10, 0],
|
|
58
|
+
}
|
|
59
|
+
const dt = 0
|
|
60
|
+
|
|
61
|
+
expect(applyGravity(params, dt)).toStrictEqual({
|
|
62
|
+
ay: -20,
|
|
63
|
+
vy: 10,
|
|
64
|
+
position: [0, 10, 0],
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("it should throw an error when max leap distance is not set", () => {
|
|
69
|
+
const params = {
|
|
70
|
+
maxJump: 10,
|
|
71
|
+
maxSpeed: 10,
|
|
72
|
+
vy: 10,
|
|
73
|
+
position: [0, 10, 0],
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
expect(() => applyGravity(params)).toThrow()
|
|
77
|
+
})
|
|
@@ -1,41 +1,31 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import('@inglorious/utils/math/linear-algebra/types').Vector3} Vector3
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/* eslint-disable no-magic-numbers */
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @param {
|
|
19
|
-
* @
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
position = zero(),
|
|
33
|
-
} = params
|
|
34
|
-
const { dt } = options
|
|
35
|
-
|
|
36
|
-
const vy = (2 * maxJump * maxSpeed) / maxLeap
|
|
37
|
-
const [x, y, z] = position
|
|
38
|
-
const py = y + vy * dt
|
|
39
|
-
|
|
40
|
-
return { vy, position: [x, py, z] }
|
|
41
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('@inglorious/utils/math/linear-algebra/types').Vector3} Vector3
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint-disable no-magic-numbers */
|
|
6
|
+
|
|
7
|
+
const DEFAULT_MAX_JUMP = 0 // Default maximum jump height.
|
|
8
|
+
const DEFAULT_MAX_LEAP = 0 // Default maximum leap distance.
|
|
9
|
+
const DEFAULT_MAX_SPEED = 0 // Default maximum speed.
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calculates the vertical velocity (vy) of a jump
|
|
13
|
+
* based on the provided parameters.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} params - Parameters for the jump calculation.
|
|
16
|
+
* @param {number} params.maxJump - Maximum jump height. Defaults to 0.
|
|
17
|
+
* @param {number} params.maxLeap - Maximum leap distance. Defaults to 0.
|
|
18
|
+
* @param {number} params.maxSpeed - Maximum speed. Defaults to 0.
|
|
19
|
+
* @returns {number} The computed vertical velocity (vy).
|
|
20
|
+
*/
|
|
21
|
+
export function jump(params) {
|
|
22
|
+
let {
|
|
23
|
+
maxJump = DEFAULT_MAX_JUMP,
|
|
24
|
+
maxLeap = DEFAULT_MAX_LEAP,
|
|
25
|
+
maxSpeed = DEFAULT_MAX_SPEED,
|
|
26
|
+
} = params
|
|
27
|
+
|
|
28
|
+
const vy = (2 * maxJump * maxSpeed) / maxLeap
|
|
29
|
+
|
|
30
|
+
return vy
|
|
31
|
+
}
|
|
@@ -1,38 +1,36 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import('@inglorious/utils/math/linear-algebra/types').Vector3} Vector3
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
clamp,
|
|
7
|
-
multiply,
|
|
8
|
-
zero,
|
|
9
|
-
} from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
10
|
-
import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const DEFAULT_MAX_SPEED = 0 // Default maximum speed for velocity clamping.
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Applies velocity to a position based on the given parameters and options.
|
|
17
|
-
*
|
|
18
|
-
* @param {Object} params - The parameters for velocity application.
|
|
19
|
-
* @param {number} [params.maxSpeed] - The maximum speed for clamping the velocity. Defaults to 0.
|
|
20
|
-
* @param {Vector3} [params.velocity] - The current velocity vector. Defaults to a zero vector.
|
|
21
|
-
* @param {Vector3} [params.position] - The current position vector. Defaults to a zero vector.
|
|
22
|
-
* @param {
|
|
23
|
-
* @
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return { velocity, position }
|
|
38
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('@inglorious/utils/math/linear-algebra/types').Vector3} Vector3
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
clamp,
|
|
7
|
+
multiply,
|
|
8
|
+
zero,
|
|
9
|
+
} from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
10
|
+
import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
11
|
+
|
|
12
|
+
const DEFAULT_DT = 1 // Default time delta for the applyVelocity function.
|
|
13
|
+
const DEFAULT_MAX_SPEED = 0 // Default maximum speed for velocity clamping.
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Applies velocity to a position based on the given parameters and options.
|
|
17
|
+
*
|
|
18
|
+
* @param {Object} params - The parameters for velocity application.
|
|
19
|
+
* @param {number} [params.maxSpeed] - The maximum speed for clamping the velocity. Defaults to 0.
|
|
20
|
+
* @param {Vector3} [params.velocity] - The current velocity vector. Defaults to a zero vector.
|
|
21
|
+
* @param {Vector3} [params.position] - The current position vector. Defaults to a zero vector.
|
|
22
|
+
* @param {number} [dt=0] - The time delta for the calculation. Defaults to 0.
|
|
23
|
+
* @returns {Object} The updated velocity and position.
|
|
24
|
+
*/
|
|
25
|
+
export function applyVelocity(params, dt = DEFAULT_DT) {
|
|
26
|
+
let {
|
|
27
|
+
maxSpeed = DEFAULT_MAX_SPEED,
|
|
28
|
+
velocity = zero(),
|
|
29
|
+
position = zero(),
|
|
30
|
+
} = params
|
|
31
|
+
|
|
32
|
+
velocity = clamp(velocity, -maxSpeed, maxSpeed)
|
|
33
|
+
|
|
34
|
+
position = sum(position, multiply(velocity, dt))
|
|
35
|
+
return { velocity, position }
|
|
36
|
+
}
|
package/src/engine/loop.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import AnimationFrameLoop from "./loop/animation-frame.js"
|
|
2
|
-
import ElapsedLoop from "./loop/elapsed.js"
|
|
3
|
-
import FixedLoop from "./loop/fixed.js"
|
|
4
|
-
import FlashLoop from "./loop/flash.js"
|
|
5
|
-
import LagLoop from "./loop/lag.js"
|
|
6
|
-
|
|
7
|
-
// @see https://gameprogrammingpatterns.com/game-loop.html
|
|
8
|
-
|
|
9
|
-
export default {
|
|
10
|
-
flash: FlashLoop,
|
|
11
|
-
fixed: FixedLoop,
|
|
12
|
-
elapsed: ElapsedLoop,
|
|
13
|
-
lag: LagLoop,
|
|
14
|
-
animationFrame: AnimationFrameLoop,
|
|
15
|
-
}
|
package/src/engine/store.js
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { enableGame } from "@inglorious/game/decorators/game.js"
|
|
2
|
-
import { map } from "@inglorious/utils/data-structures/object.js"
|
|
3
|
-
import { extend } from "@inglorious/utils/data-structures/objects.js"
|
|
4
|
-
import { pipe } from "@inglorious/utils/functions/functions.js"
|
|
5
|
-
import { produce } from "immer"
|
|
6
|
-
|
|
7
|
-
const DEFAULT_TYPES = {
|
|
8
|
-
game: [enableGame()],
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const DEFAULT_INSTANCES = {
|
|
12
|
-
// eslint-disable-next-line no-magic-numbers
|
|
13
|
-
game: { type: "game", bounds: [0, 0, 800, 600] }, // Default game instance with bounds.
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const DEFAULT_LAYER = 0
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Creates a store to manage state and events.
|
|
20
|
-
* @param {Object} options - Configuration options for the store.
|
|
21
|
-
* @param {Object} options.instances - Initial instances to include in the store.
|
|
22
|
-
* @param {Object} options.originalConfig - Additional configuration for the store.
|
|
23
|
-
* @returns {Object} The store with methods to interact with state and events.
|
|
24
|
-
*/
|
|
25
|
-
export function createStore({
|
|
26
|
-
types: originalTypes,
|
|
27
|
-
instances: originalInstances,
|
|
28
|
-
}) {
|
|
29
|
-
const listeners = new Set()
|
|
30
|
-
let incomingEvents = []
|
|
31
|
-
|
|
32
|
-
let types = extend(DEFAULT_TYPES, originalTypes)
|
|
33
|
-
types = augmentTypes(types)
|
|
34
|
-
|
|
35
|
-
let instances = extend(DEFAULT_INSTANCES, originalInstances)
|
|
36
|
-
instances = augmentInstances(instances)
|
|
37
|
-
|
|
38
|
-
let state = { events: [], instances }
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
subscribe,
|
|
42
|
-
update,
|
|
43
|
-
notify,
|
|
44
|
-
dispatch: notify, // needed for react-redux
|
|
45
|
-
getTypes,
|
|
46
|
-
getState,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Subscribes a listener to state updates.
|
|
51
|
-
* @param {Function} listener - The listener function to call on updates.
|
|
52
|
-
* @returns {Function} A function to unsubscribe the listener.
|
|
53
|
-
*/
|
|
54
|
-
function subscribe(listener) {
|
|
55
|
-
listeners.add(listener)
|
|
56
|
-
|
|
57
|
-
return function unsubscribe() {
|
|
58
|
-
listeners.delete(listener)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Updates the state based on elapsed time and processes events.
|
|
64
|
-
* @param {number} dt - The delta time since the last update.
|
|
65
|
-
*/
|
|
66
|
-
function update(dt) {
|
|
67
|
-
state = { ...state }
|
|
68
|
-
|
|
69
|
-
state.events.push(...incomingEvents, { id: "game:update" })
|
|
70
|
-
incomingEvents = []
|
|
71
|
-
|
|
72
|
-
while (state.events.length) {
|
|
73
|
-
const event = state.events.shift()
|
|
74
|
-
|
|
75
|
-
if (event.id === "instance:add") {
|
|
76
|
-
add(event.payload.id, event.payload)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
state.instances = map(state.instances, (_, instance, instances) => {
|
|
80
|
-
const type = types[instance.type]
|
|
81
|
-
const handle = type[event.id]
|
|
82
|
-
return (
|
|
83
|
-
handle?.(instance, event, {
|
|
84
|
-
dt,
|
|
85
|
-
type: originalTypes[instance.type],
|
|
86
|
-
instances,
|
|
87
|
-
notify,
|
|
88
|
-
}) ?? instance
|
|
89
|
-
)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
if (event.id === "instance:remove") {
|
|
93
|
-
remove(event.payload)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
listeners.forEach((onUpdate) => onUpdate())
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Adds a new instance to the state.
|
|
102
|
-
* @param {string} id - The ID of the instance to add.
|
|
103
|
-
* @param {Object} instance - The instance object to add.
|
|
104
|
-
*/
|
|
105
|
-
function add(id, instance) {
|
|
106
|
-
state = { ...state }
|
|
107
|
-
state.instances[id] = augmentInstance(id, instance)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Removes an instance from the state.
|
|
112
|
-
* @param {string} id - The ID of the instance to remove.
|
|
113
|
-
*/
|
|
114
|
-
function remove(id) {
|
|
115
|
-
state = { ...state }
|
|
116
|
-
delete state.instances[id]
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Notifies the store of a new event.
|
|
121
|
-
* @param {Object} event - The event object to notify.
|
|
122
|
-
*/
|
|
123
|
-
function notify(event) {
|
|
124
|
-
incomingEvents.push(event)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Retrieves the types configuration.
|
|
129
|
-
* @returns {Object} The types configuration.
|
|
130
|
-
*/
|
|
131
|
-
function getTypes() {
|
|
132
|
-
return types
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Retrieves the current state.
|
|
137
|
-
* @returns {Object} The current state.
|
|
138
|
-
*/
|
|
139
|
-
function getState() {
|
|
140
|
-
return state
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function augmentTypes(types) {
|
|
145
|
-
return pipe(applyDecorators, enableMutability)(types)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function applyDecorators(types) {
|
|
149
|
-
return map(types, (_, type) => {
|
|
150
|
-
if (!Array.isArray(type)) {
|
|
151
|
-
return type
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const decorators = type.map((fn) =>
|
|
155
|
-
typeof fn !== "function" ? (type) => extend(type, fn) : fn,
|
|
156
|
-
)
|
|
157
|
-
return pipe(...decorators)({})
|
|
158
|
-
})
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function enableMutability(types) {
|
|
162
|
-
return map(types, (_, { draw, ...events }) => ({
|
|
163
|
-
draw,
|
|
164
|
-
...map(events, (_, event) => produce(event)),
|
|
165
|
-
}))
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function augmentInstances(instances) {
|
|
169
|
-
return map(instances, augmentInstance)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function augmentInstance(id, instance) {
|
|
173
|
-
return { ...instance, layer: instance.layer ?? DEFAULT_LAYER, id }
|
|
174
|
-
}
|