@canvasengine/tiled 2.0.0-beta.25

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.
Files changed (54) hide show
  1. package/dist/classes/Gid.d.ts +13 -0
  2. package/dist/classes/Layer.d.ts +26 -0
  3. package/dist/classes/Map.d.ts +232 -0
  4. package/dist/classes/Object.d.ts +8 -0
  5. package/dist/classes/Properties.d.ts +11 -0
  6. package/dist/classes/Tile.d.ts +19 -0
  7. package/dist/classes/Tileset.d.ts +13 -0
  8. package/dist/generate/tileset.d.ts +11 -0
  9. package/dist/generate/wangtile.d.ts +21 -0
  10. package/dist/index.d.ts +16 -0
  11. package/dist/index.js +6205 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/parser/open-file.d.ts +24 -0
  14. package/dist/parser/parser.d.ts +27 -0
  15. package/dist/types/Layer.d.ts +116 -0
  16. package/dist/types/Map.d.ts +72 -0
  17. package/dist/types/Objects.d.ts +57 -0
  18. package/dist/types/Text.d.ts +47 -0
  19. package/dist/types/Tile.d.ts +17 -0
  20. package/dist/types/Tileset.d.ts +92 -0
  21. package/dist/types/Types.d.ts +147 -0
  22. package/dist/types/WorldMaps.d.ts +12 -0
  23. package/dist/utils.d.ts +10 -0
  24. package/package.json +31 -0
  25. package/readme.md +1 -0
  26. package/src/classes/Gid.ts +46 -0
  27. package/src/classes/Layer.ts +135 -0
  28. package/src/classes/Map.ts +443 -0
  29. package/src/classes/Object.ts +16 -0
  30. package/src/classes/Properties.ts +30 -0
  31. package/src/classes/Tile.ts +22 -0
  32. package/src/classes/Tileset.ts +34 -0
  33. package/src/generate/tileset.ts +35 -0
  34. package/src/generate/wangtile.ts +166 -0
  35. package/src/index.ts +16 -0
  36. package/src/parser/open-file.ts +155 -0
  37. package/src/parser/parser.ts +309 -0
  38. package/src/types/Layer.ts +127 -0
  39. package/src/types/Map.ts +83 -0
  40. package/src/types/Objects.ts +64 -0
  41. package/src/types/Text.ts +47 -0
  42. package/src/types/Tile.ts +19 -0
  43. package/src/types/Tileset.ts +99 -0
  44. package/src/types/Types.ts +157 -0
  45. package/src/types/WorldMaps.ts +13 -0
  46. package/src/utils.ts +22 -0
  47. package/tests/class.spec.ts +88 -0
  48. package/tests/data.ts +5440 -0
  49. package/tests/parser.spec.ts +112 -0
  50. package/tests/tile-properties.spec.ts +99 -0
  51. package/tests/tiledmap-multi-layers.spec.ts +99 -0
  52. package/tests/tiledmap.spec.ts +223 -0
  53. package/tsconfig.json +28 -0
  54. package/vite.config.ts +21 -0
