@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.
Files changed (201) hide show
  1. package/README.md +39 -36
  2. package/package.json +10 -22
  3. package/src/engine/ai/movement/dynamic/align.js +63 -63
  4. package/src/engine/ai/movement/dynamic/arrive.js +42 -43
  5. package/src/engine/ai/movement/dynamic/evade.js +38 -38
  6. package/src/engine/ai/movement/dynamic/face.js +19 -20
  7. package/src/engine/ai/movement/dynamic/flee.js +45 -45
  8. package/src/engine/ai/movement/dynamic/look-where-youre-going.js +16 -17
  9. package/src/engine/ai/movement/dynamic/match-velocity.js +51 -50
  10. package/src/engine/ai/movement/dynamic/pursue.js +38 -38
  11. package/src/engine/ai/movement/dynamic/seek.js +44 -44
  12. package/src/engine/ai/movement/dynamic/wander.js +31 -32
  13. package/src/engine/ai/movement/kinematic/align.js +37 -37
  14. package/src/engine/ai/movement/kinematic/arrive.js +42 -42
  15. package/src/engine/ai/movement/kinematic/face.js +19 -20
  16. package/src/engine/ai/movement/kinematic/flee.js +26 -26
  17. package/src/engine/ai/movement/kinematic/seek.js +26 -26
  18. package/src/engine/ai/movement/kinematic/seek.test.js +42 -42
  19. package/src/engine/ai/movement/kinematic/wander-as-seek.js +31 -31
  20. package/src/engine/ai/movement/kinematic/wander.js +27 -27
  21. package/src/engine/animation/sprite.js +101 -0
  22. package/src/engine/animation/ticker.js +38 -0
  23. package/src/engine/behaviors/camera.js +68 -0
  24. package/src/engine/behaviors/controls/dynamic/modern.js +76 -0
  25. package/src/engine/behaviors/controls/dynamic/shooter.js +84 -0
  26. package/src/engine/behaviors/controls/dynamic/tank.js +69 -0
  27. package/src/engine/behaviors/controls/event-handlers.js +17 -0
  28. package/src/engine/behaviors/controls/kinematic/modern.js +76 -0
  29. package/src/engine/behaviors/controls/kinematic/shooter.js +82 -0
  30. package/src/engine/behaviors/controls/kinematic/tank.js +67 -0
  31. package/src/engine/behaviors/debug/collision.js +35 -0
  32. package/src/engine/behaviors/fps.js +29 -0
  33. package/src/engine/behaviors/fsm.js +33 -0
  34. package/src/{game/decorators → engine/behaviors}/fsm.test.js +49 -56
  35. package/src/engine/behaviors/game.js +15 -0
  36. package/src/engine/behaviors/input/controls.js +37 -0
  37. package/src/engine/behaviors/input/gamepad.js +114 -0
  38. package/src/engine/behaviors/input/input.js +48 -0
  39. package/src/engine/behaviors/input/keyboard.js +64 -0
  40. package/src/engine/behaviors/input/mouse.js +91 -0
  41. package/src/engine/behaviors/physics/bouncy.js +25 -0
  42. package/src/engine/behaviors/physics/clamped.js +36 -0
  43. package/src/{game/decorators/collisions.js → engine/behaviors/physics/collidable.js} +20 -24
  44. package/src/engine/behaviors/physics/jumpable.js +145 -0
  45. package/src/engine/behaviors/ui/button.js +17 -0
  46. package/src/engine/collision/detection.js +110 -115
  47. package/src/engine/core/api.js +34 -0
  48. package/src/engine/core/dev-tools.js +135 -0
  49. package/src/engine/core/engine.js +119 -0
  50. package/src/engine/core/loop.js +15 -0
  51. package/src/engine/{loop → core/loops}/animation-frame.js +25 -26
  52. package/src/engine/{loop → core/loops}/elapsed.js +22 -23
  53. package/src/engine/{loop → core/loops}/fixed.js +27 -28
  54. package/src/engine/{loop → core/loops}/flash.js +13 -14
  55. package/src/engine/{loop → core/loops}/lag.js +26 -27
  56. package/src/engine/core/select.js +26 -0
  57. package/src/engine/core/store.js +178 -0
  58. package/src/engine/core/store.test.js +110 -0
  59. package/src/engine/movement/dynamic/modern.js +21 -24
  60. package/src/engine/movement/dynamic/tank.js +43 -43
  61. package/src/engine/movement/kinematic/modern.js +16 -16
  62. package/src/engine/movement/kinematic/modern.test.js +27 -27
  63. package/src/engine/movement/kinematic/tank.js +27 -27
  64. package/src/engine/physics/bounds.js +138 -0
  65. package/src/engine/physics/position.js +43 -0
  66. package/src/engine/physics/position.test.js +80 -0
  67. package/src/engine/systems/sprite-animation.js +27 -0
  68. package/src/main.js +10 -5
  69. package/src/renderers/canvas/absolute-position.js +18 -0
  70. package/src/renderers/canvas/camera.js +13 -0
  71. package/src/renderers/canvas/canvas-renderer.js +68 -0
  72. package/src/{ui → renderers}/canvas/character.js +38 -35
  73. package/src/{ui → renderers}/canvas/form/button.js +25 -25
  74. package/src/{ui → renderers}/canvas/fps.js +18 -18
  75. package/src/renderers/canvas/image/hitmask.js +51 -0
  76. package/src/{ui → renderers}/canvas/image/image.js +34 -37
  77. package/src/{ui → renderers}/canvas/image/sprite.js +49 -49
  78. package/src/{ui → renderers}/canvas/image/tilemap.js +66 -64
  79. package/src/{ui → renderers}/canvas/mouse.js +37 -37
  80. package/src/renderers/canvas/rendering-system.js +79 -0
  81. package/src/{ui → renderers}/canvas/shapes/circle.js +29 -31
  82. package/src/{ui → renderers}/canvas/shapes/rectangle.js +27 -31
  83. package/src/renderers/react/game/character/index.jsx +20 -0
  84. package/src/{ui → renderers}/react/game/cursor/index.jsx +20 -20
  85. package/src/{ui → renderers}/react/game/form/fields/field/index.jsx +56 -56
  86. package/src/{ui → renderers}/react/game/form/fields/index.jsx +12 -12
  87. package/src/{ui → renderers}/react/game/form/index.jsx +22 -22
  88. package/src/{ui → renderers}/react/game/fps/index.jsx +16 -16
  89. package/src/{ui → renderers}/react/game/game.jsx +72 -71
  90. package/src/{ui → renderers}/react/game/index.jsx +29 -29
  91. package/src/{ui → renderers}/react/game/platform/index.jsx +30 -30
  92. package/src/{ui → renderers}/react/game/scene/index.jsx +27 -25
  93. package/src/{ui → renderers}/react/game/sprite/index.jsx +60 -58
  94. package/src/{ui → renderers}/react/game/stats/index.jsx +22 -22
  95. package/src/{ui → renderers}/react/hocs/with-absolute-position/index.jsx +20 -20
  96. package/src/{ui → renderers}/react/index.jsx +9 -9
  97. package/src/utils/algorithms/decision-tree.js +24 -24
  98. package/src/utils/algorithms/decision-tree.test.js +153 -102
  99. package/src/utils/algorithms/path-finding.js +155 -155
  100. package/src/utils/algorithms/path-finding.test.js +151 -151
  101. package/src/utils/data-structures/array.js +83 -83
  102. package/src/utils/data-structures/array.test.js +173 -173
  103. package/src/utils/data-structures/board.js +159 -159
  104. package/src/utils/data-structures/board.test.js +242 -242
  105. package/src/utils/data-structures/boolean.js +9 -9
  106. package/src/utils/data-structures/heap.js +164 -164
  107. package/src/utils/data-structures/heap.test.js +103 -103
  108. package/src/utils/data-structures/object.js +138 -102
  109. package/src/utils/data-structures/object.test.js +218 -121
  110. package/src/utils/data-structures/objects.js +66 -48
  111. package/src/utils/data-structures/objects.test.js +99 -99
  112. package/src/utils/data-structures/tree.js +36 -36
  113. package/src/utils/data-structures/tree.test.js +33 -33
  114. package/src/utils/functions/functions.js +19 -19
  115. package/src/utils/functions/functions.test.js +23 -23
  116. package/src/utils/math/geometry/circle.js +70 -117
  117. package/src/utils/math/geometry/circle.test.js +97 -97
  118. package/src/utils/math/geometry/hitmask.js +70 -39
  119. package/src/utils/math/geometry/hitmask.test.js +155 -84
  120. package/src/utils/math/geometry/line.js +35 -35
  121. package/src/utils/math/geometry/line.test.js +49 -49
  122. package/src/utils/math/geometry/point.js +78 -71
  123. package/src/utils/math/geometry/point.test.js +81 -81
  124. package/src/utils/math/geometry/rectangle.js +76 -45
  125. package/src/utils/math/geometry/rectangle.test.js +42 -42
  126. package/src/utils/math/geometry/segment.js +80 -80
  127. package/src/utils/math/geometry/segment.test.js +183 -183
  128. package/src/utils/math/geometry/triangle.js +15 -15
  129. package/src/utils/math/geometry/triangle.test.js +11 -11
  130. package/src/utils/math/linear-algebra/2d.js +28 -28
  131. package/src/utils/math/linear-algebra/2d.test.js +17 -17
  132. package/src/utils/math/linear-algebra/quaternion.js +22 -22
  133. package/src/utils/math/linear-algebra/quaternion.test.js +25 -25
  134. package/src/utils/math/linear-algebra/quaternions.js +20 -20
  135. package/src/utils/math/linear-algebra/quaternions.test.js +29 -29
  136. package/src/utils/math/linear-algebra/vector.js +327 -302
  137. package/src/utils/math/linear-algebra/vector.test.js +265 -257
  138. package/src/utils/math/linear-algebra/vectors.js +122 -122
  139. package/src/utils/math/linear-algebra/vectors.test.js +65 -65
  140. package/src/utils/math/linear-interpolation.js +9 -0
  141. package/src/utils/math/numbers.js +90 -90
  142. package/src/utils/math/numbers.test.js +137 -137
  143. package/src/utils/math/rng.js +44 -44
  144. package/src/utils/math/rng.test.js +39 -39
  145. package/src/utils/math/statistics.js +43 -43
  146. package/src/utils/math/statistics.test.js +47 -47
  147. package/src/utils/math/trigonometry.js +89 -89
  148. package/src/utils/math/trigonometry.test.js +52 -52
  149. package/src/utils/physics/acceleration.js +61 -63
  150. package/src/utils/physics/friction.js +28 -30
  151. package/src/utils/physics/friction.test.js +42 -44
  152. package/src/utils/physics/gravity.js +69 -71
  153. package/src/utils/physics/gravity.test.js +77 -80
  154. package/src/utils/physics/jump.js +31 -41
  155. package/src/utils/physics/velocity.js +36 -38
  156. package/src/engine/loop.js +0 -15
  157. package/src/engine/store.js +0 -174
  158. package/src/engine/store.test.js +0 -256
  159. package/src/engine.js +0 -74
  160. package/src/game/animation.js +0 -26
  161. package/src/game/bounds.js +0 -66
  162. package/src/game/decorators/character.js +0 -5
  163. package/src/game/decorators/clamp-to-bounds.js +0 -15
  164. package/src/game/decorators/controls/dynamic/modern.js +0 -48
  165. package/src/game/decorators/controls/dynamic/shooter.js +0 -47
  166. package/src/game/decorators/controls/dynamic/tank.js +0 -55
  167. package/src/game/decorators/controls/kinematic/modern.js +0 -49
  168. package/src/game/decorators/controls/kinematic/shooter.js +0 -45
  169. package/src/game/decorators/controls/kinematic/tank.js +0 -52
  170. package/src/game/decorators/debug/collisions.js +0 -32
  171. package/src/game/decorators/double-jump.js +0 -70
  172. package/src/game/decorators/fps.js +0 -30
  173. package/src/game/decorators/fsm.js +0 -27
  174. package/src/game/decorators/game.js +0 -11
  175. package/src/game/decorators/image/image.js +0 -5
  176. package/src/game/decorators/image/sprite.js +0 -5
  177. package/src/game/decorators/image/tilemap.js +0 -5
  178. package/src/game/decorators/input/controls.js +0 -27
  179. package/src/game/decorators/input/gamepad.js +0 -74
  180. package/src/game/decorators/input/input.js +0 -41
  181. package/src/game/decorators/input/keyboard.js +0 -49
  182. package/src/game/decorators/input/mouse.js +0 -65
  183. package/src/game/decorators/jump.js +0 -72
  184. package/src/game/decorators/platform.js +0 -5
  185. package/src/game/decorators/ui/button.js +0 -21
  186. package/src/game/sprite.js +0 -119
  187. package/src/ui/canvas/absolute-position.js +0 -17
  188. package/src/ui/canvas/image/hitmask.js +0 -37
  189. package/src/ui/canvas.js +0 -81
  190. package/src/ui/react/game/character/index.jsx +0 -30
  191. package/src/utils/math/geometry/platform.js +0 -42
  192. package/src/utils/math/geometry/platform.test.js +0 -133
  193. /package/src/{ui → renderers}/react/game/character/character.module.scss +0 -0
  194. /package/src/{ui → renderers}/react/game/cursor/cursor.module.scss +0 -0
  195. /package/src/{ui → renderers}/react/game/form/fields/field/field.module.scss +0 -0
  196. /package/src/{ui → renderers}/react/game/form/fields/fields.module.scss +0 -0
  197. /package/src/{ui → renderers}/react/game/form/form.module.scss +0 -0
  198. /package/src/{ui → renderers}/react/game/platform/platform.module.scss +0 -0
  199. /package/src/{ui → renderers}/react/game/scene/scene.module.scss +0 -0
  200. /package/src/{ui → renderers}/react/game/sprite/sprite.module.css +0 -0
  201. /package/src/{ui → renderers}/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -0
