@inglorious/utils 3.6.3 → 3.7.1
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 +1 -1
- package/package.json +5 -4
- package/src/data-structures/object.js +96 -3
- package/src/algorithms/decision-tree.test.js +0 -154
- package/src/algorithms/path-finding.test.js +0 -151
- package/src/data-structures/array.test.js +0 -206
- package/src/data-structures/board.test.js +0 -242
- package/src/data-structures/heap.test.js +0 -103
- package/src/data-structures/object.test.js +0 -335
- package/src/data-structures/objects.test.js +0 -196
- package/src/data-structures/set.test.js +0 -15
- package/src/data-structures/tree.test.js +0 -33
- package/src/functions/function.test.js +0 -15
- package/src/functions/functions.test.js +0 -51
- package/src/math/circle.test.js +0 -98
- package/src/math/hitmask.test.js +0 -156
- package/src/math/line.test.js +0 -50
- package/src/math/numbers.test.js +0 -198
- package/src/math/point.test.js +0 -94
- package/src/math/quaternion.test.js +0 -25
- package/src/math/quaternions.test.js +0 -29
- package/src/math/rectangle.test.js +0 -43
- package/src/math/rng.test.js +0 -55
- package/src/math/segment.test.js +0 -184
- package/src/math/statistics.test.js +0 -47
- package/src/math/triangle.test.js +0 -11
- package/src/math/trigonometry.test.js +0 -52
- package/src/math/vector.test.js +0 -345
- package/src/math/vectors.test.js +0 -77
- package/src/physics/friction.test.js +0 -43
- package/src/physics/gravity.test.js +0 -78
- package/src/v.test.js +0 -48
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { isArray } from "./array.js"
|
|
4
|
-
import { extend, extendWith, merge, mergeWith } from "./objects.js"
|
|
5
|
-
|
|
6
|
-
test("it should extend an object with another, producing a new object as a result", () => {
|
|
7
|
-
const obj1 = {
|
|
8
|
-
primitiveKept: 1,
|
|
9
|
-
primitiveMerged: 2,
|
|
10
|
-
primitiveArrayKept: [1, 2],
|
|
11
|
-
primitiveArrayMerged: [3, 4],
|
|
12
|
-
primitiveObjectKept: { a: 1 },
|
|
13
|
-
primitiveObjectMerged: { b: 2, c: 3 },
|
|
14
|
-
nestedArrayKept: [{ a: 1 }],
|
|
15
|
-
nestedArrayMerged: [{ b: 2, c: 3 }],
|
|
16
|
-
nestedObjectKept: { a: { b: 2 } },
|
|
17
|
-
nestedObjectMerged: { c: { d: 4 } },
|
|
18
|
-
}
|
|
19
|
-
const obj2 = {
|
|
20
|
-
primitiveMerged: 3,
|
|
21
|
-
primitiveAdded: 4,
|
|
22
|
-
primitiveArrayMerged: [5],
|
|
23
|
-
primitiveArrayAdded: [6, 7],
|
|
24
|
-
primitiveObjectMerged: { c: 4 },
|
|
25
|
-
primitiveObjectAdded: { d: 4 },
|
|
26
|
-
nestedArrayMerged: [{ d: 4 }],
|
|
27
|
-
nestedArrayAdded: [{ e: 5 }],
|
|
28
|
-
nestedObjectMerged: { c: { e: 5 } },
|
|
29
|
-
nestedObjectAdded: { f: { g: 7 } },
|
|
30
|
-
}
|
|
31
|
-
const expectedResult = {
|
|
32
|
-
primitiveKept: 1,
|
|
33
|
-
primitiveMerged: 3,
|
|
34
|
-
primitiveAdded: 4,
|
|
35
|
-
primitiveArrayKept: [1, 2],
|
|
36
|
-
primitiveArrayMerged: [5],
|
|
37
|
-
primitiveArrayAdded: [6, 7],
|
|
38
|
-
primitiveObjectKept: { a: 1 },
|
|
39
|
-
primitiveObjectMerged: { b: 2, c: 4 },
|
|
40
|
-
primitiveObjectAdded: { d: 4 },
|
|
41
|
-
nestedArrayKept: [{ a: 1 }],
|
|
42
|
-
nestedArrayMerged: [{ d: 4 }],
|
|
43
|
-
nestedArrayAdded: [{ e: 5 }],
|
|
44
|
-
nestedObjectKept: { a: { b: 2 } },
|
|
45
|
-
nestedObjectMerged: { c: { d: 4, e: 5 } },
|
|
46
|
-
nestedObjectAdded: { f: { g: 7 } },
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const result = extend(obj1, obj2)
|
|
50
|
-
expect(result).toStrictEqual(expectedResult)
|
|
51
|
-
expect(result).not.toBe(obj1)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test("it should deep merge an two objects, changing the first object in place", () => {
|
|
55
|
-
const obj1 = {
|
|
56
|
-
primitiveKept: 1,
|
|
57
|
-
primitiveMerged: 2,
|
|
58
|
-
primitiveArrayKept: [1, 2],
|
|
59
|
-
primitiveArrayMerged: [3, 4],
|
|
60
|
-
primitiveObjectKept: { a: 1 },
|
|
61
|
-
primitiveObjectMerged: { b: 2, c: 3 },
|
|
62
|
-
nestedArrayKept: [{ a: 1 }],
|
|
63
|
-
nestedArrayMerged: [{ b: 2, c: 3 }],
|
|
64
|
-
nestedObjectKept: { a: { b: 2 } },
|
|
65
|
-
nestedObjectMerged: { c: { d: 4 } },
|
|
66
|
-
}
|
|
67
|
-
const obj2 = {
|
|
68
|
-
primitiveMerged: 3,
|
|
69
|
-
primitiveAdded: 4,
|
|
70
|
-
primitiveArrayMerged: [5],
|
|
71
|
-
primitiveArrayAdded: [6, 7],
|
|
72
|
-
primitiveObjectMerged: { c: 4 },
|
|
73
|
-
primitiveObjectAdded: { d: 4 },
|
|
74
|
-
nestedArrayMerged: [{ d: 4 }],
|
|
75
|
-
nestedArrayAdded: [{ e: 5 }],
|
|
76
|
-
nestedObjectMerged: { c: { e: 5 } },
|
|
77
|
-
nestedObjectAdded: { f: { g: 7 } },
|
|
78
|
-
}
|
|
79
|
-
const expectedResult = {
|
|
80
|
-
primitiveKept: 1,
|
|
81
|
-
primitiveMerged: 3,
|
|
82
|
-
primitiveAdded: 4,
|
|
83
|
-
primitiveArrayKept: [1, 2],
|
|
84
|
-
primitiveArrayMerged: [5],
|
|
85
|
-
primitiveArrayAdded: [6, 7],
|
|
86
|
-
primitiveObjectKept: { a: 1 },
|
|
87
|
-
primitiveObjectMerged: { b: 2, c: 4 },
|
|
88
|
-
primitiveObjectAdded: { d: 4 },
|
|
89
|
-
nestedArrayKept: [{ a: 1 }],
|
|
90
|
-
nestedArrayMerged: [{ d: 4 }],
|
|
91
|
-
nestedArrayAdded: [{ e: 5 }],
|
|
92
|
-
nestedObjectKept: { a: { b: 2 } },
|
|
93
|
-
nestedObjectMerged: { c: { d: 4, e: 5 } },
|
|
94
|
-
nestedObjectAdded: { f: { g: 7 } },
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const result = merge(obj1, obj2)
|
|
98
|
-
expect(result).toStrictEqual(expectedResult)
|
|
99
|
-
expect(result).toBe(obj1)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test("it should extend an object with a custom merger, producing a new object", () => {
|
|
103
|
-
const obj1 = {
|
|
104
|
-
primitiveArrayMerged: [3, 4],
|
|
105
|
-
nestedArrayMerged: [{ b: 2, c: 3 }],
|
|
106
|
-
nestedObjectMerged: { c: { d: 4 } },
|
|
107
|
-
}
|
|
108
|
-
const obj2 = {
|
|
109
|
-
primitiveArrayMerged: [5],
|
|
110
|
-
nestedArrayMerged: [{ d: 4 }],
|
|
111
|
-
nestedObjectMerged: { c: { e: 5 } },
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const merger = (targetValue, sourceValue) => {
|
|
115
|
-
if (isArray(targetValue) && isArray(sourceValue)) {
|
|
116
|
-
return targetValue.concat(sourceValue)
|
|
117
|
-
}
|
|
118
|
-
return undefined // Use default logic for non-arrays
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const expectedResult = {
|
|
122
|
-
primitiveArrayMerged: [3, 4, 5], // Concatenated
|
|
123
|
-
nestedArrayMerged: [{ b: 2, c: 3 }, { d: 4 }], // Concatenated
|
|
124
|
-
nestedObjectMerged: { c: { d: 4, e: 5 } }, // Default deep merge
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const result = extendWith(merger, obj1, obj2)
|
|
128
|
-
expect(result).toStrictEqual(expectedResult)
|
|
129
|
-
expect(result).not.toBe(obj1)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
test("it should merge an object with a custom merger, changing the first object in place", () => {
|
|
133
|
-
const obj1 = {
|
|
134
|
-
primitiveArrayMerged: [3, 4],
|
|
135
|
-
nestedArrayMerged: [{ b: 2, c: 3 }],
|
|
136
|
-
nestedObjectMerged: { c: { d: 4 } },
|
|
137
|
-
}
|
|
138
|
-
const obj2 = {
|
|
139
|
-
primitiveArrayMerged: [5],
|
|
140
|
-
nestedArrayMerged: [{ d: 4 }],
|
|
141
|
-
nestedObjectMerged: { c: { e: 5 } },
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const merger = (targetValue, sourceValue) => {
|
|
145
|
-
if (isArray(targetValue) && isArray(sourceValue)) {
|
|
146
|
-
return targetValue.concat(sourceValue)
|
|
147
|
-
}
|
|
148
|
-
return undefined // Use default logic for non-arrays
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const expectedResult = {
|
|
152
|
-
primitiveArrayMerged: [3, 4, 5], // Concatenated
|
|
153
|
-
nestedArrayMerged: [{ b: 2, c: 3 }, { d: 4 }], // Concatenated
|
|
154
|
-
nestedObjectMerged: { c: { d: 4, e: 5 } }, // Default deep merge
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const result = mergeWith(merger, obj1, obj2)
|
|
158
|
-
expect(result).toStrictEqual(expectedResult)
|
|
159
|
-
expect(result).toBe(obj1)
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
test("extendWith without a merger should behave like extend", () => {
|
|
163
|
-
const obj1 = { a: 1, b: { c: 2 }, d: [3] }
|
|
164
|
-
const obj2 = { a: 10, b: { d: 20 }, d: [30] }
|
|
165
|
-
|
|
166
|
-
const expected = {
|
|
167
|
-
a: 10,
|
|
168
|
-
b: { c: 2, d: 20 },
|
|
169
|
-
d: [30],
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const result = extendWith(undefined, obj1, obj2)
|
|
173
|
-
expect(result).toStrictEqual(expected)
|
|
174
|
-
expect(result).not.toBe(obj1)
|
|
175
|
-
|
|
176
|
-
const extendResult = extend(obj1, obj2)
|
|
177
|
-
expect(result).toStrictEqual(extendResult)
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
test("mergeWith without a merger should behave like merge", () => {
|
|
181
|
-
const obj1 = { a: 1, b: { c: 2 }, d: [3] }
|
|
182
|
-
const obj2 = { a: 10, b: { d: 20 }, d: [30] }
|
|
183
|
-
|
|
184
|
-
const expected = {
|
|
185
|
-
a: 10,
|
|
186
|
-
b: { c: 2, d: 20 },
|
|
187
|
-
d: [30],
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const result = mergeWith(undefined, obj1, obj2)
|
|
191
|
-
expect(result).toStrictEqual(expected)
|
|
192
|
-
expect(result).toBe(obj1)
|
|
193
|
-
|
|
194
|
-
const mergeResult = merge({ a: 1, b: { c: 2 }, d: [3] }, obj2)
|
|
195
|
-
expect(result).toStrictEqual(mergeResult)
|
|
196
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { ensureSet } from "./set.js"
|
|
4
|
-
|
|
5
|
-
test("it should return the same array if the value is already an array", () => {
|
|
6
|
-
const set = new Set([1, "two", { three: 3 }])
|
|
7
|
-
|
|
8
|
-
expect(ensureSet(set)).toBe(set)
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
test("it should wrap the value in an array if it is not an array", () => {
|
|
12
|
-
const str = "hello"
|
|
13
|
-
|
|
14
|
-
expect(ensureSet(str)).toStrictEqual(new Set(["h", "e", "l", "o"]))
|
|
15
|
-
})
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { bfs, dfs } from "./tree.js"
|
|
4
|
-
|
|
5
|
-
test("it should perform Breadth-First Search on a tree", () => {
|
|
6
|
-
const tree = {
|
|
7
|
-
value: 1,
|
|
8
|
-
children: [
|
|
9
|
-
{ value: 2, children: [{ value: 4 }, { value: 5 }] },
|
|
10
|
-
{ value: 3, children: [{ value: 6 }, { value: 7 }] },
|
|
11
|
-
],
|
|
12
|
-
}
|
|
13
|
-
const expectedResult = [1, 2, 3, 4, 5, 6, 7]
|
|
14
|
-
|
|
15
|
-
const result = bfs(tree)
|
|
16
|
-
|
|
17
|
-
expect(result).toStrictEqual(expectedResult)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test("it should perform Depth-First Search on a tree", () => {
|
|
21
|
-
const tree = {
|
|
22
|
-
value: 1,
|
|
23
|
-
children: [
|
|
24
|
-
{ value: 2, children: [{ value: 3 }, { value: 4 }] },
|
|
25
|
-
{ value: 5, children: [{ value: 6 }, { value: 7 }] },
|
|
26
|
-
],
|
|
27
|
-
}
|
|
28
|
-
const expectedResult = [1, 2, 3, 4, 5, 6, 7]
|
|
29
|
-
|
|
30
|
-
const result = dfs(tree)
|
|
31
|
-
|
|
32
|
-
expect(result).toStrictEqual(expectedResult)
|
|
33
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { isFunction } from "./function.js"
|
|
4
|
-
|
|
5
|
-
test("it should correctly identify a function", () => {
|
|
6
|
-
const func = () => {}
|
|
7
|
-
|
|
8
|
-
expect(isFunction(func)).toBe(true)
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
test("it should correctly identify a non-function", () => {
|
|
12
|
-
const str = "hello"
|
|
13
|
-
|
|
14
|
-
expect(isFunction(str)).toBe(false)
|
|
15
|
-
})
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { compose, pipe } from "./functions.js"
|
|
4
|
-
|
|
5
|
-
test("it should compose unary functions", () => {
|
|
6
|
-
const shout = (x) => x.toUpperCase()
|
|
7
|
-
const punctuate = (mark) => (x) => `${x}${mark}`
|
|
8
|
-
const html = (tag) => (x) => `<${tag}>${x}</${tag}>`
|
|
9
|
-
|
|
10
|
-
const fn = compose(html("p"), punctuate("!"), shout)
|
|
11
|
-
expect(fn("Hello world")).toBe("<p>HELLO WORLD!</p>")
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
test("it should compose functions with multiple initial arguments", () => {
|
|
15
|
-
const add = (a, b) => a + b
|
|
16
|
-
const square = (x) => x * x
|
|
17
|
-
const half = (x) => x / 2
|
|
18
|
-
|
|
19
|
-
const fn = compose(half, square, add) // half(square(add(2, 3)))
|
|
20
|
-
expect(fn(2, 3)).toBe(12.5)
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
test("it should return an identity-like function if compose is called with no arguments", () => {
|
|
24
|
-
const fn = compose()
|
|
25
|
-
expect(fn(42)).toBe(42)
|
|
26
|
-
expect(fn({ a: 1 })).toStrictEqual({ a: 1 })
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test("it should pipe unary functions", () => {
|
|
30
|
-
const shout = (x) => x.toUpperCase()
|
|
31
|
-
const punctuate = (mark) => (x) => `${x}${mark}`
|
|
32
|
-
const html = (tag) => (x) => `<${tag}>${x}</${tag}>`
|
|
33
|
-
|
|
34
|
-
const fn = pipe(shout, punctuate("!"), html("p"))
|
|
35
|
-
expect(fn("Hello world")).toBe("<p>HELLO WORLD!</p>")
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
test("it should pipe functions with multiple initial arguments", () => {
|
|
39
|
-
const add = (a, b) => a + b
|
|
40
|
-
const square = (x) => x * x
|
|
41
|
-
const half = (x) => x / 2
|
|
42
|
-
|
|
43
|
-
const fn = pipe(add, square, half) // half(square(add(2, 3)))
|
|
44
|
-
expect(fn(2, 3)).toBe(12.5)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test("it should return an identity-like function if pipe is called with no arguments", () => {
|
|
48
|
-
const fn = pipe()
|
|
49
|
-
expect(fn(42)).toBe(42)
|
|
50
|
-
expect(fn({ a: 1 })).toStrictEqual({ a: 1 })
|
|
51
|
-
})
|
package/src/math/circle.test.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { v } from "../v.js"
|
|
4
|
-
import {
|
|
5
|
-
intersectsCircle,
|
|
6
|
-
intersectsPoint,
|
|
7
|
-
intersectsRectangle,
|
|
8
|
-
} from "./circle.js"
|
|
9
|
-
|
|
10
|
-
test("it should prove that a circle around a point intersects with it", () => {
|
|
11
|
-
const circle = {
|
|
12
|
-
position: v(1, 1, 0),
|
|
13
|
-
radius: 1,
|
|
14
|
-
}
|
|
15
|
-
const point = v(1.5, 1.5, 0)
|
|
16
|
-
|
|
17
|
-
expect(intersectsPoint(circle, point)).toBe(true)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test("it should prove that two equal circles intersect", () => {
|
|
21
|
-
const circle1 = { position: v(1, 1, 0), radius: 1 }
|
|
22
|
-
const circle2 = { position: v(1, 1, 0), radius: 1 }
|
|
23
|
-
|
|
24
|
-
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
test("it should prove that two circles shifted by a small x intersect", () => {
|
|
28
|
-
const circle1 = { position: v(1, 1, 0), radius: 1 }
|
|
29
|
-
const circle2 = { position: v(2, 1, 0), radius: 1 }
|
|
30
|
-
|
|
31
|
-
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
test("it should prove that two touching circles intersect", () => {
|
|
35
|
-
const circle1 = { position: v(1, 1, 0), radius: 1 }
|
|
36
|
-
const circle2 = { position: v(3, 1, 0), radius: 1 }
|
|
37
|
-
|
|
38
|
-
expect(intersectsCircle(circle1, circle2)).toBe(true)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
test("it should prove that two non-touching circles do not intersect", () => {
|
|
42
|
-
const circle1 = { position: v(1, 1, 0), radius: 1 }
|
|
43
|
-
const circle2 = { position: v(4, 1, 0), radius: 1 }
|
|
44
|
-
|
|
45
|
-
expect(intersectsCircle(circle1, circle2)).toBe(false)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
test("it should prove that a circle inside of a rectangle intersects with it", () => {
|
|
49
|
-
const circle = {
|
|
50
|
-
position: v(1, 1, 0),
|
|
51
|
-
radius: 1,
|
|
52
|
-
}
|
|
53
|
-
const rectangle = {
|
|
54
|
-
position: v(-1, -1, 0),
|
|
55
|
-
size: v(4, 4, 0),
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test("it should prove that a circle touching the border of a rectangle intersects with it", () => {
|
|
62
|
-
const circle = {
|
|
63
|
-
position: v(1, 1, 0),
|
|
64
|
-
radius: 1,
|
|
65
|
-
}
|
|
66
|
-
const rectangle = {
|
|
67
|
-
position: v(-1, 1, 0), // Rectangle's right edge is at x=0, touching the circle's left edge.
|
|
68
|
-
size: v(2, 2, 0),
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
test("it should prove that a circle crossing a rectangle intersects with it", () => {
|
|
75
|
-
const circle = {
|
|
76
|
-
position: v(1, 1, 0),
|
|
77
|
-
radius: 1,
|
|
78
|
-
}
|
|
79
|
-
const rectangle = {
|
|
80
|
-
position: v(0, 0, 0),
|
|
81
|
-
size: v(2, 2, 0),
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(true)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
test("it should prove that a circle outside of a rectangle does not intersect with it", () => {
|
|
88
|
-
const circle = {
|
|
89
|
-
position: v(1, 1, 0),
|
|
90
|
-
radius: 1,
|
|
91
|
-
}
|
|
92
|
-
const rectangle = {
|
|
93
|
-
position: v(-3, 0, 0),
|
|
94
|
-
size: v(2, 2, 0),
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
expect(intersectsRectangle(circle, rectangle)).toBe(false)
|
|
98
|
-
})
|
package/src/math/hitmask.test.js
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { v } from "../v.js"
|
|
4
|
-
import { findCollisions } from "./hitmask.js"
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Given a rectangle located at (x=1.5, y=0, z=2.5) with a size of (1, 1, 1),
|
|
8
|
-
* which is touching a wall tile, this test proves a collision is detected.
|
|
9
|
-
*
|
|
10
|
-
* Tilemap layout:
|
|
11
|
-
* ⬛️🟩🟩⬛️
|
|
12
|
-
* ⬛️⬛️⬛️⬛️
|
|
13
|
-
* ⬛️⬛️⬛️⬛️
|
|
14
|
-
*
|
|
15
|
-
* Rectangle position (X,Z): R at (1.5, 2.5)
|
|
16
|
-
*
|
|
17
|
-
* Expected outcome: true
|
|
18
|
-
*/
|
|
19
|
-
test("it should prove that a rectangle touching a wall intersects with it", () => {
|
|
20
|
-
const hitmask = {
|
|
21
|
-
position: v(2, 0, 1.5),
|
|
22
|
-
tileSize: [1, 1],
|
|
23
|
-
columns: 4,
|
|
24
|
-
// The top row (indices 0, 1, 2, 3) now has the walls.
|
|
25
|
-
heights: [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
26
|
-
}
|
|
27
|
-
const rectangle = {
|
|
28
|
-
shape: "rectangle",
|
|
29
|
-
position: v(1.5, 0, 2.5),
|
|
30
|
-
size: v(1, 1, 1),
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
expect(findCollisions(hitmask, rectangle)).toBe(true)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Given the same scenario as the previous test, but all coordinates
|
|
38
|
-
* are shifted by a constant value, this test proves the outcome remains
|
|
39
|
-
* unchanged, ensuring the collision detection is relative.
|
|
40
|
-
*
|
|
41
|
-
* Tilemap layout:
|
|
42
|
-
* ⬛️🟩🟩⬛️
|
|
43
|
-
* ⬛️⬛️⬛️⬛️
|
|
44
|
-
* ⬛️⬛️⬛️⬛️
|
|
45
|
-
*
|
|
46
|
-
* Rectangle position (X,Z): R at (11.5, 12.5)
|
|
47
|
-
*
|
|
48
|
-
* Expected outcome: true
|
|
49
|
-
*/
|
|
50
|
-
test("it should prove that shifting operands does not change the outcome", () => {
|
|
51
|
-
const SHIFT = 10
|
|
52
|
-
const hitmask = {
|
|
53
|
-
position: [2 + SHIFT, 0, 1.5 + SHIFT],
|
|
54
|
-
tileSize: [1, 1],
|
|
55
|
-
columns: 4,
|
|
56
|
-
// The top row (indices 0, 1, 2, 3) now has the walls.
|
|
57
|
-
heights: [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
58
|
-
}
|
|
59
|
-
const rectangle = {
|
|
60
|
-
shape: "rectangle",
|
|
61
|
-
position: v(11.5, 0, 12.5),
|
|
62
|
-
size: v(1, 1, 1),
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
expect(findCollisions(hitmask, rectangle)).toBe(true)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Given a rectangle located at (x=0.5, y=0, z=0.5) with a size of (1, 1, 1),
|
|
70
|
-
* which is not touching any walls, this test proves no collision is detected.
|
|
71
|
-
*
|
|
72
|
-
* Tilemap layout:
|
|
73
|
-
* ⬛️🟩🟩⬛️
|
|
74
|
-
* ⬛️⬛️⬛️⬛️
|
|
75
|
-
* ⬛️⬛️⬛️⬛️
|
|
76
|
-
*
|
|
77
|
-
* Rectangle position (X,Z): R at (0.5, 0.5)
|
|
78
|
-
*
|
|
79
|
-
* Expected outcome: false
|
|
80
|
-
*/
|
|
81
|
-
test("it should prove that a rectangle not touching a wall does not intersect with it", () => {
|
|
82
|
-
const hitmask = {
|
|
83
|
-
position: v(2, 0, 1.5),
|
|
84
|
-
tileSize: [1, 1],
|
|
85
|
-
columns: 4,
|
|
86
|
-
// The top row (indices 0, 1, 2, 3) now has the walls.
|
|
87
|
-
heights: [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
88
|
-
}
|
|
89
|
-
const rectangle = {
|
|
90
|
-
shape: "rectangle",
|
|
91
|
-
position: v(0.5, 0, 0.5),
|
|
92
|
-
size: v(1, 1, 1),
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
expect(findCollisions(hitmask, rectangle)).toBe(false)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Given a rectangle located above the tile, this test proves no
|
|
100
|
-
* collision is detected even when the X and Z positions overlap.
|
|
101
|
-
*
|
|
102
|
-
* Tilemap layout:
|
|
103
|
-
* ⬛️🟩🟩⬛️
|
|
104
|
-
* ⬛️⬛️⬛️⬛️
|
|
105
|
-
* ⬛️⬛️⬛️⬛️
|
|
106
|
-
*
|
|
107
|
-
* Rectangle position: R at (x=1.5, y=1.6, z=2.5)
|
|
108
|
-
*
|
|
109
|
-
* Expected outcome: false
|
|
110
|
-
*/
|
|
111
|
-
test("it should prove that a rectangle above the tile of a hitmask does not intersect with it", () => {
|
|
112
|
-
const hitmask = {
|
|
113
|
-
position: v(2, 0, 1.5),
|
|
114
|
-
tileSize: [1, 1],
|
|
115
|
-
columns: 4,
|
|
116
|
-
// The top row (indices 0, 1, 2, 3) now has the walls.
|
|
117
|
-
heights: [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
118
|
-
}
|
|
119
|
-
const rectangle = {
|
|
120
|
-
shape: "rectangle",
|
|
121
|
-
position: v(1.5, 1.6, 2.5),
|
|
122
|
-
size: v(1, 1, 1),
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
expect(findCollisions(hitmask, rectangle)).toBe(false)
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Given a rectangle located outside of the tilemap, this test proves
|
|
130
|
-
* no collision is detected.
|
|
131
|
-
*
|
|
132
|
-
* Tilemap layout:
|
|
133
|
-
* ⬛️🟩🟩⬛️
|
|
134
|
-
* ⬛️⬛️⬛️⬛️
|
|
135
|
-
* ⬛️⬛️⬛️⬛️
|
|
136
|
-
*
|
|
137
|
-
* Rectangle position: R at (x=5.5, y=0.5, z=1.5)
|
|
138
|
-
*
|
|
139
|
-
* Expected outcome: false
|
|
140
|
-
*/
|
|
141
|
-
test("it should prove that a rectangle outside of a hitmask does not intersect with it", () => {
|
|
142
|
-
const hitmask = {
|
|
143
|
-
position: v(2, 0, 1.5),
|
|
144
|
-
tileSize: [1, 1],
|
|
145
|
-
columns: 4,
|
|
146
|
-
// The top row (indices 0, 1, 2, 3) now has the walls.
|
|
147
|
-
heights: [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
148
|
-
}
|
|
149
|
-
const rectangle = {
|
|
150
|
-
shape: "rectangle",
|
|
151
|
-
position: v(5.5, 0.5, 1.5),
|
|
152
|
-
size: v(1, 1, 1),
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
expect(findCollisions(hitmask, rectangle)).toBe(false)
|
|
156
|
-
})
|
package/src/math/line.test.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { v } from "../v.js"
|
|
4
|
-
import { distanceFromPoint, intersectsCircle } from "./line.js"
|
|
5
|
-
|
|
6
|
-
test("it should compute the distance between a line and a point", () => {
|
|
7
|
-
const line = v(-4, 3, 0)
|
|
8
|
-
const point = v(5, 0, 0)
|
|
9
|
-
const expectedResult = 4
|
|
10
|
-
|
|
11
|
-
expect(distanceFromPoint(line, point)).toBe(expectedResult)
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
test("it should not compute the distance between a line and a point", () => {
|
|
15
|
-
const line = v(-1, 1, 0)
|
|
16
|
-
const point = v(2, 0, 2)
|
|
17
|
-
const expectedResult = 0
|
|
18
|
-
|
|
19
|
-
expect(distanceFromPoint(line, point)).toBe(expectedResult)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
test("it should prove that a line that crosses a circle intersects with it", () => {
|
|
23
|
-
const line = v(-2, 2, 0)
|
|
24
|
-
const circle = {
|
|
25
|
-
position: v(1, 1, 0),
|
|
26
|
-
radius: 1,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
expect(intersectsCircle(line, circle)).toBe(true)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test("it should prove that a line tangent to a circle intersects with it", () => {
|
|
33
|
-
const line = v(-2, 0, 0)
|
|
34
|
-
const circle = {
|
|
35
|
-
position: v(1, 0, 1),
|
|
36
|
-
radius: 1,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
expect(intersectsCircle(line, circle)).toBe(true)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test("it should prove that a line that does not cross a circle does not intersect with it", () => {
|
|
43
|
-
const line = v(1, 1, 0)
|
|
44
|
-
const circle = {
|
|
45
|
-
position: v(1, 0, 1),
|
|
46
|
-
radius: 1,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
expect(intersectsCircle(line, circle)).toBe(false)
|
|
50
|
-
})
|