@@ -0,0 +1,46 @@
1
+ import { TiledProperties } from "./Properties"
2
+
3
+ const FLIPPED_HORIZONTALLY_FLAG = 0x80000000
4
+ const FLIPPED_VERTICALLY_FLAG = 0x40000000
5
+ const FLIPPED_DIAGONALLY_FLAG = 0x20000000
6
+ const ROTATED_HEXAGONAL_120_FLAG = 0x10000000
7
+
8
+ export class TileGid extends TiledProperties {
9
+ private _gid: number
10
+
11
+ constructor(public obj?) {
12
+ super(obj)
13
+ this._gid = obj?.gid
14
+ }
15
+
16
+ static getRealGid(gid: number): number {
17
+ return gid & ~(FLIPPED_HORIZONTALLY_FLAG |
18
+ FLIPPED_VERTICALLY_FLAG |
19
+ FLIPPED_DIAGONALLY_FLAG |
20
+ ROTATED_HEXAGONAL_120_FLAG)
21
+ }
22
+
23
+ get horizontalFlip(): boolean {
24
+ return !!(this._gid & FLIPPED_HORIZONTALLY_FLAG)
25
+ }
26
+
27
+ get verticalFlip(): boolean {
28
+ return !!(this._gid & FLIPPED_VERTICALLY_FLAG)
29
+ }
30
+
31
+ get diagonalFlip(): boolean {
32
+ return !!(this._gid & FLIPPED_DIAGONALLY_FLAG)
33
+ }
34
+
35
+ get rotatedHex120(): boolean {
36
+ return !!(this._gid & ROTATED_HEXAGONAL_120_FLAG)
37
+ }
38
+
39
+ get gid(): number {
40
+ return TileGid.getRealGid(this._gid)
41
+ }
42
+
43
+ set gid(val: number) {
44
+ this._gid = val
45
+ }
46
+ }
@@ -0,0 +1,135 @@
1
+ import { TiledLayer } from "../types/Layer";
2
+ import { TileGid } from "./Gid";
3
+ import { TiledObjectClass } from "./Object";
4
+ import { TiledProperties } from "./Properties";
5
+ import { Tile } from "./Tile";
6
+ import { Tileset } from "./Tileset";
7
+
8
+ export class Layer extends TiledProperties {
9
+ cacheTiles: boolean = false
10
+ tiles: (Tile | undefined)[] = []
11
+ objects: TiledObjectClass[]
12
+
13
+ get size(): number {
14
+ return this.data.length
15
+ }
16
+
17
+ constructor(layer: TiledLayer, private tilesets: Tileset[], private parent?: Layer) {
18
+ super(layer)
19
+ Object.assign(this, layer)
20
+ this.mapObjects()
21
+ this.mergePropertiesWithParent()
22
+ // Caching tiles saves CPU but consumes RAM for large maps
23
+ this.cacheTiles = this.getProperty<boolean, boolean>('cache-tiles', false)
24
+ if (this.cacheTiles) this.propertiesTiles()
25
+ }
26
+
27
+ createTile(gid: number, tileIndex: number, layerIndex?: number): Tile | undefined {
28
+ if (gid == 0) {
29
+ return
30
+ }
31
+ const realGid = TileGid.getRealGid(gid)
32
+ const tileset = Layer.findTileSet(realGid, this.tilesets)
33
+ if (!tileset) {
34
+ return undefined
35
+ }
36
+ const tile = tileset.getTile(realGid - tileset.firstgid)
37
+ if (tile) {
38
+ return new Tile({
39
+ ...tile.tile,
40
+ gid,
41
+ index: tileIndex,
42
+ layerIndex
43
+ })
44
+ }
45
+ return new Tile({
46
+ gid,
47
+ index: tileIndex,
48
+ layerIndex
49
+ })
50
+ }
51
+
52
+ private mergePropertiesWithParent() {
53
+ const parent = this.getLayerParent()
54
+ if (!this.properties) this.properties = {}
55
+ if (!parent) return
56
+ for (let key in parent.properties) {
57
+ const val = parent.properties[key]
58
+ const valChild = this.properties[key]
59
+ if (valChild === undefined) {
60
+ this.properties[key] = val
61
+ }
62
+ else {
63
+ if (key == 'z') {
64
+ this.properties[key] += val
65
+ }
66
+ else {
67
+ continue
68
+ }
69
+ }
70
+ }
71
+ this.opacity = Math.round((parent.opacity ?? 1) * (this.opacity ?? 1) * 100) / 100
72
+ this.offsetx = (parent.offsetx ?? 0) + (this.offsetx ?? 0)
73
+ this.offsety = (parent.offsety ?? 0) + (this.offsety ?? 0)
74
+ this.locked = parent.locked ?? false
75
+ }
76
+
77
+ private propertiesTiles() {
78
+ if (!this.data) return
79
+ const data = this.data as number[]
80
+ for (let i = 0; i < data.length; i++) {
81
+ const id = data[i]
82
+ this.tiles.push(this.createTile(id, i))
83
+ }
84
+ }
85
+
86
+ private mapObjects() {
87
+ if (this.objects) {
88
+ this.objects = this.objects.map(object => {
89
+ const obj = new TiledObjectClass(object)
90
+ obj.layerName = this.name
91
+ return obj
92
+ })
93
+ }
94
+ }
95
+
96
+ getTileByIndex(tileIndex: number): Tile | undefined {
97
+ if (this.cacheTiles) {
98
+ return this.tiles[tileIndex]
99
+ }
100
+ return this.createTile(this.data[tileIndex] as number, tileIndex)
101
+ }
102
+
103
+ static findTileSet(gid: number, tileSets: Tileset[]): Tileset | undefined {
104
+ let tileset: Tileset | undefined
105
+ for (let i = tileSets.length - 1; i >= 0; i--) {
106
+ tileset = tileSets[i]
107
+ if (tileset.firstgid && tileset.firstgid <= gid) {
108
+ break;
109
+ }
110
+ }
111
+ return tileset;
112
+ }
113
+
114
+ getLayerParent(): Layer | undefined {
115
+ return this.parent
116
+ }
117
+
118
+ tilesForEach(cb: (tile: Tile | undefined, index: number) => void) {
119
+ for (let i = 0; i < this.data.length; i++) {
120
+ if (this.cacheTiles) {
121
+ cb(this.tiles[i], i)
122
+ continue
123
+ }
124
+ cb(this.createTile(this.data[i] as number, i) as Tile, i)
125
+ }
126
+ }
127
+
128
+ setData(tileIndex: number, gid: number): void {
129
+ (this.data as number[])[tileIndex] = gid
130
+ }
131
+ }
132
+
133
+ export interface Layer extends TiledLayer {
134
+ objects: TiledObjectClass[]
135
+ }
@@ -0,0 +1,443 @@
1
+ import { TiledLayer, TiledLayerType } from "../types/Layer";
2
+ import { TiledMap } from "../types/Map";
3
+ import { TiledTileset } from "../types/Tileset";
4
+ import { Layer } from "./Layer";
5
+ import { TiledObjectClass } from "./Object";
6
+ import { TiledProperties } from "./Properties";
7
+ import { Tile } from "./Tile";
8
+ import { Tileset } from "./Tileset";
9
+
10
+ export interface TileInfo {
11
+ tiles: Tile[]
12
+ hasCollision: boolean | undefined
13
+ isClimbable?: boolean | undefined
14
+ isOverlay: boolean | undefined
15
+ objectGroups: TiledObjectClass[],
16
+ tileIndex: number
17
+ }
18
+
19
+ export interface GetTileOptions {
20
+ populateTiles?: boolean
21
+ }
22
+
23
+ // Allows you to cache tilesets. Avoid rebuilding for other maps
24
+ export let bufferTilesets = {}
25
+
26
+ export class MapClass extends TiledProperties {
27
+ /**
28
+ * @title Data of map
29
+ * @prop {object} [data]
30
+ * @readonly
31
+ * @memberof Map
32
+ * @memberof RpgSceneMap
33
+ * */
34
+ data: TiledMap
35
+
36
+ tilesets: Tileset[] = []
37
+ layers: Layer[] = []
38
+
39
+ private tmpLayers: Layer[] = []
40
+ private tilesIndex: {
41
+ [zIndex: number]: Uint16Array
42
+ } = {}
43
+
44
+ /**
45
+ * Allows to define the size of ArrayBuffer to keep in memory the tiles of the map
46
+ */
47
+ private allocateMemory: number = 0
48
+
49
+ /**
50
+ * If set to true, the memory allocation will take only one tile (the tile of the last layer)
51
+ */
52
+ private lowMemory: boolean = false
53
+
54
+ constructor(map?: TiledMap) {
55
+ super(map ?? {})
56
+ if (map) this.load(map)
57
+ }
58
+
59
+ load(map: TiledMap) {
60
+ Object.assign(this, map)
61
+ if (this.hasProperty('low-memory')) {
62
+ this.lowMemory = this.getProperty<boolean, boolean>('low-memory', false)
63
+ }
64
+ this.tmpLayers = []
65
+ this.mapTilesets()
66
+ this.mapLayers(this.layers)
67
+ this.layers = [...this.tmpLayers]
68
+ Reflect.deleteProperty(this, 'tmpLayers')
69
+ this.setTilesIndex()
70
+ this.data = map
71
+ }
72
+
73
+ /**
74
+ * @title Width of the map in pixels
75
+ * @prop {number} [widthPx]
76
+ * @readonly
77
+ * @memberof Map
78
+ * @memberof RpgSceneMap
79
+ * */
80
+
81
+ get widthPx(): number {
82
+ return this.width * this.tilewidth
83
+ }
84
+
85
+ /**
86
+ * @title Height of the map in pixels
87
+ * @prop {number} [heightPx]
88
+ * @readonly
89
+ * @memberof Map
90
+ * @memberof RpgSceneMap
91
+ * */
92
+ get heightPx(): number {
93
+ return this.height * this.tileheight
94
+ }
95
+
96
+ /**
97
+ * @title The depth of the map in pixels (this is the height of a tile ;))
98
+ * @prop {number} map.zTileHeight
99
+ * @readonly
100
+ * @memberof Map
101
+ * @memberof RpgSceneMap
102
+ * */
103
+ get zTileHeight(): number {
104
+ return this.tileheight
105
+ }
106
+
107
+ /**
108
+ * Find a layer by name. Returns `undefined` is the layer is not found
109
+
110
+ * @title Get Layer by name
111
+ * @method map.getLayerByName(name)
112
+ * @param {string} name layer name
113
+ * @returns {LayerInfo | undefined}
114
+ * @example
115
+ * ```ts
116
+ * const tiles = map.getLayerByName(0, 0)
117
+ * ```
118
+ * @memberof Map
119
+ * @memberof RpgSceneMap
120
+ */
121
+ getLayerByName(name: string): TiledLayer | undefined {
122
+ return this.layers.find(layer => layer.name == name)
123
+ }
124
+
125
+ /**
126
+ * Get the tile index on the tileset
127
+ *
128
+ * @title Get index of tile
129
+ * @method map.getTileIndex(x,y)
130
+ * @param {number} x Position X
131
+ * @param {number} x Position Y
132
+ * @returns {number}
133
+ * @memberof Map
134
+ * @memberof RpgSceneMap
135
+ */
136
+ getTileIndex(x: number, y: number, [z] = [0]): number {
137
+ return this.width * Math.floor((y - z) / this.tileheight) + Math.floor(x / this.tilewidth)
138
+ }
139
+
140
+ getTilePosition(index: number): { x: number, y: number } {
141
+ return {
142
+ y: Math.floor(index / this.width) * this.tileheight,
143
+ x: index % (this.width) * this.tilewidth
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Find the point of origin (top left) of a tile. Of course, its position depends on the size of the tile
149
+
150
+ * @title Get origin position of tile
151
+ * @method map.getTileOriginPosition(x,y)
152
+ * @param {number} x Position X
153
+ * @param {number} x Position Y
154
+ * @returns { {x: number, y: number }}
155
+ * @example
156
+ * ```ts
157
+ * // If the size of a tile is 32x32px
158
+ * const position = map.getTileOriginPosition(35, 12)
159
+ * console.log(position) // { x: 32, y: 0 }
160
+ * ```
161
+ * @memberof Map
162
+ * @memberof RpgSceneMap
163
+ */
164
+
165
+ getTileOriginPosition(x: number, y: number): {
166
+ x: number
167
+ y: number
168
+ } {
169
+ return {
170
+ x: Math.floor(x / this.tilewidth) * this.tilewidth,
171
+ y: Math.floor(y / this.tileheight) * this.tileheight
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Recover tiles according to a position
177
+
178
+ * @title Get tile by position
179
+ * @method map.getTileByPosition(x,y)
180
+ * @param {number} x Position X
181
+ * @param {number} x Position Y
182
+ * @returns {TileInfo}
183
+ * @example
184
+ * ```ts
185
+ * const tiles = map.getTileByPosition(0, 0)
186
+ * ```
187
+ * @memberof Map
188
+ * @memberof RpgSceneMap
189
+ */
190
+ getTileByPosition(x: number, y: number, z: [number, number] = [0, 0], options: GetTileOptions = {}): TileInfo {
191
+ const tileIndex = this.getTileIndex(x, y, [z[0]])
192
+ return this.getTileByIndex(tileIndex, z, options)
193
+ }
194
+
195
+ /**
196
+ * Retrieves tiles according to its index
197
+
198
+ * @title Get tile by index
199
+ * @method map.getTileByIndex(tileIndex)
200
+ * @param {number} tileIndex tile index
201
+ * @returns {TileInfo}
202
+ * @example
203
+ * ```ts
204
+ * const index = map.getTileIndex(0, 0)
205
+ * const tiles = map.getTileByIndex(index)
206
+ * ```
207
+ * @memberof Map
208
+ * @memberof RpgSceneMap
209
+ */
210
+
211
+ getTileByIndex(
212
+ tileIndex: number,
213
+ zPlayer: [number, number] = [0, 0],
214
+ options: GetTileOptions = {
215
+ populateTiles: true
216
+ }
217
+ ): TileInfo {
218
+ const zA = Math.floor(zPlayer[0] / this.zTileHeight)
219
+ const zB = Math.floor(zPlayer[1] / this.zTileHeight)
220
+ const level = this.tilesIndex[zA]
221
+ const obj: TileInfo = {
222
+ tiles: [],
223
+ hasCollision: false,
224
+ isOverlay: false,
225
+ objectGroups: [],
226
+ tileIndex
227
+ }
228
+ if (!level) {
229
+ return obj
230
+ }
231
+ const [layer] = this.layers
232
+ const getTileByPointer = (pointer = 0) => {
233
+ const pos = tileIndex * this.realAllocateMemory + pointer
234
+ const gid = level[pos]
235
+ if (gid === 0) {
236
+ return obj
237
+ }
238
+ const tile = layer.createTile(gid, tileIndex, level[pos+1])
239
+ if (tile) obj.tiles.push(tile)
240
+ }
241
+ if (options.populateTiles) {
242
+ for (let i=0 ; i < this.realAllocateMemory ; i += 2) {
243
+ getTileByPointer(i)
244
+ }
245
+ }
246
+ else {
247
+ getTileByPointer()
248
+ }
249
+ const [tile] = obj.tiles
250
+ if (tile) {
251
+ obj.hasCollision = tile.getProperty<boolean, boolean>('collision', false)
252
+ obj.objectGroups = tile.objects as TiledObjectClass[] ?? []
253
+ }
254
+ return obj
255
+ }
256
+
257
+ getAllObjects(): TiledObjectClass[] {
258
+ return this.layers.reduce((prev: TiledObjectClass[], current: Layer) => {
259
+ if (!current.objects) return prev
260
+ return prev.concat(...current.objects)
261
+ }, [])
262
+ }
263
+
264
+ getData() {
265
+ return {
266
+ ...this.data,
267
+ layers: this.layers
268
+ }
269
+ }
270
+
271
+ setTile(x: number, y: number, layerFilter: string | ((layer: any) => boolean), tileInfo: any): {
272
+ x: number,
273
+ y: number,
274
+ tiles: {
275
+ [tileIndex: number]: Tile
276
+ }
277
+ } | never {
278
+ if (this.lowMemory) {
279
+ throw 'Impossible to change a tile with the lowMemory option'
280
+ }
281
+ const tileIndex = this.getTileIndex(x, y)
282
+ let fnFilter
283
+ let tilesEdited = {}
284
+ if (typeof layerFilter == 'string') {
285
+ fnFilter = (layer) => layer.name == layerFilter
286
+ }
287
+ else {
288
+ fnFilter = layerFilter
289
+ }
290
+ for (let i=0 ; i < this.layers.length ; i++) {
291
+ const layer = this.layers[i]
292
+ if (!fnFilter(layer)) continue
293
+ let tile: Tile | undefined
294
+ const oldTile = this.getTileByIndex(tileIndex)
295
+ if (tileInfo.gid) {
296
+ tile = layer.createTile(tileInfo.gid, tileIndex)
297
+ }
298
+ if (!tile) continue
299
+ for (let key in tileInfo) {
300
+ if (key == 'gid') continue
301
+ tile[key] = tileInfo[key]
302
+ }
303
+ tilesEdited[layer.name] = {
304
+ gid: tile.gid,
305
+ properties: tile.properties
306
+ }
307
+ this.setTileIndex(layer, oldTile.tiles[0], tile, tileIndex, i)
308
+ layer.setData(tileIndex, tile.gid)
309
+ }
310
+ return {
311
+ x,
312
+ y,
313
+ tiles: tilesEdited
314
+ }
315
+ }
316
+
317
+ removeCacheTileset(name: string) {
318
+ delete bufferTilesets[name]
319
+ }
320
+
321
+ clearCacheTilesets() {
322
+ bufferTilesets = {}
323
+ }
324
+
325
+ private mapTilesets() {
326
+ this.tilesets = this.tilesets.map(tileset => {
327
+ if (bufferTilesets[tileset.name]) {
328
+ const instance = bufferTilesets[tileset.name]
329
+ instance.firstgid = tileset.firstgid
330
+ return instance
331
+ }
332
+ const _tileset = new Tileset(tileset)
333
+ bufferTilesets[_tileset.name] = _tileset
334
+ return _tileset
335
+ })
336
+ }
337
+
338
+ private mapLayers(layers: TiledLayer[] = [], parent?: Layer) {
339
+ for (let layer of layers) {
340
+ const layerInstance = new Layer(layer, this.tilesets, parent)
341
+ this.tmpLayers.push(layerInstance)
342
+ if (layer.layers) {
343
+ this.mapLayers(layer.layers, layerInstance)
344
+ }
345
+ }
346
+ if (this.lowMemory) this.allocateMemory = 1
347
+ if (!this.allocateMemory) this.allocateMemory = this.layers.length
348
+ }
349
+
350
+ private setTileIndex(layer: Layer, oldTile: Tile, newTile: Tile, tileIndex: number, layerIndex: number) {
351
+ const startPos = tileIndex * this.realAllocateMemory
352
+ let pointer = startPos + this.realAllocateMemory - 2
353
+ const zLayer = layer.getProperty<number, number>('z', 0)
354
+ const zTile = oldTile.getProperty<number, number>('z', 0)
355
+ let z = zLayer + zTile
356
+ while (pointer >= startPos) {
357
+ const zlayer = this.tilesIndex[z]
358
+ if (zlayer[pointer] === oldTile.gid && zlayer[pointer+1] === layerIndex) {
359
+ this.tilesIndex[z][pointer] = newTile.gid
360
+ }
361
+ pointer -= 2
362
+ }
363
+ }
364
+
365
+ /**
366
+ * We multiply by 2 because 2 entries are stored for a tile: its GID and the Layer Index
367
+ *
368
+ * Example If I have 3 layers, The array will have the following form
369
+ *
370
+ * [
371
+ * GID of Layer 3,
372
+ * Layer Index of Layer 3,
373
+ * GID of Layer 2,
374
+ * Layer Index of Layer 2,
375
+ * GID of Layer 1,
376
+ * Layer Index of Layer 1,
377
+ * ... others tiles
378
+ * ]
379
+ *
380
+ * The size in memory of the map is therefore:
381
+ *
382
+ * `(map width * map height * number of layers * 4) bytes`
383
+ *
384
+ * > We multiply by 4, because an element takes 2 bytes and has 2 elements for a tile is 4 bytes in all
385
+ *
386
+ * Example (a 100x100 map with 5 layers)
387
+ *
388
+ * `100 * 100 * 5 * 4 = 200000 bytes = ~195 Kb`
389
+ *
390
+ * If we define on lowMemory then the calculation is the following
391
+ *
392
+ * `(map width * map height * 4) bytes`
393
+ *
394
+ * Example
395
+ *
396
+ * `100 * 100 * 4 = 40000 bytes = ~39 Kb`
397
+ */
398
+ private get realAllocateMemory() {
399
+ return this.allocateMemory * 2
400
+ }
401
+
402
+ /**
403
+ * We keep each tile in memory classified by z value. The values are ordered from the end to the beginning so that the first element of the array (when retrieved with getTileByIndex() is the tile on the highest layer. This way, the tile search is very fast for collisions
404
+ *
405
+ */
406
+ private addTileIndex(layer: Layer, tile: Tile | undefined, tileIndex: number, layerIndex: number) {
407
+ if ((!tile) || (tile && tile.gid == 0)) {
408
+ return
409
+ }
410
+ const zLayer = layer.getProperty<number, number>('z', 0)
411
+ const zTile = tile.getProperty<number, number>('z', 0)
412
+ let z = zLayer + zTile
413
+ if (!this.tilesIndex[z]) {
414
+ const buffer = new ArrayBuffer(layer.size * this.realAllocateMemory * 2)
415
+ this.tilesIndex[z] = new Uint16Array(buffer)
416
+ }
417
+ const startPos = tileIndex * this.realAllocateMemory
418
+ let pointer = startPos + this.realAllocateMemory - 2
419
+
420
+ while (this.tilesIndex[z][pointer] !== 0 && pointer > startPos) {
421
+ pointer -= 2
422
+ }
423
+
424
+ this.tilesIndex[z][pointer] = tile.gid
425
+ this.tilesIndex[z][pointer+1] = layerIndex
426
+ this.tilesIndex[z][startPos] = tile.gid
427
+ this.tilesIndex[z][startPos+1] = layerIndex
428
+ }
429
+
430
+ private setTilesIndex() {
431
+ for (let i=0 ; i < this.layers.length ; i++) {
432
+ const layer = this.layers[i]
433
+ if (layer.type != TiledLayerType.Tile) {
434
+ continue
435
+ }
436
+ layer.tilesForEach((tile, index) => {
437
+ this.addTileIndex(layer, tile, index, i)
438
+ })
439
+ }
440
+ }
441
+ }
442
+
443
+ export interface MapClass extends TiledMap { }
@@ -0,0 +1,16 @@
1
+ import { TiledObject } from "../types/Objects";
2
+ import { TileGid } from "./Gid";
3
+
4
+ export class TiledObjectClass extends TileGid {
5
+ layerName?: string = ''
6
+
7
+ constructor(object?: TiledObject) {
8
+ super(object)
9
+ Object.assign(this, object)
10
+ if (object?.gid) {
11
+ this.y -= this.height
12
+ }
13
+ }
14
+ }
15
+
16
+ export interface TiledObjectClass extends TiledObject {}
@@ -0,0 +1,30 @@
1
+ export class TiledProperties {
2
+ properties: {
3
+ [key: string]: any
4
+ } = {}
5
+ class: string
6
+
7
+ constructor(data?: any) {
8
+ this.properties = data?.properties ?? {}
9
+ }
10
+
11
+ getProperty<P, D = undefined>(name: string, defaultValue?: D): P | D {
12
+ const val = this.properties[name]
13
+ if (val === undefined) {
14
+ return defaultValue as D
15
+ }
16
+ return val as any
17
+ }
18
+
19
+ hasProperty(name: string): boolean {
20
+ return !!this.properties[name]
21
+ }
22
+
23
+ setProperty<T>(name: string, value: T) {
24
+ this.properties[name] = value
25
+ }
26
+
27
+ getType(): string {
28
+ return this.class || this['type']
29
+ }
30
+ }
@@ -0,0 +1,22 @@
1
+ import { TilesetTile } from "../types/Tile";
2
+ import { TileGid } from "./Gid";
3
+
4
+ type TileInfo = TilesetTile & { gid?: number, index: number, layerIndex?: number }
5
+
6
+ export class Tile extends TileGid {
7
+ index: number
8
+
9
+ constructor(public tile: TileInfo | { gid: number }) {
10
+ super(tile)
11
+ // Store the properties before Object.assign to avoid overwriting them
12
+ const preservedProperties = this.properties
13
+ Reflect.deleteProperty(tile, 'gid')
14
+ Object.assign(this, tile)
15
+ // Restore properties if they were overwritten by Object.assign
16
+ if (preservedProperties && Object.keys(preservedProperties).length > 0) {
17
+ this.properties = { ...preservedProperties, ...this.properties }
18
+ }
19
+ }
20
+ }
21
+
22
+ export interface Tile extends TileInfo {}