@inglorious/engine 0.1.1 → 0.3.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 +75 -72
- package/package.json +15 -37
- package/src/{engine/ai → ai}/movement/dynamic/align.js +9 -9
- package/src/{engine/ai → ai}/movement/dynamic/arrive.js +9 -10
- package/src/{engine/ai → ai}/movement/dynamic/evade.js +9 -9
- package/src/{engine/ai → ai}/movement/dynamic/face.js +5 -6
- package/src/{engine/ai/movement/dynamic/seek.js → ai/movement/dynamic/flee.js} +8 -7
- package/src/ai/movement/dynamic/look-where-youre-going.js +16 -0
- package/src/{engine/ai → ai}/movement/dynamic/match-velocity.js +9 -8
- package/src/{engine/ai → ai}/movement/dynamic/pursue.js +9 -9
- package/src/{engine/ai/movement/dynamic/flee.js → ai/movement/dynamic/seek.js} +7 -8
- package/src/{engine/ai → ai}/movement/dynamic/wander.js +9 -10
- package/src/{engine/ai → ai}/movement/kinematic/align.js +7 -7
- package/src/{engine/ai → ai}/movement/kinematic/arrive.js +8 -8
- package/src/{engine/ai → ai}/movement/kinematic/face.js +5 -6
- package/src/{engine/ai → ai}/movement/kinematic/flee.js +5 -5
- package/src/{engine/ai → ai}/movement/kinematic/seek.js +5 -5
- package/src/{engine/ai → ai}/movement/kinematic/seek.test.js +10 -10
- package/src/{engine/ai → ai}/movement/kinematic/wander-as-seek.js +9 -9
- package/src/{engine/ai → ai}/movement/kinematic/wander.js +5 -5
- package/src/animation/sprite.js +101 -0
- package/src/animation/ticker.js +38 -0
- package/src/behaviors/camera.js +68 -0
- package/src/behaviors/controls/dynamic/modern.js +76 -0
- package/src/behaviors/controls/dynamic/shooter.js +84 -0
- package/src/behaviors/controls/dynamic/tank.js +69 -0
- package/src/behaviors/controls/event-handlers.js +17 -0
- package/src/behaviors/controls/kinematic/modern.js +76 -0
- package/src/behaviors/controls/kinematic/shooter.js +82 -0
- package/src/behaviors/controls/kinematic/tank.js +67 -0
- package/src/behaviors/debug/collision.js +29 -0
- package/src/behaviors/fps.js +29 -0
- package/src/behaviors/fsm.js +33 -0
- package/src/{game/decorators → behaviors}/fsm.test.js +15 -22
- package/src/behaviors/game.js +15 -0
- package/src/behaviors/input/controls.js +37 -0
- package/src/behaviors/input/gamepad.js +114 -0
- package/src/behaviors/input/input.js +48 -0
- package/src/behaviors/input/keyboard.js +64 -0
- package/src/behaviors/input/mouse.js +91 -0
- package/src/behaviors/physics/bouncy.js +25 -0
- package/src/behaviors/physics/clamped.js +36 -0
- package/src/{game/decorators/collisions.js → behaviors/physics/collidable.js} +3 -7
- package/src/behaviors/physics/jumpable.js +145 -0
- package/src/behaviors/ui/button.js +17 -0
- package/src/collision/detection.js +110 -0
- package/src/core/api.js +34 -0
- package/src/core/dev-tools.js +135 -0
- package/src/core/engine.js +119 -0
- package/src/core/loop.js +15 -0
- package/src/{engine/loop → core/loops}/animation-frame.js +1 -2
- package/src/{engine/loop → core/loops}/elapsed.js +1 -2
- package/src/{engine/loop → core/loops}/fixed.js +1 -2
- package/src/{engine/loop → core/loops}/flash.js +1 -2
- package/src/{engine/loop → core/loops}/lag.js +1 -2
- package/src/core/select.js +26 -0
- package/src/core/store.js +178 -0
- package/src/core/store.test.js +110 -0
- package/src/main.js +7 -2
- package/src/{engine/movement → movement}/dynamic/modern.js +3 -6
- package/src/{engine/movement → movement}/dynamic/tank.js +9 -9
- package/src/{engine/movement → movement}/kinematic/modern.js +3 -3
- package/src/movement/kinematic/modern.test.js +27 -0
- package/src/{engine/movement → movement}/kinematic/tank.js +5 -5
- package/src/physics/bounds.js +138 -0
- package/src/physics/position.js +43 -0
- package/src/physics/position.test.js +80 -0
- package/src/systems/sprite-animation.js +27 -0
- package/src/engine/ai/movement/dynamic/look-where-youre-going.js +0 -17
- package/src/engine/collision/detection.js +0 -115
- package/src/engine/loop.js +0 -15
- package/src/engine/movement/kinematic/modern.test.js +0 -27
- 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/character.js +0 -35
- package/src/ui/canvas/form/button.js +0 -25
- package/src/ui/canvas/fps.js +0 -18
- package/src/ui/canvas/image/hitmask.js +0 -37
- package/src/ui/canvas/image/image.js +0 -37
- package/src/ui/canvas/image/sprite.js +0 -49
- package/src/ui/canvas/image/tilemap.js +0 -64
- package/src/ui/canvas/mouse.js +0 -37
- package/src/ui/canvas/shapes/circle.js +0 -31
- package/src/ui/canvas/shapes/rectangle.js +0 -31
- package/src/ui/canvas.js +0 -81
- package/src/ui/react/game/character/character.module.scss +0 -17
- package/src/ui/react/game/character/index.jsx +0 -30
- package/src/ui/react/game/cursor/cursor.module.scss +0 -47
- package/src/ui/react/game/cursor/index.jsx +0 -20
- package/src/ui/react/game/form/fields/field/field.module.scss +0 -5
- package/src/ui/react/game/form/fields/field/index.jsx +0 -56
- package/src/ui/react/game/form/fields/fields.module.scss +0 -48
- package/src/ui/react/game/form/fields/index.jsx +0 -12
- package/src/ui/react/game/form/form.module.scss +0 -18
- package/src/ui/react/game/form/index.jsx +0 -22
- package/src/ui/react/game/fps/index.jsx +0 -16
- package/src/ui/react/game/game.jsx +0 -71
- package/src/ui/react/game/index.jsx +0 -29
- package/src/ui/react/game/platform/index.jsx +0 -30
- package/src/ui/react/game/platform/platform.module.scss +0 -7
- package/src/ui/react/game/scene/index.jsx +0 -25
- package/src/ui/react/game/scene/scene.module.scss +0 -9
- package/src/ui/react/game/sprite/index.jsx +0 -58
- package/src/ui/react/game/sprite/sprite.module.css +0 -3
- package/src/ui/react/game/stats/index.jsx +0 -22
- package/src/ui/react/hocs/with-absolute-position/index.jsx +0 -20
- package/src/ui/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -5
- package/src/ui/react/index.jsx +0 -9
- package/src/utils/algorithms/decision-tree.js +0 -24
- package/src/utils/algorithms/decision-tree.test.js +0 -102
- package/src/utils/algorithms/path-finding.js +0 -155
- package/src/utils/algorithms/path-finding.test.js +0 -151
- package/src/utils/algorithms/types.d.ts +0 -28
- package/src/utils/data-structures/array.js +0 -83
- package/src/utils/data-structures/array.test.js +0 -173
- package/src/utils/data-structures/board.js +0 -159
- package/src/utils/data-structures/board.test.js +0 -242
- package/src/utils/data-structures/boolean.js +0 -9
- package/src/utils/data-structures/heap.js +0 -164
- package/src/utils/data-structures/heap.test.js +0 -103
- package/src/utils/data-structures/object.js +0 -102
- package/src/utils/data-structures/object.test.js +0 -121
- package/src/utils/data-structures/objects.js +0 -48
- package/src/utils/data-structures/objects.test.js +0 -99
- package/src/utils/data-structures/tree.js +0 -36
- package/src/utils/data-structures/tree.test.js +0 -33
- package/src/utils/data-structures/types.d.ts +0 -4
- package/src/utils/functions/functions.js +0 -19
- package/src/utils/functions/functions.test.js +0 -23
- package/src/utils/math/geometry/circle.js +0 -117
- package/src/utils/math/geometry/circle.test.js +0 -97
- package/src/utils/math/geometry/hitmask.js +0 -39
- package/src/utils/math/geometry/hitmask.test.js +0 -84
- package/src/utils/math/geometry/line.js +0 -35
- package/src/utils/math/geometry/line.test.js +0 -49
- package/src/utils/math/geometry/platform.js +0 -42
- package/src/utils/math/geometry/platform.test.js +0 -133
- package/src/utils/math/geometry/point.js +0 -71
- package/src/utils/math/geometry/point.test.js +0 -81
- package/src/utils/math/geometry/rectangle.js +0 -45
- package/src/utils/math/geometry/rectangle.test.js +0 -42
- package/src/utils/math/geometry/segment.js +0 -80
- package/src/utils/math/geometry/segment.test.js +0 -183
- package/src/utils/math/geometry/triangle.js +0 -15
- package/src/utils/math/geometry/triangle.test.js +0 -11
- package/src/utils/math/geometry/types.d.ts +0 -23
- package/src/utils/math/linear-algebra/2d.js +0 -28
- package/src/utils/math/linear-algebra/2d.test.js +0 -17
- package/src/utils/math/linear-algebra/quaternion.js +0 -22
- package/src/utils/math/linear-algebra/quaternion.test.js +0 -25
- package/src/utils/math/linear-algebra/quaternions.js +0 -20
- package/src/utils/math/linear-algebra/quaternions.test.js +0 -29
- package/src/utils/math/linear-algebra/types.d.ts +0 -4
- package/src/utils/math/linear-algebra/vector.js +0 -302
- package/src/utils/math/linear-algebra/vector.test.js +0 -257
- package/src/utils/math/linear-algebra/vectors.js +0 -122
- package/src/utils/math/linear-algebra/vectors.test.js +0 -65
- package/src/utils/math/numbers.js +0 -90
- package/src/utils/math/numbers.test.js +0 -137
- package/src/utils/math/rng.js +0 -44
- package/src/utils/math/rng.test.js +0 -39
- package/src/utils/math/statistics.js +0 -43
- package/src/utils/math/statistics.test.js +0 -47
- package/src/utils/math/trigonometry.js +0 -89
- package/src/utils/math/trigonometry.test.js +0 -52
- package/src/utils/physics/acceleration.js +0 -63
- package/src/utils/physics/friction.js +0 -30
- package/src/utils/physics/friction.test.js +0 -44
- package/src/utils/physics/gravity.js +0 -71
- package/src/utils/physics/gravity.test.js +0 -80
- package/src/utils/physics/jump.js +0 -41
- package/src/utils/physics/velocity.js +0 -38
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import('./types').Vector2} Vector2
|
|
3
|
-
* @typedef {import('./types').Vector3} Vector3
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { hypothenuse } from "@inglorious/utils/math/geometry/triangle.js"
|
|
7
|
-
import {
|
|
8
|
-
abs as nAbs,
|
|
9
|
-
clamp as nClamp,
|
|
10
|
-
mod as nMod,
|
|
11
|
-
snap as nSnap,
|
|
12
|
-
} from "@inglorious/utils/math/numbers.js"
|
|
13
|
-
import { atan2, cos, sin } from "@inglorious/utils/math/trigonometry.js"
|
|
14
|
-
|
|
15
|
-
import { from2D, to2D } from "./2d.js"
|
|
16
|
-
import { quaternion } from "./quaternion.js"
|
|
17
|
-
import { cross, sum } from "./vectors.js"
|
|
18
|
-
|
|
19
|
-
const ZERO_VECTOR = [0, 0, 0] // eslint-disable-line no-magic-numbers
|
|
20
|
-
const UNIT_VECTOR = [1, 0, 0] // eslint-disable-line no-magic-numbers
|
|
21
|
-
|
|
22
|
-
const X = 0
|
|
23
|
-
const Z = 2
|
|
24
|
-
const LAST_COORDINATE = 1
|
|
25
|
-
const TWO_COORDINATES = 2
|
|
26
|
-
const NO_Y = 0
|
|
27
|
-
const DEFAULT_PRECISION = 1
|
|
28
|
-
const DEFAULT_DECIMALS = 0
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Returns the absolute value of each component in the vector.
|
|
32
|
-
* @param {Vector3} vector - The input vector.
|
|
33
|
-
* @returns {Vector3} The vector with absolute values.
|
|
34
|
-
*/
|
|
35
|
-
export function abs(vector) {
|
|
36
|
-
return vector.map(nAbs)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Calculates the angle of the vector in radians.
|
|
41
|
-
* @param {Vector3} vector - The input vector.
|
|
42
|
-
* @returns {number} The angle in radians.
|
|
43
|
-
*/
|
|
44
|
-
export function angle(vector) {
|
|
45
|
-
return atan2(vector[vector.length - LAST_COORDINATE], vector[X])
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Clamps the magnitude of the vector between the given min and max values.
|
|
50
|
-
* @param {Vector3} vector - The input vector.
|
|
51
|
-
* @param {number} min - The minimum magnitude.
|
|
52
|
-
* @param {number} max - The maximum magnitude.
|
|
53
|
-
* @returns {Vector3} The clamped vector.
|
|
54
|
-
*/
|
|
55
|
-
export function clamp(vector, min, max) {
|
|
56
|
-
const length = magnitude(vector)
|
|
57
|
-
|
|
58
|
-
if (typeof min === "number" && length < min) {
|
|
59
|
-
return setMagnitude(vector, min)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (typeof max === "number" && length > max) {
|
|
63
|
-
return setMagnitude(vector, max)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (typeof min !== "number" && typeof max !== "number") {
|
|
67
|
-
return vector.map((coordinate, index) =>
|
|
68
|
-
nClamp(coordinate, min[index], max[index]),
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return vector
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Returns the conjugate of the vector.
|
|
77
|
-
* @param {Vector3} vector - The input vector.
|
|
78
|
-
* @returns {Vector3} The conjugated vector.
|
|
79
|
-
*/
|
|
80
|
-
export function conjugate(vector) {
|
|
81
|
-
return vector.map((coordinate, index) => (index ? -coordinate : coordinate))
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Creates a vector with the given magnitude and angle.
|
|
86
|
-
* @param {number} magnitude - The magnitude of the vector.
|
|
87
|
-
* @param {number} angle - The angle of the vector in radians.
|
|
88
|
-
* @returns {Vector3} The created vector.
|
|
89
|
-
*/
|
|
90
|
-
export function createVector(magnitude, angle) {
|
|
91
|
-
return multiply(fromAngle(angle), magnitude)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Divides each component of the vector by the given scalar.
|
|
96
|
-
* @param {Vector3} vector - The input vector.
|
|
97
|
-
* @param {number} scalar - The scalar value.
|
|
98
|
-
* @returns {Vector3} The resulting vector.
|
|
99
|
-
*/
|
|
100
|
-
export function divide(vector, scalar) {
|
|
101
|
-
return vector.map((coordinate) => coordinate / scalar)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Creates a unit vector from the given angle.
|
|
106
|
-
* @param {number} angle - The angle in radians.
|
|
107
|
-
* @returns {Vector3} The unit vector.
|
|
108
|
-
*/
|
|
109
|
-
export function fromAngle(angle) {
|
|
110
|
-
return rotate(UNIT_VECTOR, angle)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export const length = magnitude
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Calculates the magnitude of the vector.
|
|
117
|
-
* @param {Vector3} vector - The input vector.
|
|
118
|
-
* @returns {number} The magnitude of the vector.
|
|
119
|
-
*/
|
|
120
|
-
export function magnitude(vector) {
|
|
121
|
-
return hypothenuse(...vector)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Calculates the modulus of each component in the vector with the given divisor.
|
|
126
|
-
* @param {Vector3} vector - The input vector.
|
|
127
|
-
* @param {number} divisor - The divisor value.
|
|
128
|
-
* @returns {Vector3} The resulting vector.
|
|
129
|
-
*/
|
|
130
|
-
export function mod(vector, divisor) {
|
|
131
|
-
return vector.map((coordinate) => nMod(coordinate, divisor))
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Multiplies each component of the vector by the given scalar.
|
|
136
|
-
* @param {Vector3} vector - The input vector.
|
|
137
|
-
* @param {number} scalar - The scalar value.
|
|
138
|
-
* @returns {Vector3} The resulting vector.
|
|
139
|
-
*/
|
|
140
|
-
export function multiply(vector, scalar) {
|
|
141
|
-
return vector.map((coordinate) => coordinate * scalar)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Normalizes the vector to have a magnitude of 1.
|
|
146
|
-
* @param {Vector3} vector - The input vector.
|
|
147
|
-
* @returns {Vector3} The normalized vector.
|
|
148
|
-
*/
|
|
149
|
-
export function normalize(vector) {
|
|
150
|
-
const length = magnitude(vector)
|
|
151
|
-
return vector.map((coordinate) => coordinate / length)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export const remainder = mod
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Rotates the vector by the given angle.
|
|
158
|
-
* @param {Vector3} vector - The input vector.
|
|
159
|
-
* @param {number} angle - The angle in radians.
|
|
160
|
-
* @returns {Vector3} The rotated vector.
|
|
161
|
-
*/
|
|
162
|
-
export function rotate(vector, angle) {
|
|
163
|
-
const is2D = vector.length === TWO_COORDINATES
|
|
164
|
-
|
|
165
|
-
let v = is2D ? from2D(vector) : vector
|
|
166
|
-
|
|
167
|
-
let result = rotateWithQuaternion(v, angle)
|
|
168
|
-
|
|
169
|
-
return is2D ? to2D(result) : result
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Sets the angle of the vector while maintaining its magnitude.
|
|
174
|
-
* @param {Vector3} vector - The input vector.
|
|
175
|
-
* @param {number} angle - The new angle in radians.
|
|
176
|
-
* @returns {Vector3} The vector with the updated angle.
|
|
177
|
-
*/
|
|
178
|
-
export function setAngle(vector, angle) {
|
|
179
|
-
const length = magnitude(vector)
|
|
180
|
-
const [x, z] = toCartesian([length, angle])
|
|
181
|
-
return [x, NO_Y, z]
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export const setLength = setMagnitude
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Sets the magnitude of the vector while maintaining its direction.
|
|
188
|
-
* @param {Vector3} vector - The input vector.
|
|
189
|
-
* @param {number} length - The new magnitude.
|
|
190
|
-
* @returns {Vector3} The vector with the updated magnitude.
|
|
191
|
-
*/
|
|
192
|
-
export function setMagnitude(vector, length) {
|
|
193
|
-
const normalized = normalize(vector)
|
|
194
|
-
return multiply(normalized, length)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Shifts the components of the vector by the given index.
|
|
199
|
-
* @param {Vector3} vector - The input vector.
|
|
200
|
-
* @param {number} index - The index to shift by.
|
|
201
|
-
* @returns {Vector3} The shifted vector.
|
|
202
|
-
*/
|
|
203
|
-
export function shift(vector, index) {
|
|
204
|
-
return [...vector.slice(index), ...vector.slice(X, index)]
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Snaps each component of the vector to the nearest multiple of the given precision.
|
|
209
|
-
* @param {Vector3} vector - The input vector.
|
|
210
|
-
* @param {number} [precision=DEFAULT_PRECISION] - The precision value.
|
|
211
|
-
* @returns {Vector3} The snapped vector.
|
|
212
|
-
*/
|
|
213
|
-
export function snap(vector, precision = DEFAULT_PRECISION) {
|
|
214
|
-
return vector.map((coordinate) => nSnap(coordinate, -precision, precision))
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export const times = multiply
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Converts polar coordinates to Cartesian coordinates.
|
|
221
|
-
* @param {Vector2} vector - The polar coordinates [magnitude, angle].
|
|
222
|
-
* @returns {Vector2} The Cartesian coordinates [x, y].
|
|
223
|
-
*/
|
|
224
|
-
export function toCartesian([magnitude, angle]) {
|
|
225
|
-
return [magnitude * cos(angle), magnitude * sin(angle)]
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Converts a vector to cylindrical coordinates.
|
|
230
|
-
* @param {Vector2} vector - The input vector.
|
|
231
|
-
* @returns {Vector2} The cylindrical coordinates [radius, theta, z].
|
|
232
|
-
*/
|
|
233
|
-
export function toCylindrical(vector) {
|
|
234
|
-
const radius = magnitude(vector)
|
|
235
|
-
const theta = angle(vector)
|
|
236
|
-
return [radius * cos(theta), radius * sin(theta), vector[Z]]
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Converts a vector to polar coordinates.
|
|
241
|
-
* @param {Vector2} vector - The input vector.
|
|
242
|
-
* @returns {Vector2} The polar coordinates [magnitude, angle].
|
|
243
|
-
*/
|
|
244
|
-
export function toPolar(vector) {
|
|
245
|
-
return [magnitude(vector), angle(vector)]
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Converts a vector to a string representation.
|
|
250
|
-
* @param {Vector3} vector - The input vector.
|
|
251
|
-
* @param {number} [decimals=DEFAULT_DECIMALS] - The number of decimal places.
|
|
252
|
-
* @returns {string} The string representation of the vector.
|
|
253
|
-
*/
|
|
254
|
-
export function toString(vector, decimals = DEFAULT_DECIMALS) {
|
|
255
|
-
return `[${vector
|
|
256
|
-
.map((coordinate) => coordinate.toFixed(decimals))
|
|
257
|
-
.join(", ")}]`
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// TODO: add toSpherical(vector), as described in https://www.cs.mcgill.ca/~rwest/wikispeedia/wpcd/wp/p/Polar_coordinate_system.htm#:~:text=Polar%20coordinates%20can%20also%20be,as%20in%20the%20polar%20coordinates).
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Creates a unit vector with the given angle.
|
|
264
|
-
* @param {number} angle - The angle in radians.
|
|
265
|
-
* @returns {Vector3} The unit vector.
|
|
266
|
-
*/
|
|
267
|
-
export function unit(angle) {
|
|
268
|
-
if (!angle) {
|
|
269
|
-
return [...UNIT_VECTOR]
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return setAngle(UNIT_VECTOR, angle)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Creates a zero vector.
|
|
277
|
-
* @returns {Vector3} The zero vector.
|
|
278
|
-
*/
|
|
279
|
-
export function zero() {
|
|
280
|
-
return [...ZERO_VECTOR]
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Rotates the vector using a quaternion.
|
|
285
|
-
* @param {Vector3} vector - The input vector.
|
|
286
|
-
* @param {number} angle - The angle in radians.
|
|
287
|
-
* @returns {Vector3} The rotated vector.
|
|
288
|
-
*/
|
|
289
|
-
function rotateWithQuaternion(vector, angle) {
|
|
290
|
-
if (!angle) {
|
|
291
|
-
return vector
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// @see https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Performance_comparisons
|
|
295
|
-
const [w, ...r] = quaternion(angle)
|
|
296
|
-
const result = sum(
|
|
297
|
-
vector,
|
|
298
|
-
cross(multiply(r, 2), sum(cross(r, vector), multiply(vector, w))), // eslint-disable-line no-magic-numbers
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
return conjugate(result) // HACK: not really sure why I should invert the result, it just works this way
|
|
302
|
-
}
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
import { sqrt } from "@inglorious/utils/math/numbers.js"
|
|
2
|
-
import { cos, pi, sin } from "@inglorious/utils/math/trigonometry.js"
|
|
3
|
-
import { expect, test } from "vitest"
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
abs,
|
|
7
|
-
angle,
|
|
8
|
-
clamp,
|
|
9
|
-
conjugate,
|
|
10
|
-
createVector,
|
|
11
|
-
divide,
|
|
12
|
-
fromAngle,
|
|
13
|
-
magnitude,
|
|
14
|
-
mod,
|
|
15
|
-
multiply,
|
|
16
|
-
normalize,
|
|
17
|
-
rotate,
|
|
18
|
-
setAngle,
|
|
19
|
-
setMagnitude,
|
|
20
|
-
shift,
|
|
21
|
-
snap,
|
|
22
|
-
toCartesian,
|
|
23
|
-
toCylindrical,
|
|
24
|
-
toPolar,
|
|
25
|
-
toString,
|
|
26
|
-
unit,
|
|
27
|
-
} from "./vector.js"
|
|
28
|
-
|
|
29
|
-
test("it should compute the absolute value of a vector's coordinates", () => {
|
|
30
|
-
const vector = [-2, 0, 3]
|
|
31
|
-
const expectedResult = [2, 0, 3]
|
|
32
|
-
|
|
33
|
-
expect(abs(vector)).toStrictEqual(expectedResult)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test("it should compute the angle of a 2D vector", () => {
|
|
37
|
-
const vector = [1, 1]
|
|
38
|
-
const expectedResult = pi() / 4
|
|
39
|
-
|
|
40
|
-
expect(angle(vector)).toBe(expectedResult)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test("it should compute the angle of a 3D vector", () => {
|
|
44
|
-
const vector = [1, 0, 1]
|
|
45
|
-
const expectedResult = pi() / 4
|
|
46
|
-
|
|
47
|
-
expect(angle(vector)).toBe(expectedResult)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test("it should clamp the magnitude of a vector to a certain length if too long", () => {
|
|
51
|
-
const vector = [6, 8]
|
|
52
|
-
const min = 0
|
|
53
|
-
const max = 5
|
|
54
|
-
const expectedResult = [3, 4]
|
|
55
|
-
|
|
56
|
-
expect(clamp(vector, min, max)).toStrictEqual(expectedResult)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
test("it should not clamp the magnitude of a vector to a certain length if not too long", () => {
|
|
60
|
-
const vector = [3, 4]
|
|
61
|
-
const min = 0
|
|
62
|
-
const max = 6
|
|
63
|
-
const expectedResult = [3, 4]
|
|
64
|
-
|
|
65
|
-
expect(clamp(vector, min, max)).toStrictEqual(expectedResult)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test("it should clamp the magnitude of a vector to the values of other vector bounds", () => {
|
|
69
|
-
const vector = [6, 8]
|
|
70
|
-
const lowerBound = [0, 0]
|
|
71
|
-
const upperBound = [3, 4]
|
|
72
|
-
const expectedResult = [3, 4]
|
|
73
|
-
|
|
74
|
-
expect(clamp(vector, lowerBound, upperBound)).toStrictEqual(expectedResult)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
test("it should conjugate a vector", () => {
|
|
78
|
-
const vector = [1, 2, 3]
|
|
79
|
-
const expectedResult = [1, -2, -3]
|
|
80
|
-
|
|
81
|
-
expect(conjugate(vector)).toStrictEqual(expectedResult)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
test("it should create a 3D vector given its magnitude and angle", () => {
|
|
85
|
-
const magnitude = sqrt(2)
|
|
86
|
-
const angle = pi() / 4
|
|
87
|
-
const expectedResult = [1, -0, 1.0000000000000002] // close to [1, 0, 1]
|
|
88
|
-
|
|
89
|
-
expect(createVector(magnitude, angle)).toStrictEqual(expectedResult)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
test("it should divide a vector by a scalar", () => {
|
|
93
|
-
const vector = [4, 8, 12]
|
|
94
|
-
const scalar = 4
|
|
95
|
-
const expectedResult = [1, 2, 3]
|
|
96
|
-
|
|
97
|
-
expect(divide(vector, scalar)).toStrictEqual(expectedResult)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
test("it should create a 3D unit vector from an angle", () => {
|
|
101
|
-
const angle = pi() / 4
|
|
102
|
-
const expectedResult = [0.7071067811865475, -0, 0.7071067811865476] // close to [cos(angle), 0, sin(angle)]
|
|
103
|
-
|
|
104
|
-
expect(fromAngle(angle)).toStrictEqual(expectedResult)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
test("it should compute the magnitude of a vector (aka length)", () => {
|
|
108
|
-
const vector = [3, 4]
|
|
109
|
-
const expectedResult = 5
|
|
110
|
-
|
|
111
|
-
expect(magnitude(vector)).toBe(expectedResult)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test("it should apply the mod operator (aka remainder) on a vector", () => {
|
|
115
|
-
const vector = [10, 12, -18]
|
|
116
|
-
const divisor = 12
|
|
117
|
-
const expectedResult = [10, 0, 6]
|
|
118
|
-
|
|
119
|
-
expect(mod(vector, divisor)).toStrictEqual(expectedResult)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
test("it should multiply a vector with a scalar (aka times)", () => {
|
|
123
|
-
const vector = [1, 2, 3]
|
|
124
|
-
const scalar = 4
|
|
125
|
-
const expectedResult = [4, 8, 12]
|
|
126
|
-
|
|
127
|
-
expect(multiply(vector, scalar)).toStrictEqual(expectedResult)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
test("it should normalize a vector so it has unit length", () => {
|
|
131
|
-
const vector = [3, 4]
|
|
132
|
-
const expectedResult = [0.6, 0.8]
|
|
133
|
-
|
|
134
|
-
expect(normalize(vector)).toStrictEqual(expectedResult)
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
test("it should normalize a negative vector", () => {
|
|
138
|
-
const vector = [-3, -4]
|
|
139
|
-
const expectedResult = [-0.6, -0.8]
|
|
140
|
-
|
|
141
|
-
expect(normalize(vector)).toStrictEqual(expectedResult)
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
test("it should rotate a 2D vector by a certain angle", () => {
|
|
145
|
-
const vector = [1, 0]
|
|
146
|
-
const angle = pi() / 4
|
|
147
|
-
const expectedResult = [0.7071067811865475, 0.7071067811865476] // close to [cos(pi/4), sin(pi/4)]
|
|
148
|
-
|
|
149
|
-
expect(rotate(vector, angle)).toStrictEqual(expectedResult)
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
test("it should not rotate a vector when the angle is zero", () => {
|
|
153
|
-
const vector = [1, 0, 0]
|
|
154
|
-
const angle = 0
|
|
155
|
-
const expectedResult = [1, 0, 0]
|
|
156
|
-
|
|
157
|
-
expect(rotate(vector, angle)).toStrictEqual(expectedResult)
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
test("it should rotate a vector by a certain angle", () => {
|
|
161
|
-
const vector = [1, 0, 0]
|
|
162
|
-
const angle = pi() / 4
|
|
163
|
-
const expectedResult = [0.7071067811865475, -0, 0.7071067811865476] // close to [cos(pi/4), 0, sin(pi/4)]
|
|
164
|
-
|
|
165
|
-
expect(rotate(vector, angle)).toStrictEqual(expectedResult)
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
test("it should rotate a vector that faces left by a certain angle", () => {
|
|
169
|
-
const vector = [-1, 0, 0]
|
|
170
|
-
const angle = pi() / 4
|
|
171
|
-
const expectedResult = [-0.7071067811865475, -0, -0.7071067811865476] // close to [cos(-3/4pi), 0, sin(-3/4pi)]
|
|
172
|
-
|
|
173
|
-
expect(rotate(vector, angle)).toStrictEqual(expectedResult)
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
test("it should change the angle of a vector", () => {
|
|
177
|
-
const vector = [cos(pi() / 4), 0, sin(pi() / 4)]
|
|
178
|
-
const expectedResult = [6.123233995736766e-17, 0, 1] // close to [0, 0, 1]
|
|
179
|
-
|
|
180
|
-
expect(setAngle(vector, 1.5707963267948966)).toStrictEqual(expectedResult)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
test("it should change magnitude of a vector (aka setLength)", () => {
|
|
184
|
-
const vector = [3, 4]
|
|
185
|
-
const magnitude = 10
|
|
186
|
-
const expectedResult = [6, 8]
|
|
187
|
-
|
|
188
|
-
expect(setMagnitude(vector, magnitude)).toStrictEqual(expectedResult)
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
test("it should change magnitude of a negative vector", () => {
|
|
192
|
-
const vector = [-3, -4]
|
|
193
|
-
const magnitude = 10
|
|
194
|
-
const expectedResult = [-6, -8]
|
|
195
|
-
|
|
196
|
-
expect(setMagnitude(vector, magnitude)).toStrictEqual(expectedResult)
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
test("it should shift a vector at a certain index", () => {
|
|
200
|
-
const vector = [1, 2, 3, 4, 5]
|
|
201
|
-
const index = 2
|
|
202
|
-
const expectedResult = [3, 4, 5, 1, 2]
|
|
203
|
-
|
|
204
|
-
expect(shift(vector, index)).toStrictEqual(expectedResult)
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
test("it should snap a floating vector to a certain precision", () => {
|
|
208
|
-
const vector = [1, 1.5, 1.7]
|
|
209
|
-
const precision = 1
|
|
210
|
-
const expectedResult = [1, 1, 2]
|
|
211
|
-
|
|
212
|
-
expect(snap(vector, precision)).toStrictEqual(expectedResult)
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
test("it should convert a 2D polar vector to cartesian coordinates", () => {
|
|
216
|
-
const vector = [sqrt(2), pi() / 4]
|
|
217
|
-
const expectedResult = [1.0000000000000002, 1]
|
|
218
|
-
|
|
219
|
-
expect(toCartesian(vector)).toStrictEqual(expectedResult)
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
test("it should convert a 3D cartesian vector to cylindrical coordinates", () => {
|
|
223
|
-
const vector = [1, 1, 1]
|
|
224
|
-
const expectedResult = [1.2247448713915892, 1.224744871391589, 1]
|
|
225
|
-
|
|
226
|
-
expect(toCylindrical(vector)).toStrictEqual(expectedResult)
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
test("it should convert a 2D cartesian vector to polar coordinates", () => {
|
|
230
|
-
const vector = [1, 1]
|
|
231
|
-
const expectedResult = [sqrt(2), pi() / 4]
|
|
232
|
-
|
|
233
|
-
expect(toPolar(vector)).toStrictEqual(expectedResult)
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
test("it should create a string representation of an integer vector", () => {
|
|
237
|
-
const vector = [3, 4]
|
|
238
|
-
const expectedResult = "[3, 4]"
|
|
239
|
-
|
|
240
|
-
expect(toString(vector)).toBe(expectedResult)
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
test("it should create a string representation of a float vector", () => {
|
|
244
|
-
const vector = [pi() / 4, pi() / 4]
|
|
245
|
-
const decimals = 2
|
|
246
|
-
const expectedResult = "[0.79, 0.79]"
|
|
247
|
-
|
|
248
|
-
expect(toString(vector, decimals)).toBe(expectedResult)
|
|
249
|
-
})
|
|
250
|
-
|
|
251
|
-
test("it should create a unit vector oriented on the X-axis", () => {
|
|
252
|
-
expect(unit()).toStrictEqual([1, 0, 0])
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
test("it should create a unit vector oriented on the Z-axis", () => {
|
|
256
|
-
expect(unit(pi() / 2)).toStrictEqual([6.123233995736766e-17, 0, 1]) // close to [0, 0, 1]
|
|
257
|
-
})
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import('./types').Vector2} Vector2
|
|
3
|
-
* @typedef {import('./types').Vector3} Vector3
|
|
4
|
-
* @typedef {import('./types').Vector7} Vector7
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { magnitude, shift } from "./vector.js"
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Alias for the sum function.
|
|
11
|
-
* @type {typeof sum}
|
|
12
|
-
*/
|
|
13
|
-
export const add = sum
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Computes the cross product of multiple vectors.
|
|
17
|
-
* @param {...Vector3 | Vector7} vectors - The vectors to compute the cross product for.
|
|
18
|
-
* @returns {Vector3 | Vector7} The resulting vector after the cross product.
|
|
19
|
-
*/
|
|
20
|
-
export function cross(...vectors) {
|
|
21
|
-
return vectors.reduce(crossMultiplyCoordinates)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Computes the distance between multiple vectors.
|
|
26
|
-
* @param {...Vector2 | Vector3} vectors - The vectors to compute the distance between.
|
|
27
|
-
* @returns {number} The distance between the vectors.
|
|
28
|
-
*/
|
|
29
|
-
export function distance(...vectors) {
|
|
30
|
-
return magnitude(subtract(...vectors))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Computes the dot product of multiple vectors.
|
|
35
|
-
* @param {...Vector2 | Vector3} vectors - The vectors to compute the dot product for.
|
|
36
|
-
* @returns {number} The resulting scalar value of the dot product.
|
|
37
|
-
*/
|
|
38
|
-
export function dot(...vectors) {
|
|
39
|
-
return vectors
|
|
40
|
-
.reduce(dotMultiplyCoordinates)
|
|
41
|
-
.reduce((coord1, coord2) => coord1 + coord2)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Alias for the dot product function.
|
|
46
|
-
* @type {typeof dot}
|
|
47
|
-
*/
|
|
48
|
-
export const scalarProduct = dot
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Subtracts multiple vectors.
|
|
52
|
-
* @param {...Vector2 | Vector3} vectors - The vectors to subtract.
|
|
53
|
-
* @returns {Vector2 | Vector3} The resulting vector after subtraction.
|
|
54
|
-
*/
|
|
55
|
-
export function subtract(...vectors) {
|
|
56
|
-
return vectors.reduce(subtractCoordinates)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Sums multiple vectors.
|
|
61
|
-
* @param {...Vector2 | Vector3} vectors - The vectors to sum.
|
|
62
|
-
* @returns {Vector2 | Vector3} The resulting vector after summation.
|
|
63
|
-
*/
|
|
64
|
-
export function sum(...vectors) {
|
|
65
|
-
return vectors.reduce(sumCoordinates)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Alias for the cross product function.
|
|
70
|
-
* @type {typeof cross}
|
|
71
|
-
*/
|
|
72
|
-
export const vectorProduct = cross
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Adds the coordinates of two vectors.
|
|
76
|
-
* @param {Vector2 | Vector3} vector1 - The first vector.
|
|
77
|
-
* @param {Vector2 | Vector3} vector2 - The second vector.
|
|
78
|
-
* @returns {Vector2 | Vector3} The resulting vector after addition.
|
|
79
|
-
*/
|
|
80
|
-
function sumCoordinates(vector1, vector2) {
|
|
81
|
-
return vector1.map((coordinate, index) => coordinate + vector2[index])
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Subtracts the coordinates of two vectors.
|
|
86
|
-
* @param {Vector2 | Vector3} vector1 - The first vector.
|
|
87
|
-
* @param {Vector2 | Vector3} vector2 - The second vector.
|
|
88
|
-
* @returns {Vector2 | Vector3} The resulting vector after subtraction.
|
|
89
|
-
*/
|
|
90
|
-
function subtractCoordinates(vector1, vector2) {
|
|
91
|
-
return vector1.map((coordinate, index) => coordinate - vector2[index])
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Computes the cross product of two vectors' coordinates.
|
|
96
|
-
* @param {Vector3} vector1 - The first vector.
|
|
97
|
-
* @param {Vector3} vector2 - The second vector.
|
|
98
|
-
* @returns {Vector3} The resulting vector after the cross product.
|
|
99
|
-
*/
|
|
100
|
-
function crossMultiplyCoordinates(vector1, vector2) {
|
|
101
|
-
const indexes = Array(vector1.length)
|
|
102
|
-
.fill(null)
|
|
103
|
-
.map((_, index) => index)
|
|
104
|
-
|
|
105
|
-
return indexes.map((_, index) => {
|
|
106
|
-
const [index1, index2] = shift(
|
|
107
|
-
indexes.filter((_, i) => i !== index),
|
|
108
|
-
index,
|
|
109
|
-
)
|
|
110
|
-
return vector1[index1] * vector2[index2] - vector1[index2] * vector2[index1]
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Multiplies the coordinates of two vectors.
|
|
116
|
-
* @param {Vector2 | Vector3} vector1 - The first vector.
|
|
117
|
-
* @param {Vector2 | Vector3} vector2 - The second vector.
|
|
118
|
-
* @returns {Vector2 | Vector3} The resulting vector containing multiplied coordinates.
|
|
119
|
-
*/
|
|
120
|
-
function dotMultiplyCoordinates(vector1, vector2) {
|
|
121
|
-
return vector1.map((coordinate, index) => coordinate * vector2[index])
|
|
122
|
-
}
|