@@ -1,119 +0,0 @@
1
- /* eslint-disable no-magic-numbers */
2
- import { Animation } from "@inglorious/game/animation.js"
3
- import { mod } from "@inglorious/utils/math/numbers.js"
4
- import { pi, toRange } from "@inglorious/utils/math/trigonometry.js"
5
-
6
- const BEFORE = -1
7
- const AFTER = 1
8
-
9
- export const Sprite = {
10
- move2,
11
- move4,
12
- move6,
13
- move8,
14
- play,
15
- }
16
-
17
- function move2(instance) {
18
- const directions = 2
19
- const multiple = pi() / directions
20
- const theta = toRange(instance.orientation) / multiple
21
-
22
- if (theta > 0 + BEFORE && theta < 0 + AFTER) {
23
- return "right"
24
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
25
- return "left"
26
- }
27
-
28
- return instance.sprite.state ?? "right"
29
- }
30
-
31
- function move4(instance) {
32
- const directions = 4
33
- const multiple = pi() / directions
34
- const theta = toRange(instance.orientation) / multiple
35
-
36
- if (theta >= -2 + BEFORE && theta < -2 + AFTER) {
37
- return "down"
38
- } else if (theta >= 0 + BEFORE && theta < 0 + AFTER) {
39
- return "right"
40
- } else if (theta >= 2 + BEFORE && theta < 2 + AFTER) {
41
- return "up"
42
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
43
- return "left"
44
- }
45
-
46
- return instance.sprite.state ?? "down"
47
- }
48
-
49
- function move6(instance) {
50
- const directions = 6
51
- const multiple = pi() / directions
52
- const theta = toRange(instance.orientation) / multiple
53
-
54
- if (theta >= -6 + BEFORE && theta < -6 + AFTER) {
55
- return "leftDown"
56
- } else if (theta >= -4 + BEFORE && theta < -4 + AFTER) {
57
- return "down"
58
- } else if (theta >= -2 + BEFORE && theta < -2 + AFTER) {
59
- return "rightDown"
60
- } else if (theta >= 0 + BEFORE && theta < 0 + AFTER) {
61
- return "right"
62
- } else if (theta >= 2 + BEFORE && theta < 2 + AFTER) {
63
- return "rightUp"
64
- } else if (theta >= 4 + BEFORE && theta < 4 + AFTER) {
65
- return "up"
66
- } else if (theta >= 6 + BEFORE && theta < 6 + AFTER) {
67
- return "leftUp"
68
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
69
- return "left"
70
- }
71
-
72
- return instance.sprite.state ?? "down"
73
- }
74
-
75
- function move8(instance) {
76
- const directions = 8
77
- const multiple = pi() / directions
78
- const theta = toRange(instance.orientation) / multiple
79
-
80
- if (theta >= -6 + BEFORE && theta < -6 + AFTER) {
81
- return "leftDown"
82
- } else if (theta >= -4 + BEFORE && theta < -4 + AFTER) {
83
- return "down"
84
- } else if (theta >= -2 + BEFORE && theta < -2 + AFTER) {
85
- return "rightDown"
86
- } else if (theta >= 0 + BEFORE && theta < 0 + AFTER) {
87
- return "right"
88
- } else if (theta >= 2 + BEFORE && theta < 2 + AFTER) {
89
- return "rightUp"
90
- } else if (theta >= 4 + BEFORE && theta < 4 + AFTER) {
91
- return "up"
92
- } else if (theta >= 6 + BEFORE && theta < 6 + AFTER) {
93
- return "leftUp"
94
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
95
- return "left"
96
- }
97
-
98
- return instance.sprite.state ?? "down"
99
- }
100
-
101
- function play(spriteState, instance, options) {
102
- Animation.play("sprite", spriteState, instance, { ...options, onTick })
103
- }
104
-
105
- function onTick(instance, options) {
106
- const { notify } = options
107
-
108
- const { frames, state } = instance.sprite
109
-
110
- const framesLength = frames[state].length
111
-
112
- instance.sprite.value = mod(instance.sprite.value + 1, framesLength)
113
- if (instance.sprite.value === framesLength - 1) {
114
- notify({
115
- id: `sprite:animationEnd`,
116
- payload: { id: instance.id, spriteState: state },
117
- })
118
- }
119
- }
@@ -1,17 +0,0 @@
1
- import { snap, zero } from "@inglorious/utils/math/linear-algebra/vector.js"
2
-
3
- export function absolutePosition(draw) {
4
- return (ctx, instance, options = {}) => {
5
- const { position = zero() } = instance
6
- const { instances } = options
7
- const [, , , screenHeight] = instances.game.bounds
8
- const [x, y, z] = snap(position)
9
-
10
- ctx.save()
11
-
12
- ctx.translate(x, screenHeight - y - z)
13
- draw(ctx, instance, options)
14
-
15
- ctx.restore()
16
- }
17
- }
@@ -1,37 +0,0 @@
1
- import drawRectangle from "@inglorious/ui/canvas/shapes/rectangle.js"
2
- import { max } from "@inglorious/utils/data-structures/array.js"
3
-
4
- const NO_Y = 0
5
- const MAX_HUE = 255
6
-
7
- export default function draw(ctx, instance, options) {
8
- const { tileSize, columns, heights } = instance
9
-
10
- const [tileWidth, tileHeight] = tileSize
11
- const rows = Math.ceil(heights.length / columns)
12
- const height = rows * tileHeight
13
-
14
- const minH = 0
15
- const maxH = max(heights)
16
-
17
- heights.forEach((h, index) => {
18
- const x = (index % columns) * tileWidth
19
- const z = Math.floor(index / columns) * tileHeight - height
20
-
21
- ctx.save()
22
-
23
- const normalizedH = (h - minH) / (maxH - minH)
24
- const hue = MAX_HUE - normalizedH * MAX_HUE
25
-
26
- const instance = {
27
- offset: [x, NO_Y, z],
28
- size: [tileWidth, NO_Y, tileHeight],
29
- color: "transparent",
30
- backgroundColor: `hsla(${hue}, 100%, 50%, 0.2)`,
31
- }
32
-
33
- drawRectangle(ctx, instance, options)
34
-
35
- ctx.restore()
36
- })
37
- }
package/src/ui/canvas.js DELETED
@@ -1,81 +0,0 @@
1
- import Engine from "@inglorious/engine.js"
2
- import { track } from "@inglorious/game/decorators/input/mouse.js"
3
-
4
- import { absolutePosition } from "./canvas/absolute-position.js"
5
-
6
- const Y = 1
7
- const Z = 2
8
-
9
- export function start(config, canvas) {
10
- const ctx = canvas.getContext("2d")
11
- const engine = new Engine(config, { render: render(ctx) })
12
-
13
- const { game } = engine._store.getState().instances
14
- const [, , width, height] = game.bounds
15
-
16
- canvas.style.width = `${width}px`
17
- canvas.style.height = `${height}px`
18
- const dpi = window.devicePixelRatio
19
- canvas.width = Math.floor(width * dpi)
20
- canvas.height = Math.floor(height * dpi)
21
- ctx.scale(dpi, dpi)
22
-
23
- if (game.pixelated) {
24
- canvas.style.imageRendering = "pixelated"
25
- ctx.textRendering = "geometricPrecision"
26
- }
27
-
28
- document.addEventListener("keypress", (event) => {
29
- if (event.key === "p") {
30
- engine.isRunning ? engine.stop() : engine.start()
31
- }
32
- })
33
-
34
- const { onMouseMove, onClick } = track(canvas, {
35
- notify: engine.notify,
36
- })
37
-
38
- canvas.addEventListener("mousemove", onMouseMove)
39
- canvas.addEventListener("click", onClick)
40
-
41
- engine.start()
42
- }
43
-
44
- function render(ctx) {
45
- return (options) => {
46
- const { types, instances } = options
47
-
48
- const { game, mouse, ...rest } = instances
49
-
50
- const [x, y, width, height] = game.bounds
51
- ctx.fillStyle = "lightgrey"
52
- ctx.fillRect(x, y, width, height)
53
- if (game.pixelated) {
54
- ctx.imageSmoothingEnabled = false
55
- }
56
-
57
- Object.values(rest)
58
- .filter(({ position }) => position)
59
- .toSorted(
60
- (a, b) =>
61
- a.layer - b.layer ||
62
- a.position[Y] - b.position[Y] ||
63
- b.position[Z] - a.position[Z],
64
- )
65
- .forEach((instance) =>
66
- draw(ctx, instance, { ...options, type: types[instance.type] }),
67
- )
68
-
69
- if (mouse) {
70
- draw(ctx, mouse, { ...options, type: types[mouse.type] })
71
- }
72
- }
73
- }
74
-
75
- function draw(ctx, instance, options) {
76
- const draw = options.type.draw
77
-
78
- if (draw) {
79
- absolutePosition(draw)(ctx, instance, options)
80
- }
81
- }
@@ -1,30 +0,0 @@
1
- import { useDispatch } from "react-redux"
2
-
3
- import classes from "./character.module.scss"
4
-
5
- const DEFAULT_SIZE = 24
6
- const DEFAULT_ORIENTATION = 0
7
-
8
- export default function Character({ id, type, instance, className, style }) {
9
- const notify = useDispatch()
10
-
11
- const size = type.size ?? DEFAULT_SIZE
12
- const { orientation = DEFAULT_ORIENTATION } = instance
13
-
14
- const handleClick = (event) => {
15
- event.stopPropagation()
16
- notify({ id: "instance:click", payload: id })
17
- }
18
-
19
- return (
20
- <div
21
- className={`${classes.character} ${className}`}
22
- style={{
23
- ...style,
24
- "--size": `${size}px`,
25
- "--angle": `${-orientation}rad`,
26
- }}
27
- onClick={handleClick}
28
- />
29
- )
30
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Checks if a platform intersects with a circle in 3D space.
3
- * @param {Platform} platform - The platform to check.
4
- * @param {Circle} circle - The circle to check.
5
- * @returns {boolean} True if the platform intersects the circle, false otherwise.
6
- */
7
- export function intersectsCircle(platform, circle) {
8
- const [left, top, front] = platform.position
9
- const [extension, elevation, thickness] = platform.size
10
-
11
- const [x, y, z] = circle.position
12
-
13
- const lowestPoint = y - circle.radius
14
- const isAbove = lowestPoint <= top && lowestPoint >= top - elevation
15
-
16
- const isOverlappingX = x >= left && x <= left + extension
17
- const isOverlappingZ = z >= front && z <= front + thickness
18
-
19
- return isAbove && isOverlappingX && isOverlappingZ
20
- }
21
-
22
- /**
23
- * Determines whether platform intersects with a rectangle in 3D space.
24
- *
25
- * @param {Platform} platform - The platform defined by its position (top-left-front corner) and size (extension, elevation, thickness).
26
- * @param {Rectangle} rectangle - The rectangle defined by its position (top-left-front corner) and size (width, height, depth).
27
- * @returns {boolean} True if the platform intersects the rectangle, false otherwise.
28
- */
29
- export function intersectsRectangle(platform, rectangle) {
30
- const [left, top, front] = platform.position
31
- const [extension, elevation, thickness] = platform.size
32
-
33
- const [x, y, z] = rectangle.position
34
- const [width, , depth] = rectangle.size
35
-
36
- const isAbove = y >= top && y <= top + elevation
37
-
38
- const isOverlappingX = x + width >= left && x <= left + extension
39
- const isOverlappingZ = z + depth >= front && z <= front + thickness
40
-
41
- return isAbove && isOverlappingX && isOverlappingZ
42
- }
@@ -1,133 +0,0 @@
1
- import { expect, test } from "vitest"
2
-
3
- import { intersectsCircle, intersectsRectangle } from "./platform"
4
-
5
- test("it should prove that a circle right above a platform intersects with it", () => {
6
- const platform = {
7
- position: [-1, 0, 0],
8
- size: [2, 1, 0],
9
- }
10
- const circle = {
11
- position: [1, 1, 0],
12
- radius: 1,
13
- }
14
-
15
- expect(intersectsCircle(platform, circle)).toBe(true)
16
- })
17
-
18
- test("it should prove that a circle way above a platform intersects with it", () => {
19
- const platform = {
20
- position: [0, 0, -2],
21
- size: [2, 1, 0],
22
- }
23
- const circle = {
24
- position: [1, 1, 0],
25
- radius: 1,
26
- }
27
-
28
- expect(intersectsCircle(platform, circle)).toBe(false)
29
- })
30
-
31
- test("it should prove that a circle crossing a platform does not intersect with it", () => {
32
- const platform = {
33
- position: [-1, -1, 0],
34
- size: [2, 2, 0],
35
- }
36
- const circle = {
37
- position: [1, 1, 0],
38
- radius: 1,
39
- }
40
-
41
- expect(intersectsCircle(platform, circle)).toBe(false)
42
- })
43
-
44
- test("it should prove that a circle below a platform does not intersect with it", () => {
45
- const platform = {
46
- position: [0, 2, 0],
47
- size: [2, 1, 0],
48
- }
49
- const circle = {
50
- position: [1, 1, 0],
51
- radius: 1,
52
- }
53
-
54
- expect(intersectsCircle(platform, circle)).toBe(false)
55
- })
56
-
57
- test("it should prove that a circle not crossing a platform horizontally does not intersect with it", () => {
58
- const platform = {
59
- position: [-3, -1, 0],
60
- size: [2, 1, 0],
61
- }
62
- const circle = {
63
- position: [1, 1, 0],
64
- radius: 1,
65
- }
66
-
67
- expect(intersectsCircle(platform, circle)).toBe(false)
68
- })
69
-
70
- test("it should prove that a rectangle crossing a platform from above intersects with it", () => {
71
- const platform = {
72
- position: [0, -1, 0],
73
- size: [2, 2, 0],
74
- }
75
- const rectangle = {
76
- position: [0, 0, 0],
77
- size: [2, 2, 0],
78
- }
79
-
80
- expect(intersectsRectangle(platform, rectangle)).toBe(true)
81
- })
82
-
83
- test("it should prove that a rectangle right on top of a platform intersects with it", () => {
84
- const platform = {
85
- position: [0, -2, 0],
86
- size: [2, 2, 0],
87
- }
88
- const rectangle = {
89
- position: [0, 0, 0],
90
- size: [2, 2, 0],
91
- }
92
-
93
- expect(intersectsRectangle(platform, rectangle)).toBe(true)
94
- })
95
-
96
- test("it should prove that a rectangle crossing a platform from below does not intersect with it", () => {
97
- const platform = {
98
- position: [0, 1, 0],
99
- size: [2, 2, 0],
100
- }
101
- const rectangle = {
102
- position: [0, 0, 0],
103
- size: [2, 2, 0],
104
- }
105
-
106
- expect(intersectsRectangle(platform, rectangle)).toBe(false)
107
- })
108
-
109
- test("it should prove that a rectangle below a platform does not intersect with it", () => {
110
- const platform = {
111
- position: [0, -3, 0],
112
- size: [2, 2, 0],
113
- }
114
- const rectangle = {
115
- position: [0, 0, 0],
116
- size: [2, 2, 0],
117
- }
118
-
119
- expect(intersectsRectangle(platform, rectangle)).toBe(false)
120
- })
121
-
122
- test("it should prove that a rectangle not crossing a platform horizontally does not intersect with it", () => {
123
- const platform = {
124
- position: [-3, 0, 0],
125
- size: [2, 2, 0],
126
- }
127
- const rectangle = {
128
- position: [0, 0, 0],
129
- size: [2, 2, 0],
130
- }
131
-
132
- expect(intersectsRectangle(platform, rectangle)).toBe(false)
133
- })