@xtia/grid 0.0.4 → 0.0.6
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 +60 -10
- package/lib/grid.d.ts +1 -0
- package/lib/grid.js +4 -1
- package/package.json +2 -1
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";
|
|
25
|
+
import { Grid } from "@xtia/grid"; // ~4.8kb gzipped
|
|
26
26
|
|
|
27
27
|
// initialise a 30x20 Grid<number> of 0's
|
|
28
28
|
const numGrid = Grid.solid(30, 20, 0);
|
|
@@ -46,6 +46,34 @@ const source = imagePipe
|
|
|
46
46
|
const grid = Grid.from(source);
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
### Wrapping existing structures
|
|
50
|
+
|
|
51
|
+
Use Grid's interface over any read/write 2D structure:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const gameMap = [
|
|
55
|
+
[0, 1, -1, 2],
|
|
56
|
+
[1, 0, 1, 0],
|
|
57
|
+
[-1, 1, 0, 2],
|
|
58
|
+
[2, 0, 2, -1]
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
// create a *live view* Grid over gameMap
|
|
62
|
+
const grid = Grid.wrap(
|
|
63
|
+
gameMap[0].length, // width
|
|
64
|
+
gameMap.length, // height
|
|
65
|
+
(x, y) => gameMap[y][x], // get
|
|
66
|
+
(x, y, value) => gameMap[y][x] = value // set
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// reading the grid = reading the source
|
|
70
|
+
gameMap[0][0] = 50;
|
|
71
|
+
console.log(grid.get(0, 0)); // 50
|
|
72
|
+
// writing to the grid = writing to the source
|
|
73
|
+
grid.set(3, 3, 100);
|
|
74
|
+
console.log(gameMap[3][3]); // 100
|
|
75
|
+
```
|
|
76
|
+
|
|
49
77
|
## Regions
|
|
50
78
|
|
|
51
79
|
Use `grid.region(x, y, w, h)` to define a subgrid. The subgrid is **zero-copy view** into the parent; changes to the subgrid affect the parent and vice-versa.
|
|
@@ -74,12 +102,12 @@ const lakeGrid = Grid.from(lakeRegion);
|
|
|
74
102
|
|
|
75
103
|
## Transformation Layers
|
|
76
104
|
|
|
77
|
-
`grid.map(read, write)` creates a **view** that reads and writes the parent through the provided transformation functions.
|
|
105
|
+
`grid.map(read, write)` creates a **zero-copy view** that reads and writes the parent through the provided transformation functions.
|
|
78
106
|
|
|
79
107
|
```ts
|
|
80
108
|
const spriteMap = world.map(
|
|
81
109
|
type => type + ".png",
|
|
82
|
-
sprite => sprite.replace(
|
|
110
|
+
sprite => sprite.replace(/\..*/, '')
|
|
83
111
|
);
|
|
84
112
|
|
|
85
113
|
world.set(0, 0, "mountain"); // modify the parent
|
|
@@ -90,6 +118,20 @@ console.log(world.get(1, 0)); // read the parent: "forest"
|
|
|
90
118
|
|
|
91
119
|
For one-way read-mapping, use `grid.pipe` - a [Pipe2D](https://github.com/tiadrop/pipe2d) view into the grid's data.
|
|
92
120
|
|
|
121
|
+
```ts
|
|
122
|
+
// create a one-way, player-centred sprite map
|
|
123
|
+
const viewport = world.pipe
|
|
124
|
+
.oob("mountain")
|
|
125
|
+
.map(t => t + ".png")
|
|
126
|
+
.crop(playerX - 5, playerY - 5, 10, 10);
|
|
127
|
+
|
|
128
|
+
// or get a list of locations of cells with mountains
|
|
129
|
+
const mountainCells = world.cells.toFlatArrayXY()
|
|
130
|
+
.filter(cell => cell.value === "mountain")
|
|
131
|
+
.map(cell => [cell.x, cell.y]);
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
|
|
93
135
|
## Cell interface
|
|
94
136
|
|
|
95
137
|
`grid.cells` provides a Pipe2D, for convenient transformation, of live-view interfaces relating to positions in the grid.
|
|
@@ -98,12 +140,12 @@ For one-way read-mapping, use `grid.pipe` - a [Pipe2D](https://github.com/tiadro
|
|
|
98
140
|
const topLeft = world.cells.get(0, 0);
|
|
99
141
|
console.log(topLeft.value); // "mountain"
|
|
100
142
|
|
|
101
|
-
topLeft.value = "forest; // modifies the underlying data
|
|
143
|
+
topLeft.value = "forest"; // modifies the underlying data
|
|
102
144
|
console.log(spriteMap.get(0, 0)); // now "forest.png";
|
|
103
145
|
|
|
104
146
|
// navigate by offset
|
|
105
147
|
const adjacentCell = topLeft.look(1, 0);
|
|
106
|
-
console.log(adjacentCell
|
|
148
|
+
console.log(adjacentCell?.x, adjacentCell?.y); // 1, 0
|
|
107
149
|
```
|
|
108
150
|
|
|
109
151
|
Cells provide methods for locational utilities such as pathfinding and visibility mapping.
|
|
@@ -149,9 +191,6 @@ const visibility = start.createVisibilityMap(
|
|
|
149
191
|
// any 2d source, including visibility maps, can be used as a mask for paste/fill operations
|
|
150
192
|
// paste(source: Source2D<T>, mask?: Source2D<boolean>)
|
|
151
193
|
screenGrid.paste(spriteMap, visibility);
|
|
152
|
-
|
|
153
|
-
// using pipe2d's convenience
|
|
154
|
-
const mountainCells = world.cells.toFlatArrayXY().filter(c => c.value === "mountain");
|
|
155
194
|
```
|
|
156
195
|
|
|
157
196
|
### Reusing path data
|
|
@@ -165,7 +204,7 @@ const pathToCentre = pathMap.get(50, 50);
|
|
|
165
204
|
const pathToCorner = pathMap.get(99, 99);
|
|
166
205
|
```
|
|
167
206
|
|
|
168
|
-
Unlike visibility maps, which are lazily evaluated according to the supplied `
|
|
207
|
+
Unlike visibility maps, which are lazily evaluated according to the supplied `isClear` function *when the map is queried* (but can be easily cached with `visMap.withCache()`), path maps use a relatively expensive traversal map that's created *when the map is created*. This distinction is hinted through the `create*` vs `get*` naming.
|
|
169
208
|
|
|
170
209
|
## The storage layer
|
|
171
210
|
|
|
@@ -173,4 +212,15 @@ Unlike visibility maps, which are lazily evaluated according to the supplied `is
|
|
|
173
212
|
|
|
174
213
|
Although the Grid factory methods (`Grid.solid()`, `Grid.from()`, `Grid.init()`) return a `GridBase<T>`, the mental model is that we're simply working with `Grid`s, therefore those factory methods live on `Grid`. The only API distinction is that `GridBase` provides a 'change' event, via `grid.on("change", handler)`.
|
|
175
214
|
|
|
176
|
-
You can perform batched updates, holding off the 'change' event until the batch process concludes, with `grid.batchUpdate(callback)`.
|
|
215
|
+
You can perform batched updates, holding off the 'change' event until the batch process concludes, with `grid.batchUpdate(callback)`.
|
|
216
|
+
|
|
217
|
+
## Save and load
|
|
218
|
+
|
|
219
|
+
Pipe2D makes it easy to save and restore grid data:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
const saved = world.pipe.toFlatArrayXY(); // ["mountain", "forest", "grass", ...]
|
|
223
|
+
|
|
224
|
+
const restoredPipe = Pipe2D.fromFlatArrayXY(saved);
|
|
225
|
+
const restored = Grid.from(restoredPipe);
|
|
226
|
+
```
|
package/lib/grid.d.ts
CHANGED
|
@@ -77,6 +77,7 @@ export declare class Grid<T> {
|
|
|
77
77
|
static init<T>(width: number, height: number, initCell: (x: number, y: number) => T): GridBase<T>;
|
|
78
78
|
static from<T>(source: Source2D<T>): GridBase<T>;
|
|
79
79
|
static solid<T>(width: number, height: number, fillValue: T): GridBase<T>;
|
|
80
|
+
static wrap<T>(width: number, height: number, get: (x: number, y: number) => T, set: (x: number, y: number, value: T) => void, batch?: (callback: () => void) => void): Grid<T>;
|
|
80
81
|
}
|
|
81
82
|
export declare class GridBase<T> extends Grid<T> {
|
|
82
83
|
private data;
|
package/lib/grid.js
CHANGED
|
@@ -132,7 +132,7 @@ export class Cell {
|
|
|
132
132
|
return path;
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
-
return this.gridView.cells.map(
|
|
135
|
+
return this.gridView.cells.map(costs, () => Infinity)
|
|
136
136
|
.strict();
|
|
137
137
|
}
|
|
138
138
|
*getLineTo(target) {
|
|
@@ -314,6 +314,9 @@ export class Grid {
|
|
|
314
314
|
static solid(width, height, fillValue) {
|
|
315
315
|
return new GridBase(Pipe2D.solid(fillValue, width, height));
|
|
316
316
|
}
|
|
317
|
+
static wrap(width, height, get, set, batch = cb => cb()) {
|
|
318
|
+
return new Grid(width, height, get, set, batch);
|
|
319
|
+
}
|
|
317
320
|
}
|
|
318
321
|
export class GridBase extends Grid {
|
|
319
322
|
triggerEvent(name, data) {
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.6",
|
|
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,6 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"./lib/*": null
|
|
11
11
|
},
|
|
12
|
+
"keywords": ["grid", "game-dev", "pathfinding", "cellular-automata"],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "npx tsc",
|
|
14
15
|
"test": "npx vitest run"
|