@inglorious/engine 0.1.0 → 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 +20 -33
- 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/docs/ai/movement/dynamic/align.js +0 -131
- package/src/docs/ai/movement/dynamic/arrive.js +0 -88
- package/src/docs/ai/movement/dynamic/dynamic.mdx +0 -99
- package/src/docs/ai/movement/dynamic/dynamic.stories.js +0 -58
- package/src/docs/ai/movement/dynamic/evade.js +0 -72
- package/src/docs/ai/movement/dynamic/face.js +0 -90
- package/src/docs/ai/movement/dynamic/flee.js +0 -38
- package/src/docs/ai/movement/dynamic/look-where-youre-going.js +0 -114
- package/src/docs/ai/movement/dynamic/match-velocity.js +0 -92
- package/src/docs/ai/movement/dynamic/pursue.js +0 -72
- package/src/docs/ai/movement/dynamic/seek.js +0 -37
- package/src/docs/ai/movement/dynamic/wander.js +0 -71
- package/src/docs/ai/movement/kinematic/align.js +0 -122
- package/src/docs/ai/movement/kinematic/arrive.js +0 -78
- package/src/docs/ai/movement/kinematic/face.js +0 -82
- package/src/docs/ai/movement/kinematic/flee.js +0 -36
- package/src/docs/ai/movement/kinematic/kinematic.mdx +0 -67
- package/src/docs/ai/movement/kinematic/kinematic.stories.js +0 -42
- package/src/docs/ai/movement/kinematic/seek.js +0 -34
- package/src/docs/ai/movement/kinematic/wander-as-seek.js +0 -62
- package/src/docs/ai/movement/kinematic/wander.js +0 -28
- package/src/docs/bounds.js +0 -7
- package/src/docs/code-reuse.js +0 -35
- package/src/docs/collision/circles.js +0 -58
- package/src/docs/collision/collision.mdx +0 -27
- package/src/docs/collision/collision.stories.js +0 -22
- package/src/docs/collision/platform.js +0 -76
- package/src/docs/collision/tilemap.js +0 -181
- package/src/docs/empty.js +0 -1
- package/src/docs/engine.mdx +0 -81
- package/src/docs/engine.stories.js +0 -37
- package/src/docs/event-handlers.js +0 -68
- package/src/docs/framerate.js +0 -37
- package/src/docs/game.jsx +0 -15
- package/src/docs/image/image.js +0 -19
- package/src/docs/image/image.stories.js +0 -22
- package/src/docs/image/sprite.js +0 -39
- package/src/docs/image/tilemap.js +0 -84
- package/src/docs/input/controls.js +0 -67
- package/src/docs/input/gamepad.js +0 -67
- package/src/docs/input/input.mdx +0 -55
- package/src/docs/input/input.stories.js +0 -27
- package/src/docs/input/keyboard.js +0 -58
- package/src/docs/input/mouse.js +0 -32
- package/src/docs/instances.js +0 -49
- package/src/docs/player/dynamic/double-jump.js +0 -90
- package/src/docs/player/dynamic/dynamic.stories.js +0 -32
- package/src/docs/player/dynamic/jump.js +0 -83
- package/src/docs/player/dynamic/modern-controls.js +0 -57
- package/src/docs/player/dynamic/shooter-controls.js +0 -51
- package/src/docs/player/dynamic/tank-controls.js +0 -44
- package/src/docs/player/kinematic/double-jump.js +0 -90
- package/src/docs/player/kinematic/jump.js +0 -82
- package/src/docs/player/kinematic/kinematic.stories.js +0 -32
- package/src/docs/player/kinematic/modern-controls.js +0 -56
- package/src/docs/player/kinematic/shooter-controls.js +0 -48
- package/src/docs/player/kinematic/tank-controls.js +0 -42
- package/src/docs/quick-start/first-game.js +0 -49
- package/src/docs/quick-start/hello-world.js +0 -1
- package/src/docs/quick-start.mdx +0 -127
- package/src/docs/quick-start.stories.js +0 -17
- package/src/docs/recipes/add-and-remove.js +0 -71
- package/src/docs/recipes/add-instance.js +0 -42
- package/src/docs/recipes/decision-tree.js +0 -169
- package/src/docs/recipes/random-instances.js +0 -25
- package/src/docs/recipes/recipes.mdx +0 -81
- package/src/docs/recipes/recipes.stories.js +0 -37
- package/src/docs/recipes/remove-instance.js +0 -52
- package/src/docs/recipes/states.js +0 -64
- package/src/docs/ui/button.js +0 -28
- package/src/docs/ui/form.stories.js +0 -55
- package/src/docs/ui-chooser.jsx +0 -6
- package/src/docs/utils/data-structures/object.mdx +0 -47
- package/src/docs/utils/data-structures/objects.mdx +0 -30
- package/src/docs/utils/functions/functions.mdx +0 -34
- package/src/docs/utils/math/geometry/circle.mdx +0 -55
- package/src/docs/utils/math/geometry/point.mdx +0 -38
- package/src/docs/utils/math/geometry/rectangle.mdx +0 -24
- package/src/docs/utils/math/geometry/segment.mdx +0 -55
- package/src/docs/utils/math/geometry/triangle.mdx +0 -22
- package/src/docs/utils/math/linear-algebra/2d.mdx +0 -22
- package/src/docs/utils/math/linear-algebra/quaternion.mdx +0 -21
- package/src/docs/utils/math/linear-algebra/quaternions.mdx +0 -22
- package/src/docs/utils/math/linear-algebra/vector.mdx +0 -177
- package/src/docs/utils/math/linear-algebra/vectors.mdx +0 -58
- package/src/docs/utils/math/numbers.mdx +0 -76
- package/src/docs/utils/math/random.mdx +0 -35
- package/src/docs/utils/math/statistics.mdx +0 -38
- package/src/docs/utils/math/trigonometry.mdx +0 -85
- package/src/docs/utils/physics/friction.mdx +0 -20
- package/src/docs/utils/physics/gravity.mdx +0 -28
- 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,117 +1,70 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import("./types").Point} Point
|
|
3
|
-
* @typedef {import("./types").Circle} Circle
|
|
4
|
-
* @typedef {import("./types").Rectangle} Rectangle
|
|
5
|
-
* @typedef {import("./types").Platform} Platform
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import { intersectsCircle as
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
segmentIntersectsCircle({ from: rbf, to: lbf }, circle) ||
|
|
72
|
-
segmentIntersectsCircle({ from: lbf, to: ltf }, circle) ||
|
|
73
|
-
// Back face
|
|
74
|
-
segmentIntersectsCircle({ from: ltb, to: rtb }, circle) ||
|
|
75
|
-
segmentIntersectsCircle({ from: rtb, to: rbb }, circle) ||
|
|
76
|
-
segmentIntersectsCircle({ from: rbb, to: lbb }, circle) ||
|
|
77
|
-
segmentIntersectsCircle({ from: lbb, to: ltb }, circle) ||
|
|
78
|
-
// Connecting edges
|
|
79
|
-
segmentIntersectsCircle({ from: ltf, to: ltb }, circle) ||
|
|
80
|
-
segmentIntersectsCircle({ from: rtf, to: rtb }, circle) ||
|
|
81
|
-
segmentIntersectsCircle({ from: lbf, to: lbb }, circle) ||
|
|
82
|
-
segmentIntersectsCircle({ from: rbf, to: rbb }, circle) ||
|
|
83
|
-
// Corners
|
|
84
|
-
isCircleWithinRectangleRadius(circle, rectangle)
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Checks if a circle intersects with a platform.
|
|
90
|
-
* @param {Circle} circle - The circle to check.
|
|
91
|
-
* @param {Platform} platform - The platform to check.
|
|
92
|
-
* @returns {boolean} True if the circle intersects the platform, false otherwise.
|
|
93
|
-
*/
|
|
94
|
-
export function intersectsPlatform(circle, platform) {
|
|
95
|
-
return platformIntersectsCircle(platform, circle)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function isCircleWithinRectangleRadius(circle, rectangle) {
|
|
99
|
-
const [left, top, front] = rectangle.position
|
|
100
|
-
const [width, height, depth] = rectangle.size
|
|
101
|
-
|
|
102
|
-
// Find the closest point on the rectangle to the circle's center
|
|
103
|
-
const [x, y, z] = circle.position
|
|
104
|
-
const closestPoint = [
|
|
105
|
-
clamp(x, left, left + width),
|
|
106
|
-
clamp(y, top, top + height),
|
|
107
|
-
clamp(z, front, front + depth),
|
|
108
|
-
]
|
|
109
|
-
|
|
110
|
-
// Calculate the distance from the circle's center to the closest point
|
|
111
|
-
const distanceSquared = subtract(circle.position, closestPoint).reduce(
|
|
112
|
-
(sum, value) => sum + value ** SQUARED,
|
|
113
|
-
INITIAL_SUM,
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
return distanceSquared <= circle.radius ** SQUARED
|
|
117
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("./types").Point} Point
|
|
3
|
+
* @typedef {import("./types").Circle} Circle
|
|
4
|
+
* @typedef {import("./types").Rectangle} Rectangle
|
|
5
|
+
* @typedef {import("./types").Platform} Platform
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { clamp } from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
9
|
+
import { subtract } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
10
|
+
|
|
11
|
+
import { intersectsCircle as pointIntersectsCircle } from "./point.js"
|
|
12
|
+
import { hypothenuse } from "./triangle.js"
|
|
13
|
+
|
|
14
|
+
const HALF = 2
|
|
15
|
+
const SQUARED = 2
|
|
16
|
+
const INITIAL_SUM = 0
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Checks if a circle intersects with a point.
|
|
20
|
+
* @param {Circle} circle - The circle to check.
|
|
21
|
+
* @param {Point} point - The point to check.
|
|
22
|
+
* @returns {boolean} True if the point intersects the circle, false otherwise.
|
|
23
|
+
*/
|
|
24
|
+
export function intersectsPoint(circle, point) {
|
|
25
|
+
return pointIntersectsCircle(point, circle)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Checks if two circles intersect.
|
|
30
|
+
* @param {Circle} circle1 - The first circle.
|
|
31
|
+
* @param {Circle} circle2 - The second circle.
|
|
32
|
+
* @returns {boolean} True if the circles intersect, false otherwise.
|
|
33
|
+
*/
|
|
34
|
+
export function intersectsCircle(circle1, circle2) {
|
|
35
|
+
return (
|
|
36
|
+
hypothenuse(...subtract(circle1.position, circle2.position)) <=
|
|
37
|
+
circle1.radius + circle2.radius
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a circle intersects with a rectangle.
|
|
43
|
+
* @param {Circle} circle - The circle to check.
|
|
44
|
+
* @param {Rectangle} rectangle - The rectangle to check.
|
|
45
|
+
* @returns {boolean} True if the circle intersects the rectangle, false otherwise.
|
|
46
|
+
*/
|
|
47
|
+
export function intersectsRectangle(circle, rectangle) {
|
|
48
|
+
const [rectX, rectY, rectZ] = rectangle.position
|
|
49
|
+
const [width, height, depth] = rectangle.size
|
|
50
|
+
|
|
51
|
+
const left = rectX - width / HALF
|
|
52
|
+
const right = rectX + width / HALF
|
|
53
|
+
const bottom = rectY - height / HALF
|
|
54
|
+
const top = rectY + height / HALF
|
|
55
|
+
const back = rectZ - depth / HALF
|
|
56
|
+
const front = rectZ + depth / HALF
|
|
57
|
+
|
|
58
|
+
const closestPoint = clamp(
|
|
59
|
+
circle.position,
|
|
60
|
+
[left, bottom, back],
|
|
61
|
+
[right, top, front],
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
const distanceSquared = subtract(circle.position, closestPoint).reduce(
|
|
65
|
+
(sum, value) => sum + value ** SQUARED,
|
|
66
|
+
INITIAL_SUM,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return distanceSquared <= circle.radius ** SQUARED
|
|
70
|
+
}
|
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
intersectsCircle,
|
|
5
|
-
intersectsPoint,
|
|
6
|
-
intersectsRectangle,
|
|
7
|
-
} from "./circle.js"
|
|
8
|
-
|
|
9
|
-
test("it should prove that a circle around a point intersects with it", () => {
|
|
10
|
-
const circle = {
|
|
11
|
-
position: [1, 1, 0],
|
|
12
|
-
radius: 1,
|
|
13
|
-
}
|
|
14
|
-
const point = [1.5, 1.5, 0]
|
|
15
|
-
|
|
16
|
-
expect(intersectsPoint(circle, point)).toBe(true)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
test("it should prove that two equal circles intersect", () => {
|
|
20
|
-
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
21
|
-
const circle2 = { position: [1, 1, 0], radius: 1 }
|
|
22
|
-
|
|
23
|
-
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test("it should prove that two circles shifted by a small x intersect", () => {
|
|
27
|
-
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
28
|
-
const circle2 = { position: [2, 1, 0], radius: 1 }
|
|
29
|
-
|
|
30
|
-
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
test("it should prove that two touching circles intersect", () => {
|
|
34
|
-
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
35
|
-
const circle2 = { position: [3, 1, 0], radius: 1 }
|
|
36
|
-
|
|
37
|
-
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
test("it should prove that two non-touching circles do not intersect", () => {
|
|
41
|
-
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
42
|
-
const circle2 = { position: [4, 1, 0], radius: 1 }
|
|
43
|
-
|
|
44
|
-
expect(intersectsCircle(circle1, circle2)).toBe(false)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test("it should prove that a circle inside of a rectangle intersects with it", () => {
|
|
48
|
-
const circle = {
|
|
49
|
-
position: [1, 1, 0],
|
|
50
|
-
radius: 1,
|
|
51
|
-
}
|
|
52
|
-
const rectangle = {
|
|
53
|
-
position: [-1, -1, 0],
|
|
54
|
-
size: [4, 4, 0],
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test("it should prove that a circle
|
|
61
|
-
const circle = {
|
|
62
|
-
position: [1, 1, 0],
|
|
63
|
-
radius: 1,
|
|
64
|
-
}
|
|
65
|
-
const rectangle = {
|
|
66
|
-
position: [-
|
|
67
|
-
size: [2, 2, 0],
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
test("it should prove that a circle crossing a rectangle intersects with it", () => {
|
|
74
|
-
const circle = {
|
|
75
|
-
position: [1, 1, 0],
|
|
76
|
-
radius: 1,
|
|
77
|
-
}
|
|
78
|
-
const rectangle = {
|
|
79
|
-
position: [
|
|
80
|
-
size: [2, 2, 0],
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
test("it should prove that a circle outside of a rectangle does not intersect with it", () => {
|
|
87
|
-
const circle = {
|
|
88
|
-
position: [1, 1, 0],
|
|
89
|
-
radius: 1,
|
|
90
|
-
}
|
|
91
|
-
const rectangle = {
|
|
92
|
-
position: [-3, 0, 0],
|
|
93
|
-
size: [2, 2, 0],
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(false)
|
|
97
|
-
})
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
intersectsCircle,
|
|
5
|
+
intersectsPoint,
|
|
6
|
+
intersectsRectangle,
|
|
7
|
+
} from "./circle.js"
|
|
8
|
+
|
|
9
|
+
test("it should prove that a circle around a point intersects with it", () => {
|
|
10
|
+
const circle = {
|
|
11
|
+
position: [1, 1, 0],
|
|
12
|
+
radius: 1,
|
|
13
|
+
}
|
|
14
|
+
const point = [1.5, 1.5, 0]
|
|
15
|
+
|
|
16
|
+
expect(intersectsPoint(circle, point)).toBe(true)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test("it should prove that two equal circles intersect", () => {
|
|
20
|
+
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
21
|
+
const circle2 = { position: [1, 1, 0], radius: 1 }
|
|
22
|
+
|
|
23
|
+
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test("it should prove that two circles shifted by a small x intersect", () => {
|
|
27
|
+
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
28
|
+
const circle2 = { position: [2, 1, 0], radius: 1 }
|
|
29
|
+
|
|
30
|
+
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test("it should prove that two touching circles intersect", () => {
|
|
34
|
+
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
35
|
+
const circle2 = { position: [3, 1, 0], radius: 1 }
|
|
36
|
+
|
|
37
|
+
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test("it should prove that two non-touching circles do not intersect", () => {
|
|
41
|
+
const circle1 = { position: [1, 1, 0], radius: 1 }
|
|
42
|
+
const circle2 = { position: [4, 1, 0], radius: 1 }
|
|
43
|
+
|
|
44
|
+
expect(intersectsCircle(circle1, circle2)).toBe(false)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test("it should prove that a circle inside of a rectangle intersects with it", () => {
|
|
48
|
+
const circle = {
|
|
49
|
+
position: [1, 1, 0],
|
|
50
|
+
radius: 1,
|
|
51
|
+
}
|
|
52
|
+
const rectangle = {
|
|
53
|
+
position: [-1, -1, 0],
|
|
54
|
+
size: [4, 4, 0],
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test("it should prove that a circle touching the border of a rectangle intersects with it", () => {
|
|
61
|
+
const circle = {
|
|
62
|
+
position: [1, 1, 0],
|
|
63
|
+
radius: 1,
|
|
64
|
+
}
|
|
65
|
+
const rectangle = {
|
|
66
|
+
position: [-1, 1, 0], // Rectangle's right edge is at x=0, touching the circle's left edge.
|
|
67
|
+
size: [2, 2, 0],
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test("it should prove that a circle crossing a rectangle intersects with it", () => {
|
|
74
|
+
const circle = {
|
|
75
|
+
position: [1, 1, 0],
|
|
76
|
+
radius: 1,
|
|
77
|
+
}
|
|
78
|
+
const rectangle = {
|
|
79
|
+
position: [0, 0, 0],
|
|
80
|
+
size: [2, 2, 0],
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test("it should prove that a circle outside of a rectangle does not intersect with it", () => {
|
|
87
|
+
const circle = {
|
|
88
|
+
position: [1, 1, 0],
|
|
89
|
+
radius: 1,
|
|
90
|
+
}
|
|
91
|
+
const rectangle = {
|
|
92
|
+
position: [-3, 0, 0],
|
|
93
|
+
size: [2, 2, 0],
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
expect(intersectsRectangle(circle, rectangle)).toBe(false)
|
|
97
|
+
})
|
|
@@ -1,39 +1,70 @@
|
|
|
1
|
-
// @see https://jonathanwhiting.com/tutorial/collision/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
// @see https://jonathanwhiting.com/tutorial/collision/
|
|
2
|
+
|
|
3
|
+
import { intersectsRectangle } from "./rectangle.js"
|
|
4
|
+
|
|
5
|
+
const FIRST_TILE = 0
|
|
6
|
+
const HALF = 2
|
|
7
|
+
const LAST_ROW = 1
|
|
8
|
+
|
|
9
|
+
export function findCollisions(hitmask, target) {
|
|
10
|
+
const [tilemapX, tilemapY, tilemapZ] = hitmask.position
|
|
11
|
+
const [tileWidth, tileDepth] = hitmask.tileSize
|
|
12
|
+
const halfTileWidth = tileWidth / HALF
|
|
13
|
+
const halfTileDepth = tileDepth / HALF
|
|
14
|
+
|
|
15
|
+
const dRows = Math.ceil(hitmask.heights.length / hitmask.columns)
|
|
16
|
+
const tilemapWidth = hitmask.columns * tileWidth
|
|
17
|
+
const tilemapDepth = dRows * tileDepth
|
|
18
|
+
|
|
19
|
+
const tilemapLeft = tilemapX - tilemapWidth / HALF
|
|
20
|
+
const tilemapBack = tilemapZ - tilemapDepth / HALF
|
|
21
|
+
|
|
22
|
+
const [targetX, , targetZ] = target.position
|
|
23
|
+
const [targetWidth, , targetDepth] = target.size
|
|
24
|
+
const targetHalfWidth = targetWidth / HALF
|
|
25
|
+
const targetHalfDepth = targetDepth / HALF
|
|
26
|
+
|
|
27
|
+
const targetLeft = targetX - targetHalfWidth
|
|
28
|
+
const targetRight = targetX + targetHalfWidth
|
|
29
|
+
const targetBack = targetZ - targetHalfDepth
|
|
30
|
+
const targetFront = targetZ + targetHalfDepth
|
|
31
|
+
|
|
32
|
+
const minTileX = Math.floor((targetLeft - tilemapLeft) / tileWidth)
|
|
33
|
+
const maxTileX = Math.floor((targetRight - tilemapLeft) / tileWidth)
|
|
34
|
+
const minTileZ = Math.floor((targetBack - tilemapBack) / tileDepth)
|
|
35
|
+
const maxTileZ = Math.floor((targetFront - tilemapBack) / tileDepth)
|
|
36
|
+
|
|
37
|
+
for (let i = minTileX; i <= maxTileX; i++) {
|
|
38
|
+
for (let j = minTileZ; j <= maxTileZ; j++) {
|
|
39
|
+
if (
|
|
40
|
+
i < FIRST_TILE ||
|
|
41
|
+
i >= hitmask.columns ||
|
|
42
|
+
j < FIRST_TILE ||
|
|
43
|
+
j >= dRows
|
|
44
|
+
) {
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const invertedRow = dRows - LAST_ROW - j
|
|
49
|
+
const tileIndex = invertedRow * hitmask.columns + i
|
|
50
|
+
const tileHeightValue = hitmask.heights[tileIndex]
|
|
51
|
+
|
|
52
|
+
if (tileHeightValue) {
|
|
53
|
+
const tileRectangle = {
|
|
54
|
+
position: [
|
|
55
|
+
tilemapLeft + i * tileWidth + halfTileWidth,
|
|
56
|
+
tilemapY,
|
|
57
|
+
tilemapBack + j * tileDepth + halfTileDepth,
|
|
58
|
+
],
|
|
59
|
+
size: [tileWidth, tileHeightValue, tileDepth],
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (intersectsRectangle(target, tileRectangle)) {
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return false
|
|
70
|
+
}
|