@xtia/grid 0.0.8 → 0.0.10
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 +16 -1
- package/lib/grid.d.ts +2 -2
- package/lib/grid.js +18 -16
- package/lib/utils.d.ts +0 -8
- package/lib/utils.js +0 -9
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -130,6 +130,21 @@ const mountainCells = world.cells.toFlatArrayXY()
|
|
|
130
130
|
.filter(cell => cell.value === "mountain")
|
|
131
131
|
.map(cell => [cell.x, cell.y]);
|
|
132
132
|
|
|
133
|
+
// or get a live, renderable minimap
|
|
134
|
+
import { C } from "@xtia/rgba";
|
|
135
|
+
|
|
136
|
+
const colourMap = new Map(Object.entries({
|
|
137
|
+
grass: C.x0f0,
|
|
138
|
+
water: C.x00f,
|
|
139
|
+
forest: C.x080,
|
|
140
|
+
mountain: C.xa70
|
|
141
|
+
}));
|
|
142
|
+
const minimap = world.pipe
|
|
143
|
+
.map(colourMap)
|
|
144
|
+
.floorCoordinates()
|
|
145
|
+
.crop(viewX, viewY, vw, vh)
|
|
146
|
+
.stretch(canvas.width, canvas.height);
|
|
147
|
+
|
|
133
148
|
```
|
|
134
149
|
|
|
135
150
|
## Cell interface
|
|
@@ -190,7 +205,7 @@ const visibility = start.createVisibilityMap(
|
|
|
190
205
|
|
|
191
206
|
// any 2d source, including visibility maps, can be used as a mask for paste/fill operations
|
|
192
207
|
// paste(source: Source2D<T>, mask?: Source2D<boolean>)
|
|
193
|
-
screenGrid.paste(spriteMap, visibility);
|
|
208
|
+
screenGrid.paste(spriteMap, 0, 0, visibility);
|
|
194
209
|
```
|
|
195
210
|
|
|
196
211
|
### Reusing path data
|
package/lib/grid.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ type PathFindOptions<T> = {
|
|
|
13
13
|
cell: Cell<T>;
|
|
14
14
|
cost: number;
|
|
15
15
|
}) => void;
|
|
16
|
-
shortcutMap?: Source2D<
|
|
16
|
+
shortcutMap?: Source2D<LocationSpec<T>[] | undefined> | GetXYFunc<LocationSpec<T>[] | undefined>;
|
|
17
17
|
};
|
|
18
18
|
type CostMapOptions<T> = PathFindOptions<T> & {
|
|
19
19
|
stopAt?: LocationSpec<T>;
|
|
@@ -65,7 +65,7 @@ export declare class Grid<T> {
|
|
|
65
65
|
set(x: number, y: number, value: T): void;
|
|
66
66
|
trySet(x: number, y: number, value: T): boolean;
|
|
67
67
|
fill(value: T, mask?: Source2D<boolean> | GetXYFunc<boolean>): void;
|
|
68
|
-
paste(
|
|
68
|
+
paste(source: Source2D<T>, x?: number, y?: number, mask?: Source2D<boolean> | GetXYFunc<boolean>): void;
|
|
69
69
|
[Symbol.iterator](): IterableIterator<{
|
|
70
70
|
x: number;
|
|
71
71
|
y: number;
|
package/lib/grid.js
CHANGED
|
@@ -50,11 +50,7 @@ export class Cell {
|
|
|
50
50
|
return this.gridView.cells.get(xDelta + this.x, yDelta + this.y);
|
|
51
51
|
}
|
|
52
52
|
findPath(target, getCost, options = {}) {
|
|
53
|
-
const pathMap = this.calculateCosts(getCost, {
|
|
54
|
-
stopAt: target,
|
|
55
|
-
allowDiagonal: options.allowDiagonal,
|
|
56
|
-
maxCost: options.maxCost,
|
|
57
|
-
}, true);
|
|
53
|
+
const pathMap = this.calculateCosts(getCost, Object.assign(Object.assign({}, options), { stopAt: target }), true);
|
|
58
54
|
return pathMap === null || pathMap === void 0 ? void 0 : pathMap.get(...this.getSiblingXY(target));
|
|
59
55
|
}
|
|
60
56
|
getPathMap(getCost, options = {}) {
|
|
@@ -89,7 +85,7 @@ export class Cell {
|
|
|
89
85
|
}
|
|
90
86
|
const currentCost = costs.get(current);
|
|
91
87
|
const neighbours = current.getNeighbours(options.allowDiagonal).map(cell => ({
|
|
92
|
-
traversalType: cell.x == current.x
|
|
88
|
+
traversalType: cell.x == current.x || cell.y == current.y
|
|
93
89
|
? TraversalType.cardinal
|
|
94
90
|
: TraversalType.diagonal,
|
|
95
91
|
cell
|
|
@@ -98,7 +94,7 @@ export class Cell {
|
|
|
98
94
|
? options.shortcutMap(current.x, current.y)
|
|
99
95
|
: (_b = options.shortcutMap) === null || _b === void 0 ? void 0 : _b.get(current.x, current.y);
|
|
100
96
|
if (shortcutCells) {
|
|
101
|
-
const shortcuts = shortcutCells.map(cell => ({
|
|
97
|
+
const shortcuts = shortcutCells.map(loc => this.getSiblingCell(loc)).map(cell => ({
|
|
102
98
|
traversalType: TraversalType.shortcut,
|
|
103
99
|
cell
|
|
104
100
|
}));
|
|
@@ -185,14 +181,14 @@ export class Cell {
|
|
|
185
181
|
}
|
|
186
182
|
}
|
|
187
183
|
createVisibilityMap(isClear, options = {}) {
|
|
188
|
-
var _a
|
|
189
|
-
const maxDistance =
|
|
190
|
-
const boundariesVisible = (
|
|
184
|
+
var _a;
|
|
185
|
+
const maxDistance = options.maxDistance;
|
|
186
|
+
const boundariesVisible = (_a = options.boundariesVisible) !== null && _a !== void 0 ? _a : true;
|
|
191
187
|
return new Pipe2D(this.gridView.width, this.gridView.height, (x, y) => {
|
|
192
188
|
if (!isClear(this)) {
|
|
193
189
|
return x === this.x && y === this.y ? boundariesVisible : false;
|
|
194
190
|
}
|
|
195
|
-
if (maxDistance
|
|
191
|
+
if (maxDistance !== undefined) {
|
|
196
192
|
if (getDistance(this, { x, y }) > maxDistance) {
|
|
197
193
|
return false;
|
|
198
194
|
}
|
|
@@ -239,7 +235,12 @@ export class Grid {
|
|
|
239
235
|
this.parentSet(x, y, value);
|
|
240
236
|
}
|
|
241
237
|
trySet(x, y, value) {
|
|
242
|
-
if (x < 0
|
|
238
|
+
if (x < 0
|
|
239
|
+
|| x >= this.width
|
|
240
|
+
|| y < 0
|
|
241
|
+
|| y >= this.height
|
|
242
|
+
|| !Number.isInteger(x)
|
|
243
|
+
|| !Number.isInteger(y))
|
|
243
244
|
return false;
|
|
244
245
|
this.set(x, y, value);
|
|
245
246
|
return true;
|
|
@@ -260,7 +261,7 @@ export class Grid {
|
|
|
260
261
|
}
|
|
261
262
|
});
|
|
262
263
|
}
|
|
263
|
-
paste(x, y
|
|
264
|
+
paste(source, x = 0, y = 0, mask) {
|
|
264
265
|
const maskSource = typeof mask == "function" ? {
|
|
265
266
|
width: this.width,
|
|
266
267
|
height: this.height,
|
|
@@ -311,8 +312,6 @@ export class Grid {
|
|
|
311
312
|
return new Grid(width, height, (tx, ty) => {
|
|
312
313
|
return this.parentGet(tx + x, ty + y);
|
|
313
314
|
}, (tx, ty, value) => {
|
|
314
|
-
if (tx < 0 || ty < 0 || tx >= width || ty >= height)
|
|
315
|
-
throw new Error("Out of bounds");
|
|
316
315
|
this.parentSet(tx + x, ty + y, value);
|
|
317
316
|
}, fn => this.batch(fn));
|
|
318
317
|
}
|
|
@@ -381,17 +380,20 @@ export class GridBase extends Grid {
|
|
|
381
380
|
if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
|
|
382
381
|
throw new Error(`Coordinates out of bounds: (${x}, ${y})`);
|
|
383
382
|
}
|
|
383
|
+
if (!Number.isInteger(x) || !Number.isInteger(y)) {
|
|
384
|
+
throw new Error(`Coordinates must be integer; got (${x}, ${y})`);
|
|
385
|
+
}
|
|
384
386
|
return y * this.width + x;
|
|
385
387
|
}
|
|
386
388
|
_set(x, y, value) {
|
|
387
389
|
const idx = this.xyToIndex(x, y);
|
|
388
390
|
if (this.data[idx] === value)
|
|
389
391
|
return;
|
|
392
|
+
this.data[this.xyToIndex(x, y)] = value;
|
|
390
393
|
if (this.batchState) {
|
|
391
394
|
this.batchState.changedCells.add(this.cells.get(x, y));
|
|
392
395
|
return;
|
|
393
396
|
}
|
|
394
|
-
this.data[this.xyToIndex(x, y)] = value;
|
|
395
397
|
if (this.eventHandlers.change) {
|
|
396
398
|
this.triggerChange(new Set([this.cells.get(x, y)]));
|
|
397
399
|
}
|
package/lib/utils.d.ts
CHANGED
|
@@ -4,14 +4,6 @@ export type Source2D<T> = {
|
|
|
4
4
|
height: number;
|
|
5
5
|
get: GetXYFunc<T>;
|
|
6
6
|
};
|
|
7
|
-
export type Angle = {
|
|
8
|
-
asDegrees: number;
|
|
9
|
-
} | {
|
|
10
|
-
asRadians: number;
|
|
11
|
-
} | {
|
|
12
|
-
asTurns: number;
|
|
13
|
-
};
|
|
14
|
-
export declare function angleToRadians(angle: Angle): number;
|
|
15
7
|
export declare class OrderedQueue<T> {
|
|
16
8
|
private getCost;
|
|
17
9
|
private queue;
|
package/lib/utils.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
export function angleToRadians(angle) {
|
|
2
|
-
if ("asRadians" in angle)
|
|
3
|
-
return angle.asRadians;
|
|
4
|
-
if ("asDegrees" in angle)
|
|
5
|
-
return angle.asDegrees * (180 / Math.PI);
|
|
6
|
-
if ("asTurns" in angle)
|
|
7
|
-
return angle.asTurns * Math.PI * 2;
|
|
8
|
-
throw new Error("Invalid angle");
|
|
9
|
-
}
|
|
10
1
|
export class OrderedQueue {
|
|
11
2
|
constructor(getCost, ...values) {
|
|
12
3
|
this.getCost = getCost;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.10",
|
|
3
3
|
"description": "2D store and utilities, with zero-copy regions and transform layers, pathfinding, Pipe2D interop",
|
|
4
4
|
"name": "@xtia/grid",
|
|
5
5
|
"exports": {
|
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
},
|
|
10
10
|
"./lib/*": null
|
|
11
11
|
},
|
|
12
|
-
"keywords": [
|
|
12
|
+
"keywords": [
|
|
13
|
+
"grid",
|
|
14
|
+
"game-dev",
|
|
15
|
+
"pathfinding",
|
|
16
|
+
"cellular-automata"
|
|
17
|
+
],
|
|
13
18
|
"scripts": {
|
|
14
19
|
"build": "npx tsc",
|
|
15
20
|
"test": "npx vitest run"
|
|
@@ -18,10 +23,11 @@
|
|
|
18
23
|
"lib/"
|
|
19
24
|
],
|
|
20
25
|
"devDependencies": {
|
|
26
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
21
27
|
"typescript": "^7.0.2",
|
|
22
28
|
"vitest": "^4.1.10"
|
|
23
29
|
},
|
|
24
30
|
"dependencies": {
|
|
25
|
-
"@xtia/pipe2d": "^2.1
|
|
31
|
+
"@xtia/pipe2d": "^2.2.1"
|
|
26
32
|
}
|
|
27
33
|
}
|