@xtia/grid 0.0.13 → 0.1.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 +7 -9
- package/lib/grid.d.ts +1 -7
- package/lib/grid.js +15 -28
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `Grid`
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Beta**: Stable core, open to refinement pre-1.0.0
|
|
4
4
|
|
|
5
5
|
## Summary
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ npm i @xtia/grid
|
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
import { Grid } from "@xtia/grid"; // ~4.8kb gzipped
|
|
25
|
+
import { Grid } from "@xtia/grid"; // ~4.8kb gzipped (2.2kb + Pipe2D dep)
|
|
26
26
|
|
|
27
27
|
// initialise a 30x20 Grid<number> of 0's
|
|
28
28
|
const numGrid = Grid.solid(30, 20, 0);
|
|
@@ -32,7 +32,7 @@ numGrid.set(3, 3, 50);
|
|
|
32
32
|
|
|
33
33
|
// initialise a chessboard
|
|
34
34
|
const chessGrid = Grid.init(8, 8, (x, y) =>
|
|
35
|
-
|
|
35
|
+
(x + y) % 2 === 0 ? 'black' : 'white'
|
|
36
36
|
);
|
|
37
37
|
|
|
38
38
|
// read a value
|
|
@@ -106,12 +106,11 @@ const lakeGrid = Grid.from(lakeRegion);
|
|
|
106
106
|
|
|
107
107
|
```ts
|
|
108
108
|
const spriteMap = world.map(
|
|
109
|
-
type => type + ".png",
|
|
110
|
-
sprite => sprite.replace(/\..*/, '')
|
|
109
|
+
type => type + ".png", // add .png on parent-read
|
|
110
|
+
sprite => sprite.replace(/\..*/, '') // remove it on parent-write
|
|
111
111
|
);
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
console.log(spriteMap.get(0, 0)); // read the transformed view: "mountain.png"
|
|
113
|
+
console.log(spriteMap.get(0, 0)); // read the transformed view: "grass.png"
|
|
115
114
|
spriteMap.set(1, 0, "forest.png"); // modify the view
|
|
116
115
|
console.log(world.get(1, 0)); // read the parent: "forest"
|
|
117
116
|
```
|
|
@@ -144,7 +143,6 @@ const minimap = world.pipe
|
|
|
144
143
|
.floorCoordinates()
|
|
145
144
|
.crop(viewX, viewY, vw, vh)
|
|
146
145
|
.stretch(canvas.width, canvas.height);
|
|
147
|
-
|
|
148
146
|
```
|
|
149
147
|
|
|
150
148
|
## Cell interface
|
|
@@ -248,7 +246,7 @@ world.paste(snapshot);
|
|
|
248
246
|
For persistent storage or transmission, Pipe2D can export as array:
|
|
249
247
|
|
|
250
248
|
```ts
|
|
251
|
-
const saved = snapshot.toFlatArrayXY(); // ["
|
|
249
|
+
const saved = snapshot.toFlatArrayXY(); // ["grass", "forest", "grass", ...]
|
|
252
250
|
|
|
253
251
|
const restoredSnapshot = Pipe2D.fromFlatArrayXY(saved);
|
|
254
252
|
```
|
package/lib/grid.d.ts
CHANGED
|
@@ -67,13 +67,8 @@ export declare class Grid<T> {
|
|
|
67
67
|
fill(value: T): void;
|
|
68
68
|
paste(source: Source2D<T>, x?: number, y?: number): void;
|
|
69
69
|
writeMask(mask: Source2D<boolean> | GetXYFunc<boolean>): Grid<T>;
|
|
70
|
-
[Symbol.iterator](): IterableIterator<
|
|
71
|
-
x: number;
|
|
72
|
-
y: number;
|
|
73
|
-
value: T;
|
|
74
|
-
}>;
|
|
70
|
+
[Symbol.iterator](): IterableIterator<T>;
|
|
75
71
|
forEach(callback: (value: T, x: number, y: number) => void): void;
|
|
76
|
-
combine<U, R>(aux: Source2D<U>, cb: (source: T, aux: U) => R): GridBase<R>;
|
|
77
72
|
map<U>(read: (initial: T, x: number, y: number) => U, write: (local: U, x: number, y: number) => T): Grid<U>;
|
|
78
73
|
region(x: number, y: number, width: number, height: number): Grid<T>;
|
|
79
74
|
scroll(xDelta: number, yDelta: number, fill: T): this;
|
|
@@ -90,7 +85,6 @@ export declare class GridBase<T> extends Grid<T> {
|
|
|
90
85
|
batchUpdate(fn: () => void): void;
|
|
91
86
|
constructor(source: Source2D<T>);
|
|
92
87
|
on<K extends keyof EventMap<T>>(eventName: K, handler: (data: EventMap<T>[K]) => void): () => void;
|
|
93
|
-
private xyToIndex;
|
|
94
88
|
private _set;
|
|
95
89
|
private triggerChange;
|
|
96
90
|
}
|
package/lib/grid.js
CHANGED
|
@@ -215,6 +215,9 @@ export class Grid {
|
|
|
215
215
|
this.parentSet = parentSet;
|
|
216
216
|
this.batch = batch;
|
|
217
217
|
this.cells = new Pipe2D(this.width, this.height, (x, y) => {
|
|
218
|
+
if (x < 0 || x >= this.width || y < 0 || y >= this.height || !Number.isInteger(x) || !Number.isInteger(y)) {
|
|
219
|
+
throw new RangeError(`Cell coordinates must be bounded integers; got (${x}, ${y})`);
|
|
220
|
+
}
|
|
218
221
|
return new Cell(x, y, this);
|
|
219
222
|
}).strict().withCache();
|
|
220
223
|
this.pipe = new Pipe2D(this);
|
|
@@ -261,7 +264,7 @@ export class Grid {
|
|
|
261
264
|
this.batchUpdate(() => {
|
|
262
265
|
for (let y = 0; y < this.height; y++) {
|
|
263
266
|
for (let x = 0; x < this.width; x++) {
|
|
264
|
-
this.
|
|
267
|
+
this.set(x, y, value);
|
|
265
268
|
}
|
|
266
269
|
}
|
|
267
270
|
});
|
|
@@ -271,7 +274,10 @@ export class Grid {
|
|
|
271
274
|
this.batchUpdate(() => {
|
|
272
275
|
for (let oy = 0; oy < source.height; oy++) {
|
|
273
276
|
for (let ox = 0; ox < source.width; ox++) {
|
|
274
|
-
|
|
277
|
+
const tx = ox + x, ty = oy + y;
|
|
278
|
+
if (tx < 0 || tx >= this.width || ty < 0 || ty >= this.height)
|
|
279
|
+
continue;
|
|
280
|
+
this.set(tx, ty, cachedSource.get(ox, oy));
|
|
275
281
|
}
|
|
276
282
|
}
|
|
277
283
|
});
|
|
@@ -290,7 +296,7 @@ export class Grid {
|
|
|
290
296
|
*[Symbol.iterator]() {
|
|
291
297
|
for (let y = 0; y < this.height; y++) {
|
|
292
298
|
for (let x = 0; x < this.width; x++) {
|
|
293
|
-
yield
|
|
299
|
+
yield this.get(x, y);
|
|
294
300
|
}
|
|
295
301
|
}
|
|
296
302
|
}
|
|
@@ -301,22 +307,11 @@ export class Grid {
|
|
|
301
307
|
}
|
|
302
308
|
}
|
|
303
309
|
}
|
|
304
|
-
combine(aux, cb) {
|
|
305
|
-
const width = Math.min(this.width, aux.width);
|
|
306
|
-
const height = Math.min(this.height, aux.height);
|
|
307
|
-
return new GridBase({
|
|
308
|
-
width,
|
|
309
|
-
height,
|
|
310
|
-
get: (x, y) => {
|
|
311
|
-
return cb(this.get(x, y), aux.get(x, y));
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
310
|
map(read, write) {
|
|
316
311
|
return new Grid(this.width, this.height, (x, y) => read(this.parentGet(x, y), x, y), (x, y, value) => this.parentSet(x, y, write(value, x, y)), fn => this.batch(fn));
|
|
317
312
|
}
|
|
318
313
|
region(x, y, width, height) {
|
|
319
|
-
if (!Number.isInteger(x) || !Number.isInteger(y)
|
|
314
|
+
if (!Number.isInteger(x) || !Number.isInteger(y)) {
|
|
320
315
|
throw new Error(`Region boundaries must be integer; got (${x}, ${y}), (${width} x ${height})`);
|
|
321
316
|
}
|
|
322
317
|
if (x < 0 || y < 0 || x + width > this.width || y + height > this.height) {
|
|
@@ -384,11 +379,12 @@ export class GridBase extends Grid {
|
|
|
384
379
|
if (this.batchState.level == 0) {
|
|
385
380
|
const changed = this.batchState.changedCells;
|
|
386
381
|
this.batchState = null;
|
|
387
|
-
|
|
382
|
+
if (changed.size > 0)
|
|
383
|
+
this.triggerChange(changed);
|
|
388
384
|
}
|
|
389
385
|
}
|
|
390
386
|
constructor(source) {
|
|
391
|
-
super(source.width, source.height, (x, y) => this.data[this.
|
|
387
|
+
super(source.width, source.height, (x, y) => this.data[y * this.width + x], (x, y, value) => this._set(x, y, value), fn => this.batchUpdate(fn));
|
|
392
388
|
this.eventHandlers = {};
|
|
393
389
|
this.batchState = null;
|
|
394
390
|
const sourcePipe = source instanceof Pipe2D
|
|
@@ -408,20 +404,11 @@ export class GridBase extends Grid {
|
|
|
408
404
|
this.eventHandlers[eventName].splice(idx, 1);
|
|
409
405
|
};
|
|
410
406
|
}
|
|
411
|
-
xyToIndex(x, y) {
|
|
412
|
-
if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
|
|
413
|
-
throw new Error(`Coordinates out of bounds: (${x}, ${y})`);
|
|
414
|
-
}
|
|
415
|
-
if (!Number.isInteger(x) || !Number.isInteger(y)) {
|
|
416
|
-
throw new Error(`Coordinates must be integer; got (${x}, ${y})`);
|
|
417
|
-
}
|
|
418
|
-
return y * this.width + x;
|
|
419
|
-
}
|
|
420
407
|
_set(x, y, value) {
|
|
421
|
-
const idx = this.
|
|
408
|
+
const idx = y * this.width + x;
|
|
422
409
|
if (this.data[idx] === value)
|
|
423
410
|
return;
|
|
424
|
-
this.data[
|
|
411
|
+
this.data[idx] = value;
|
|
425
412
|
if (this.batchState) {
|
|
426
413
|
this.batchState.changedCells.add(this.cells.get(x, y));
|
|
427
414
|
return;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.1.1",
|
|
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": {
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
"keywords": [
|
|
13
13
|
"grid",
|
|
14
14
|
"game-dev",
|
|
15
|
-
"pathfinding"
|
|
16
|
-
"cellular-automata"
|
|
15
|
+
"pathfinding"
|
|
17
16
|
],
|
|
18
17
|
"scripts": {
|
|
19
18
|
"build": "npx tsc",
|