@xtia/grid 0.1.0 → 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 CHANGED
@@ -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
- (x + y) % 2 === 0 ? 'black' : 'white'
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
- world.set(0, 0, "mountain"); // modify the parent
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(); // ["mountain", "forest", "grass", ...]
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);
@@ -293,7 +296,7 @@ export class Grid {
293
296
  *[Symbol.iterator]() {
294
297
  for (let y = 0; y < this.height; y++) {
295
298
  for (let x = 0; x < this.width; x++) {
296
- yield { x, y, value: this.get(x, y) };
299
+ yield this.get(x, y);
297
300
  }
298
301
  }
299
302
  }
@@ -304,22 +307,11 @@ export class Grid {
304
307
  }
305
308
  }
306
309
  }
307
- combine(aux, cb) {
308
- const width = Math.min(this.width, aux.width);
309
- const height = Math.min(this.height, aux.height);
310
- return new GridBase({
311
- width,
312
- height,
313
- get: (x, y) => {
314
- return cb(this.get(x, y), aux.get(x, y));
315
- }
316
- });
317
- }
318
310
  map(read, write) {
319
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));
320
312
  }
321
313
  region(x, y, width, height) {
322
- if (!Number.isInteger(x) || !Number.isInteger(y) || !Number.isInteger(width) || !Number.isInteger(height)) {
314
+ if (!Number.isInteger(x) || !Number.isInteger(y)) {
323
315
  throw new Error(`Region boundaries must be integer; got (${x}, ${y}), (${width} x ${height})`);
324
316
  }
325
317
  if (x < 0 || y < 0 || x + width > this.width || y + height > this.height) {
@@ -387,11 +379,12 @@ export class GridBase extends Grid {
387
379
  if (this.batchState.level == 0) {
388
380
  const changed = this.batchState.changedCells;
389
381
  this.batchState = null;
390
- this.triggerChange(changed);
382
+ if (changed.size > 0)
383
+ this.triggerChange(changed);
391
384
  }
392
385
  }
393
386
  constructor(source) {
394
- super(source.width, source.height, (x, y) => this.data[this.xyToIndex(x, y)], (x, y, value) => this._set(x, y, value), fn => this.batchUpdate(fn));
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));
395
388
  this.eventHandlers = {};
396
389
  this.batchState = null;
397
390
  const sourcePipe = source instanceof Pipe2D
@@ -411,20 +404,11 @@ export class GridBase extends Grid {
411
404
  this.eventHandlers[eventName].splice(idx, 1);
412
405
  };
413
406
  }
414
- xyToIndex(x, y) {
415
- if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
416
- throw new Error(`Coordinates out of bounds: (${x}, ${y})`);
417
- }
418
- if (!Number.isInteger(x) || !Number.isInteger(y)) {
419
- throw new Error(`Coordinates must be integer; got (${x}, ${y})`);
420
- }
421
- return y * this.width + x;
422
- }
423
407
  _set(x, y, value) {
424
- const idx = this.xyToIndex(x, y);
408
+ const idx = y * this.width + x;
425
409
  if (this.data[idx] === value)
426
410
  return;
427
- this.data[this.xyToIndex(x, y)] = value;
411
+ this.data[idx] = value;
428
412
  if (this.batchState) {
429
413
  this.batchState.changedCells.add(this.cells.get(x, y));
430
414
  return;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.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": {