murow 0.0.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 +61 -0
- package/dist/core/binary-codec/binary-codec.d.ts +159 -0
- package/dist/core/binary-codec/binary-codec.js +336 -0
- package/dist/core/binary-codec/index.d.ts +1 -0
- package/dist/core/binary-codec/index.js +1 -0
- package/dist/core/events/event-system.d.ts +71 -0
- package/dist/core/events/event-system.js +88 -0
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/fixed-ticker/fixed-ticker.d.ts +105 -0
- package/dist/core/fixed-ticker/fixed-ticker.js +91 -0
- package/dist/core/fixed-ticker/index.d.ts +1 -0
- package/dist/core/fixed-ticker/index.js +1 -0
- package/dist/core/generate-id/generate-id.d.ts +21 -0
- package/dist/core/generate-id/generate-id.js +25 -0
- package/dist/core/generate-id/index.d.ts +1 -0
- package/dist/core/generate-id/index.js +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +8 -0
- package/dist/core/lerp/index.d.ts +1 -0
- package/dist/core/lerp/index.js +1 -0
- package/dist/core/lerp/lerp.d.ts +40 -0
- package/dist/core/lerp/lerp.js +42 -0
- package/dist/core/navmesh/index.d.ts +1 -0
- package/dist/core/navmesh/index.js +1 -0
- package/dist/core/navmesh/navmesh.d.ts +116 -0
- package/dist/core/navmesh/navmesh.js +666 -0
- package/dist/core/pooled-codec/index.d.ts +1 -0
- package/dist/core/pooled-codec/index.js +1 -0
- package/dist/core/pooled-codec/pooled-codec.d.ts +140 -0
- package/dist/core/pooled-codec/pooled-codec.js +213 -0
- package/dist/core/prediction/index.d.ts +1 -0
- package/dist/core/prediction/index.js +1 -0
- package/dist/core/prediction/prediction.d.ts +64 -0
- package/dist/core/prediction/prediction.js +90 -0
- package/dist/core.esm.js +1 -0
- package/dist/core.js +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +18 -0
- package/dist/protocol/index.d.ts +43 -0
- package/dist/protocol/index.js +43 -0
- package/dist/protocol/intent/index.d.ts +39 -0
- package/dist/protocol/intent/index.js +38 -0
- package/dist/protocol/intent/intent-registry.d.ts +54 -0
- package/dist/protocol/intent/intent-registry.js +73 -0
- package/dist/protocol/intent/intent.d.ts +12 -0
- package/dist/protocol/intent/intent.js +1 -0
- package/dist/protocol/snapshot/index.d.ts +44 -0
- package/dist/protocol/snapshot/index.js +43 -0
- package/dist/protocol/snapshot/snapshot-codec.d.ts +48 -0
- package/dist/protocol/snapshot/snapshot-codec.js +56 -0
- package/dist/protocol/snapshot/snapshot-registry.d.ts +100 -0
- package/dist/protocol/snapshot/snapshot-registry.js +136 -0
- package/dist/protocol/snapshot/snapshot.d.ts +19 -0
- package/dist/protocol/snapshot/snapshot.js +30 -0
- package/package.json +54 -0
- package/src/core/binary-codec/README.md +60 -0
- package/src/core/binary-codec/binary-codec.test.ts +300 -0
- package/src/core/binary-codec/binary-codec.ts +430 -0
- package/src/core/binary-codec/index.ts +1 -0
- package/src/core/events/README.md +47 -0
- package/src/core/events/event-system.test.ts +243 -0
- package/src/core/events/event-system.ts +140 -0
- package/src/core/events/index.ts +1 -0
- package/src/core/fixed-ticker/README.md +77 -0
- package/src/core/fixed-ticker/fixed-ticker.test.ts +151 -0
- package/src/core/fixed-ticker/fixed-ticker.ts +158 -0
- package/src/core/fixed-ticker/index.ts +1 -0
- package/src/core/generate-id/README.md +18 -0
- package/src/core/generate-id/generate-id.test.ts +79 -0
- package/src/core/generate-id/generate-id.ts +37 -0
- package/src/core/generate-id/index.ts +1 -0
- package/src/core/index.ts +8 -0
- package/src/core/lerp/README.md +79 -0
- package/src/core/lerp/index.ts +1 -0
- package/src/core/lerp/lerp.test.ts +90 -0
- package/src/core/lerp/lerp.ts +42 -0
- package/src/core/navmesh/README.md +124 -0
- package/src/core/navmesh/index.ts +1 -0
- package/src/core/navmesh/navmesh.test.ts +344 -0
- package/src/core/navmesh/navmesh.ts +850 -0
- package/src/core/pooled-codec/README.md +70 -0
- package/src/core/pooled-codec/index.ts +1 -0
- package/src/core/pooled-codec/pooled-codec.test.ts +349 -0
- package/src/core/pooled-codec/pooled-codec.ts +239 -0
- package/src/core/prediction/README.md +64 -0
- package/src/core/prediction/index.ts +1 -0
- package/src/core/prediction/prediction.test.ts +422 -0
- package/src/core/prediction/prediction.ts +101 -0
- package/src/index.ts +20 -0
- package/src/protocol/README.md +310 -0
- package/src/protocol/index.ts +44 -0
- package/src/protocol/intent/index.ts +40 -0
- package/src/protocol/intent/intent-registry.test.ts +237 -0
- package/src/protocol/intent/intent-registry.ts +88 -0
- package/src/protocol/intent/intent.ts +12 -0
- package/src/protocol/snapshot/index.ts +45 -0
- package/src/protocol/snapshot/snapshot-codec.test.ts +138 -0
- package/src/protocol/snapshot/snapshot-codec.ts +71 -0
- package/src/protocol/snapshot/snapshot-registry.test.ts +302 -0
- package/src/protocol/snapshot/snapshot-registry.ts +162 -0
- package/src/protocol/snapshot/snapshot.test.ts +76 -0
- package/src/protocol/snapshot/snapshot.ts +41 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* A callback-based event handling system designed to simplify
|
|
4
|
+
* event-driven programming.
|
|
5
|
+
*/
|
|
6
|
+
export class EventSystem {
|
|
7
|
+
constructor({ events }) {
|
|
8
|
+
this.callbacks = new Map();
|
|
9
|
+
this.events = events;
|
|
10
|
+
for (const name of this.events) {
|
|
11
|
+
this.callbacks.set(name, new Set());
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @description
|
|
16
|
+
* Registers a callback for an event.
|
|
17
|
+
*
|
|
18
|
+
* @param name Event name
|
|
19
|
+
* @param callback Callback to run when the event is emitted
|
|
20
|
+
*/
|
|
21
|
+
on(name, callback) {
|
|
22
|
+
const event = this.callbacks.get(name);
|
|
23
|
+
if (!event)
|
|
24
|
+
return console.warn(`Event "${name}" does not exist.`);
|
|
25
|
+
event.add(callback);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @description
|
|
29
|
+
* Registers a callback for an event that runs only once.
|
|
30
|
+
*
|
|
31
|
+
* @param name Event name
|
|
32
|
+
* @param callback Callback to run when the event is emitted
|
|
33
|
+
*/
|
|
34
|
+
once(name, callback) {
|
|
35
|
+
const wrapper = (props) => {
|
|
36
|
+
callback(props);
|
|
37
|
+
this.off(name, wrapper);
|
|
38
|
+
};
|
|
39
|
+
this.on(name, wrapper);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* @description
|
|
43
|
+
* Emits an event, running all registered callbacks.
|
|
44
|
+
*
|
|
45
|
+
* @param name Event name
|
|
46
|
+
* @param data Event data
|
|
47
|
+
*/
|
|
48
|
+
emit(name, data) {
|
|
49
|
+
const event = this.callbacks.get(name);
|
|
50
|
+
if (!event)
|
|
51
|
+
return console.warn(`Event "${name}" does not exist.`);
|
|
52
|
+
for (const callback of event) {
|
|
53
|
+
callback(data);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @description
|
|
58
|
+
* Removes a callback from an event.
|
|
59
|
+
*
|
|
60
|
+
* @param name Event name
|
|
61
|
+
* @param callback Callback to remove
|
|
62
|
+
*/
|
|
63
|
+
off(name, callback) {
|
|
64
|
+
const event = this.callbacks.get(name);
|
|
65
|
+
if (!event)
|
|
66
|
+
return console.warn(`Event "${name}" does not exist.`);
|
|
67
|
+
event.delete(callback);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* @description
|
|
71
|
+
* Removes all callbacks.
|
|
72
|
+
*
|
|
73
|
+
* @param name Optional event name
|
|
74
|
+
*/
|
|
75
|
+
clear(name) {
|
|
76
|
+
if (!name) {
|
|
77
|
+
this.callbacks.clear();
|
|
78
|
+
for (const name of this.events) {
|
|
79
|
+
this.callbacks.set(name, new Set());
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const event = this.callbacks.get(name);
|
|
84
|
+
if (!event)
|
|
85
|
+
return console.warn(`Event "${name}" does not exist.`);
|
|
86
|
+
event.clear();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './event-system';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './event-system';
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* A utility class for managing fixed-rate update ticks, useful for deterministic behaviour
|
|
4
|
+
* in both client and server.
|
|
5
|
+
*
|
|
6
|
+
* The `FixedTicker` accumulates elapsed time and determines how many fixed-interval "ticks"
|
|
7
|
+
* should be processed based on a specified tick rate. It also limits the maximum number of
|
|
8
|
+
* ticks per frame to prevent runaway update loops when frame times are long.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* - The `tick` method should be called once per frame, passing the elapsed time in seconds.
|
|
13
|
+
* - The class ensures that no more than a safe number of ticks are processed per frame.
|
|
14
|
+
*/
|
|
15
|
+
export declare class FixedTicker {
|
|
16
|
+
/**
|
|
17
|
+
* @description Accumulator for the time passed since the last tick
|
|
18
|
+
*/
|
|
19
|
+
private accumulator;
|
|
20
|
+
/**
|
|
21
|
+
* @description Rate of ticks per second
|
|
22
|
+
*/
|
|
23
|
+
rate: number;
|
|
24
|
+
/**
|
|
25
|
+
* @description
|
|
26
|
+
* Interval in milliseconds per tick
|
|
27
|
+
*/
|
|
28
|
+
private intervalMs;
|
|
29
|
+
/**
|
|
30
|
+
* @description
|
|
31
|
+
* Maximum amount of ticks to run per frame, to avoid
|
|
32
|
+
* running too many ticks in a single frame.
|
|
33
|
+
*/
|
|
34
|
+
private maxTicksPerFrame;
|
|
35
|
+
/**
|
|
36
|
+
* @description
|
|
37
|
+
* Callback to execute on each tick
|
|
38
|
+
*/
|
|
39
|
+
private onTick;
|
|
40
|
+
/**
|
|
41
|
+
* @description
|
|
42
|
+
* Optional callback to execute when ticks are skipped due to high delta time.
|
|
43
|
+
* This can be useful for debugging or logging purposes.
|
|
44
|
+
*/
|
|
45
|
+
private onTickSkipped?;
|
|
46
|
+
/**
|
|
47
|
+
* @description
|
|
48
|
+
* Internal counter for the number of ticks processed.
|
|
49
|
+
*/
|
|
50
|
+
private _tickCount;
|
|
51
|
+
constructor({ rate, onTick }: FixedTickerProps);
|
|
52
|
+
/**
|
|
53
|
+
* @description
|
|
54
|
+
* Returns how many ticks to run.
|
|
55
|
+
*
|
|
56
|
+
* @param deltaTime Delta time in seconds
|
|
57
|
+
* @returns {number} Amount of ticks to run
|
|
58
|
+
*/
|
|
59
|
+
private getTicks;
|
|
60
|
+
/**
|
|
61
|
+
* @description
|
|
62
|
+
* Processes the ticks based on the elapsed time.
|
|
63
|
+
*
|
|
64
|
+
* @param deltaTime Delta time in seconds
|
|
65
|
+
*/
|
|
66
|
+
tick(deltaTime: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* @description
|
|
69
|
+
* Returns the number of ticks processed since the last reset.
|
|
70
|
+
*
|
|
71
|
+
* @returns {number} Number of ticks processed
|
|
72
|
+
*/
|
|
73
|
+
get tickCount(): number;
|
|
74
|
+
/**
|
|
75
|
+
* @description
|
|
76
|
+
* Resets the tick count to zero.
|
|
77
|
+
*/
|
|
78
|
+
resetTickCount(): void;
|
|
79
|
+
/**
|
|
80
|
+
* @description
|
|
81
|
+
* Returns the accumulated time in seconds, useful for interpolation.
|
|
82
|
+
*
|
|
83
|
+
* @returns {number} Accumulated time in seconds
|
|
84
|
+
*/
|
|
85
|
+
get accumulatedTime(): number;
|
|
86
|
+
}
|
|
87
|
+
interface FixedTickerProps {
|
|
88
|
+
/**
|
|
89
|
+
* @description
|
|
90
|
+
* Rate of ticks per second
|
|
91
|
+
*/
|
|
92
|
+
rate: number;
|
|
93
|
+
/**
|
|
94
|
+
* @description
|
|
95
|
+
* Callback to execute on each tick
|
|
96
|
+
*/
|
|
97
|
+
onTick: (deltaTime: number, tick?: number) => void;
|
|
98
|
+
/**
|
|
99
|
+
* @description
|
|
100
|
+
* Optional callback to execute when ticks are skipped due to high delta time.
|
|
101
|
+
* This can be useful for debugging or logging purposes.
|
|
102
|
+
*/
|
|
103
|
+
onTickSkipped?: (skippedTicks: number) => void;
|
|
104
|
+
}
|
|
105
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* A utility class for managing fixed-rate update ticks, useful for deterministic behaviour
|
|
4
|
+
* in both client and server.
|
|
5
|
+
*
|
|
6
|
+
* The `FixedTicker` accumulates elapsed time and determines how many fixed-interval "ticks"
|
|
7
|
+
* should be processed based on a specified tick rate. It also limits the maximum number of
|
|
8
|
+
* ticks per frame to prevent runaway update loops when frame times are long.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* - The `tick` method should be called once per frame, passing the elapsed time in seconds.
|
|
13
|
+
* - The class ensures that no more than a safe number of ticks are processed per frame.
|
|
14
|
+
*/
|
|
15
|
+
export class FixedTicker {
|
|
16
|
+
constructor({ rate, onTick }) {
|
|
17
|
+
/**
|
|
18
|
+
* @description Accumulator for the time passed since the last tick
|
|
19
|
+
*/
|
|
20
|
+
this.accumulator = 0;
|
|
21
|
+
/**
|
|
22
|
+
* @description
|
|
23
|
+
* Internal counter for the number of ticks processed.
|
|
24
|
+
*/
|
|
25
|
+
this._tickCount = 0;
|
|
26
|
+
this.rate = rate;
|
|
27
|
+
this.intervalMs = 1000 / this.rate;
|
|
28
|
+
this.onTick = onTick;
|
|
29
|
+
// Allow up to rate/2 ticks per frame, but at least 1.
|
|
30
|
+
// Prevents runaway loops if delta is too large.
|
|
31
|
+
this.maxTicksPerFrame = Math.max(1, Math.floor(rate / 2));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @description
|
|
35
|
+
* Returns how many ticks to run.
|
|
36
|
+
*
|
|
37
|
+
* @param deltaTime Delta time in seconds
|
|
38
|
+
* @returns {number} Amount of ticks to run
|
|
39
|
+
*/
|
|
40
|
+
getTicks(deltaTime) {
|
|
41
|
+
this.accumulator += deltaTime * 1000;
|
|
42
|
+
let ticks = 0;
|
|
43
|
+
while (this.accumulator >= this.intervalMs &&
|
|
44
|
+
ticks < this.maxTicksPerFrame) {
|
|
45
|
+
this.accumulator -= this.intervalMs;
|
|
46
|
+
ticks++;
|
|
47
|
+
}
|
|
48
|
+
const skippedTicks = Math.floor(this.accumulator / this.intervalMs);
|
|
49
|
+
if (skippedTicks > 0 && this.onTickSkipped) {
|
|
50
|
+
this.onTickSkipped(skippedTicks);
|
|
51
|
+
}
|
|
52
|
+
return ticks;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @description
|
|
56
|
+
* Processes the ticks based on the elapsed time.
|
|
57
|
+
*
|
|
58
|
+
* @param deltaTime Delta time in seconds
|
|
59
|
+
*/
|
|
60
|
+
tick(deltaTime) {
|
|
61
|
+
const ticks = this.getTicks(deltaTime);
|
|
62
|
+
for (let i = 0; i < ticks; i++) {
|
|
63
|
+
this.onTick(1 / this.rate, this._tickCount++);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* @description
|
|
68
|
+
* Returns the number of ticks processed since the last reset.
|
|
69
|
+
*
|
|
70
|
+
* @returns {number} Number of ticks processed
|
|
71
|
+
*/
|
|
72
|
+
get tickCount() {
|
|
73
|
+
return this._tickCount;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* @description
|
|
77
|
+
* Resets the tick count to zero.
|
|
78
|
+
*/
|
|
79
|
+
resetTickCount() {
|
|
80
|
+
this._tickCount = 0;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @description
|
|
84
|
+
* Returns the accumulated time in seconds, useful for interpolation.
|
|
85
|
+
*
|
|
86
|
+
* @returns {number} Accumulated time in seconds
|
|
87
|
+
*/
|
|
88
|
+
get accumulatedTime() {
|
|
89
|
+
return this.accumulator / 1000; // Convert to seconds
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './fixed-ticker';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './fixed-ticker';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface GenerateIdOptions {
|
|
2
|
+
/** Optional prefix to prepend to the ID */
|
|
3
|
+
prefix?: string;
|
|
4
|
+
/** Total length of the returned ID including prefix (default 16) */
|
|
5
|
+
size?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* Generates a unique identifier as a hexadecimal string.
|
|
10
|
+
* Can include a prefix and a custom total length.
|
|
11
|
+
*
|
|
12
|
+
* @param options Optional configuration: prefix and total size
|
|
13
|
+
* @returns A unique identifier string
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* generateId(); // "f3a2b1c4d5e67890"
|
|
17
|
+
* generateId({ prefix: 'user_' }); // "user_f3a2b1c4d5e67890"
|
|
18
|
+
* generateId({ prefix: 'user_', size: 24 }); // "user_00f3a2b1c4d5e67890"
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateId(options?: GenerateIdOptions): string;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Generates a unique identifier as a hexadecimal string.
|
|
4
|
+
* Can include a prefix and a custom total length.
|
|
5
|
+
*
|
|
6
|
+
* @param options Optional configuration: prefix and total size
|
|
7
|
+
* @returns A unique identifier string
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* generateId(); // "f3a2b1c4d5e67890"
|
|
11
|
+
* generateId({ prefix: 'user_' }); // "user_f3a2b1c4d5e67890"
|
|
12
|
+
* generateId({ prefix: 'user_', size: 24 }); // "user_00f3a2b1c4d5e67890"
|
|
13
|
+
*/
|
|
14
|
+
export function generateId(options = {}) {
|
|
15
|
+
const { prefix = "", size = 16 } = options;
|
|
16
|
+
// compute number of hex characters to generate (subtract prefix length)
|
|
17
|
+
const hexLength = Math.max(size - prefix.length, 8); // min 8 hex chars
|
|
18
|
+
// number of 32-bit integers needed to cover the hexLength
|
|
19
|
+
const numInts = Math.ceil(hexLength / 8);
|
|
20
|
+
const arr = crypto.getRandomValues(new Uint32Array(numInts));
|
|
21
|
+
let id = arr.reduce((acc, val) => acc + val.toString(16).padStart(8, "0"), "");
|
|
22
|
+
// truncate/pad to desired length
|
|
23
|
+
id = id.slice(0, hexLength).padStart(hexLength, "0");
|
|
24
|
+
return `${prefix}${id}`;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './generate-id';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './generate-id';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lerp';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lerp';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Performs linear interpolation between two values.
|
|
4
|
+
*
|
|
5
|
+
* Linear interpolation (lerp) calculates a value between a start and end point
|
|
6
|
+
* based on a normalized interpolation factor (t). When t = 0, the result equals
|
|
7
|
+
* the start value; when t = 1, the result equals the end value. Values of t
|
|
8
|
+
* between 0 and 1 produce intermediate results.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* - This function does not clamp the interpolation factor. Values of t outside
|
|
12
|
+
* the range [0, 1] will extrapolate beyond the start and end values.
|
|
13
|
+
* - For clamped interpolation, combine with a clamp function on the t parameter.
|
|
14
|
+
* - Commonly used for smooth animations, camera movements, and value transitions.
|
|
15
|
+
*
|
|
16
|
+
* @param start - The starting value (when t = 0)
|
|
17
|
+
* @param end - The ending value (when t = 1)
|
|
18
|
+
* @param t - The interpolation factor, typically in the range [0, 1]
|
|
19
|
+
*
|
|
20
|
+
* @returns {number} The interpolated value between start and end
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Basic interpolation
|
|
25
|
+
* lerp(0, 100, 0.5); // Returns 50
|
|
26
|
+
* lerp(0, 100, 0); // Returns 0
|
|
27
|
+
* lerp(0, 100, 1); // Returns 100
|
|
28
|
+
*
|
|
29
|
+
* // Animation example
|
|
30
|
+
* const startPos = 0;
|
|
31
|
+
* const endPos = 100;
|
|
32
|
+
* const progress = 0.75;
|
|
33
|
+
* const currentPos = lerp(startPos, endPos, progress); // Returns 75
|
|
34
|
+
*
|
|
35
|
+
* // Extrapolation (t outside [0, 1])
|
|
36
|
+
* lerp(0, 100, 1.5); // Returns 150
|
|
37
|
+
* lerp(0, 100, -0.5); // Returns -50
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function lerp(start: number, end: number, t: number): number;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Performs linear interpolation between two values.
|
|
4
|
+
*
|
|
5
|
+
* Linear interpolation (lerp) calculates a value between a start and end point
|
|
6
|
+
* based on a normalized interpolation factor (t). When t = 0, the result equals
|
|
7
|
+
* the start value; when t = 1, the result equals the end value. Values of t
|
|
8
|
+
* between 0 and 1 produce intermediate results.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* - This function does not clamp the interpolation factor. Values of t outside
|
|
12
|
+
* the range [0, 1] will extrapolate beyond the start and end values.
|
|
13
|
+
* - For clamped interpolation, combine with a clamp function on the t parameter.
|
|
14
|
+
* - Commonly used for smooth animations, camera movements, and value transitions.
|
|
15
|
+
*
|
|
16
|
+
* @param start - The starting value (when t = 0)
|
|
17
|
+
* @param end - The ending value (when t = 1)
|
|
18
|
+
* @param t - The interpolation factor, typically in the range [0, 1]
|
|
19
|
+
*
|
|
20
|
+
* @returns {number} The interpolated value between start and end
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Basic interpolation
|
|
25
|
+
* lerp(0, 100, 0.5); // Returns 50
|
|
26
|
+
* lerp(0, 100, 0); // Returns 0
|
|
27
|
+
* lerp(0, 100, 1); // Returns 100
|
|
28
|
+
*
|
|
29
|
+
* // Animation example
|
|
30
|
+
* const startPos = 0;
|
|
31
|
+
* const endPos = 100;
|
|
32
|
+
* const progress = 0.75;
|
|
33
|
+
* const currentPos = lerp(startPos, endPos, progress); // Returns 75
|
|
34
|
+
*
|
|
35
|
+
* // Extrapolation (t outside [0, 1])
|
|
36
|
+
* lerp(0, 100, 1.5); // Returns 150
|
|
37
|
+
* lerp(0, 100, -0.5); // Returns -50
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function lerp(start, end, t) {
|
|
41
|
+
return start + (end - start) * t;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navmesh';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navmesh';
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
type ObstacleId = number;
|
|
2
|
+
export type Obstacle = CircleObstacle | RectObstacle | PolygonObstacle;
|
|
3
|
+
export type ObstacleInput = Omit<CircleObstacle, 'id'> | Omit<RectObstacle, 'id'> | Omit<PolygonObstacle, 'id'>;
|
|
4
|
+
interface Vec2 {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}
|
|
8
|
+
interface BaseObstacle {
|
|
9
|
+
id: ObstacleId;
|
|
10
|
+
type: 'circle' | 'rect' | 'polygon';
|
|
11
|
+
solid?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface CircleObstacle extends BaseObstacle {
|
|
14
|
+
type: 'circle';
|
|
15
|
+
pos: Vec2;
|
|
16
|
+
radius: number;
|
|
17
|
+
}
|
|
18
|
+
export interface RectObstacle extends BaseObstacle {
|
|
19
|
+
type: 'rect';
|
|
20
|
+
pos: Vec2;
|
|
21
|
+
size: Vec2;
|
|
22
|
+
rotation?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Polygon obstacle.
|
|
26
|
+
* IMPORTANT: `points` must be defined relative to local origin (0,0).
|
|
27
|
+
* The polygon will be rotated around (0,0) then translated to `pos`.
|
|
28
|
+
* Do NOT define points in world space.
|
|
29
|
+
*/
|
|
30
|
+
export interface PolygonObstacle extends BaseObstacle {
|
|
31
|
+
type: 'polygon';
|
|
32
|
+
points: Vec2[];
|
|
33
|
+
pos: Vec2;
|
|
34
|
+
rotation?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Manages obstacles with spatial hashing for fast queries.
|
|
38
|
+
* Version tracking prevents unnecessary rebuilds.
|
|
39
|
+
*/
|
|
40
|
+
declare class Obstacles {
|
|
41
|
+
private items;
|
|
42
|
+
private spatial;
|
|
43
|
+
private _cachedItems;
|
|
44
|
+
dirty: boolean;
|
|
45
|
+
version: number;
|
|
46
|
+
add(obstacle: ObstacleInput): ObstacleId;
|
|
47
|
+
move(id: ObstacleId, pos: Vec2): void;
|
|
48
|
+
remove(id: ObstacleId): void;
|
|
49
|
+
/**
|
|
50
|
+
* Fast spatial query using hash grid.
|
|
51
|
+
* O(1) average case instead of O(n) linear scan.
|
|
52
|
+
*/
|
|
53
|
+
at(pos: Vec2): Obstacle | undefined;
|
|
54
|
+
get values(): Obstacle[];
|
|
55
|
+
}
|
|
56
|
+
type NavType = 'grid' | 'graph';
|
|
57
|
+
/**
|
|
58
|
+
* Navigation mesh with spatial hashing and smart rebuild.
|
|
59
|
+
*
|
|
60
|
+
* Features:
|
|
61
|
+
* - Spatial hash: O(1) obstacle queries
|
|
62
|
+
* - Version tracking: zero unnecessary rebuilds
|
|
63
|
+
* - Binary heap A*: handles 10k+ node searches
|
|
64
|
+
* - Simple full rebuild: correct and fast enough
|
|
65
|
+
*
|
|
66
|
+
* Performance characteristics:
|
|
67
|
+
* - Obstacle query: O(1) average via spatial hash
|
|
68
|
+
* - Grid rebuild: O(n * area), < 1ms for typical games
|
|
69
|
+
* - Pathfinding: O(b^d * log n) with binary heap
|
|
70
|
+
*
|
|
71
|
+
* Production ready for:
|
|
72
|
+
* - Grid-based games
|
|
73
|
+
* - RTS with < 1000 dynamic obstacles
|
|
74
|
+
* - Turn-based games
|
|
75
|
+
* - Moderate map sizes (< 1M cells)
|
|
76
|
+
*/
|
|
77
|
+
export declare class NavMesh {
|
|
78
|
+
private type;
|
|
79
|
+
private grid?;
|
|
80
|
+
private graph?;
|
|
81
|
+
private lastVersion;
|
|
82
|
+
obstacles: Obstacles;
|
|
83
|
+
constructor(type: NavType);
|
|
84
|
+
/**
|
|
85
|
+
* Adds an obstacle and returns its unique ID.
|
|
86
|
+
* For polygons: ensure points are defined relative to (0,0).
|
|
87
|
+
*/
|
|
88
|
+
addObstacle(obstacle: ObstacleInput): ObstacleId;
|
|
89
|
+
/**
|
|
90
|
+
* Moves an existing obstacle to a new position.
|
|
91
|
+
*/
|
|
92
|
+
moveObstacle(id: ObstacleId, pos: Vec2): void;
|
|
93
|
+
/**
|
|
94
|
+
* Removes an obstacle by ID.
|
|
95
|
+
*/
|
|
96
|
+
removeObstacle(id: ObstacleId): void;
|
|
97
|
+
/**
|
|
98
|
+
* Returns all current obstacles.
|
|
99
|
+
*/
|
|
100
|
+
getObstacles(): Obstacle[];
|
|
101
|
+
/**
|
|
102
|
+
* Finds a path from start to goal.
|
|
103
|
+
* Automatically rebuilds navigation data if obstacles changed.
|
|
104
|
+
* Returns empty array if no path exists.
|
|
105
|
+
*/
|
|
106
|
+
findPath({ from, to }: {
|
|
107
|
+
from: Vec2;
|
|
108
|
+
to: Vec2;
|
|
109
|
+
}): Vec2[];
|
|
110
|
+
/**
|
|
111
|
+
* Smart rebuild - only rebuilds if obstacles changed.
|
|
112
|
+
* Version checking eliminates unnecessary work.
|
|
113
|
+
*/
|
|
114
|
+
rebuild(): void;
|
|
115
|
+
}
|
|
116
|
+
export {};
|