@rpgjs/tiledmap 5.0.0-alpha.40 → 5.0.0-alpha.41
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/dist/client/index2.js +16 -1
- package/dist/client/index3.js +581 -1
- package/dist/client/index5.js +95 -0
- package/dist/physics.d.ts +17 -0
- package/dist/server/index2.js +17 -138
- package/dist/server/index4.js +117 -0
- package/dist/server.d.ts +0 -53
- package/package.json +5 -5
- package/src/client.ts +23 -3
- package/src/physics.ts +143 -0
- package/src/server.ts +22 -266
package/dist/client/index2.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { defineModule } from "@rpgjs/common";
|
|
2
|
+
import { resetTiledCollisionHandlers, detachTiledCollisionFromEntity, attachTiledCollisionToEntity, prepareTiledPhysicsData } from "./index5.js";
|
|
2
3
|
const client = defineModule({
|
|
3
|
-
componentAnimations: []
|
|
4
|
+
componentAnimations: [],
|
|
5
|
+
sceneMap: {
|
|
6
|
+
onPhysicsInit(map, context) {
|
|
7
|
+
prepareTiledPhysicsData(context?.mapData, map);
|
|
8
|
+
},
|
|
9
|
+
onPhysicsEntityAdd(map, context) {
|
|
10
|
+
attachTiledCollisionToEntity(context?.owner, map);
|
|
11
|
+
},
|
|
12
|
+
onPhysicsEntityRemove(map, context) {
|
|
13
|
+
detachTiledCollisionFromEntity(context?.owner, map);
|
|
14
|
+
},
|
|
15
|
+
onPhysicsReset(map) {
|
|
16
|
+
resetTiledCollisionHandlers(map);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
4
19
|
});
|
|
5
20
|
export {
|
|
6
21
|
client as default
|
package/dist/client/index3.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var TiledLayerType = /* @__PURE__ */ ((TiledLayerType2) => {
|
|
2
|
+
TiledLayerType2["Tile"] = "tilelayer";
|
|
3
|
+
TiledLayerType2["ObjectGroup"] = "objectgroup";
|
|
4
|
+
TiledLayerType2["Image"] = "imagelayer";
|
|
5
|
+
TiledLayerType2["Group"] = "group";
|
|
6
|
+
return TiledLayerType2;
|
|
7
|
+
})(TiledLayerType || {});
|
|
1
8
|
function joinPath(...segments) {
|
|
2
9
|
return segments.filter((segment) => segment && segment.length > 0).join("/").replace(/\/+/g, "/");
|
|
3
10
|
}
|
|
@@ -4636,6 +4643,579 @@ _TiledParser.propToBool = (obj, props) => {
|
|
|
4636
4643
|
return obj;
|
|
4637
4644
|
};
|
|
4638
4645
|
let TiledParser = _TiledParser;
|
|
4646
|
+
class TiledProperties {
|
|
4647
|
+
constructor(data) {
|
|
4648
|
+
this.properties = {};
|
|
4649
|
+
this.properties = data?.properties ?? {};
|
|
4650
|
+
}
|
|
4651
|
+
getProperty(name, defaultValue) {
|
|
4652
|
+
const val = this.properties[name];
|
|
4653
|
+
if (val === void 0) {
|
|
4654
|
+
return defaultValue;
|
|
4655
|
+
}
|
|
4656
|
+
return val;
|
|
4657
|
+
}
|
|
4658
|
+
hasProperty(name) {
|
|
4659
|
+
return !!this.properties[name];
|
|
4660
|
+
}
|
|
4661
|
+
setProperty(name, value) {
|
|
4662
|
+
this.properties[name] = value;
|
|
4663
|
+
}
|
|
4664
|
+
getType() {
|
|
4665
|
+
return this.class || this["type"];
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
const FLIPPED_HORIZONTALLY_FLAG = 2147483648;
|
|
4669
|
+
const FLIPPED_VERTICALLY_FLAG = 1073741824;
|
|
4670
|
+
const FLIPPED_DIAGONALLY_FLAG = 536870912;
|
|
4671
|
+
const ROTATED_HEXAGONAL_120_FLAG = 268435456;
|
|
4672
|
+
class TileGid extends TiledProperties {
|
|
4673
|
+
constructor(obj) {
|
|
4674
|
+
super(obj);
|
|
4675
|
+
this.obj = obj;
|
|
4676
|
+
this._gid = obj?.gid;
|
|
4677
|
+
}
|
|
4678
|
+
static getRealGid(gid) {
|
|
4679
|
+
return gid & 268435455;
|
|
4680
|
+
}
|
|
4681
|
+
get horizontalFlip() {
|
|
4682
|
+
return !!(this._gid & FLIPPED_HORIZONTALLY_FLAG);
|
|
4683
|
+
}
|
|
4684
|
+
get verticalFlip() {
|
|
4685
|
+
return !!(this._gid & FLIPPED_VERTICALLY_FLAG);
|
|
4686
|
+
}
|
|
4687
|
+
get diagonalFlip() {
|
|
4688
|
+
return !!(this._gid & FLIPPED_DIAGONALLY_FLAG);
|
|
4689
|
+
}
|
|
4690
|
+
get rotatedHex120() {
|
|
4691
|
+
return !!(this._gid & ROTATED_HEXAGONAL_120_FLAG);
|
|
4692
|
+
}
|
|
4693
|
+
get gid() {
|
|
4694
|
+
return TileGid.getRealGid(this._gid);
|
|
4695
|
+
}
|
|
4696
|
+
set gid(val) {
|
|
4697
|
+
this._gid = val;
|
|
4698
|
+
}
|
|
4699
|
+
}
|
|
4700
|
+
class Tile extends TileGid {
|
|
4701
|
+
constructor(tile) {
|
|
4702
|
+
super(tile);
|
|
4703
|
+
this.tile = tile;
|
|
4704
|
+
const preservedProperties = this.properties;
|
|
4705
|
+
Reflect.deleteProperty(tile, "gid");
|
|
4706
|
+
Object.assign(this, tile);
|
|
4707
|
+
if (preservedProperties && Object.keys(preservedProperties).length > 0) {
|
|
4708
|
+
this.properties = { ...preservedProperties, ...this.properties };
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
class TiledObjectClass extends TileGid {
|
|
4713
|
+
constructor(object) {
|
|
4714
|
+
super(object);
|
|
4715
|
+
this.layerName = "";
|
|
4716
|
+
Object.assign(this, object);
|
|
4717
|
+
if (object?.gid) {
|
|
4718
|
+
this.y -= this.height;
|
|
4719
|
+
}
|
|
4720
|
+
}
|
|
4721
|
+
}
|
|
4722
|
+
class Layer extends TiledProperties {
|
|
4723
|
+
constructor(layer, tilesets, parent) {
|
|
4724
|
+
super(layer);
|
|
4725
|
+
this.tilesets = tilesets;
|
|
4726
|
+
this.parent = parent;
|
|
4727
|
+
this.cacheTiles = false;
|
|
4728
|
+
this.tiles = [];
|
|
4729
|
+
Object.assign(this, layer);
|
|
4730
|
+
this.mapObjects();
|
|
4731
|
+
this.mergePropertiesWithParent();
|
|
4732
|
+
this.cacheTiles = this.getProperty("cache-tiles", false);
|
|
4733
|
+
if (this.cacheTiles) this.propertiesTiles();
|
|
4734
|
+
}
|
|
4735
|
+
get size() {
|
|
4736
|
+
return this.data.length;
|
|
4737
|
+
}
|
|
4738
|
+
createTile(gid, tileIndex, layerIndex) {
|
|
4739
|
+
if (gid == 0) {
|
|
4740
|
+
return;
|
|
4741
|
+
}
|
|
4742
|
+
const realGid = TileGid.getRealGid(gid);
|
|
4743
|
+
const tileset = Layer.findTileSet(realGid, this.tilesets);
|
|
4744
|
+
if (!tileset) {
|
|
4745
|
+
return void 0;
|
|
4746
|
+
}
|
|
4747
|
+
const tile = tileset.getTile(realGid - tileset.firstgid);
|
|
4748
|
+
if (tile) {
|
|
4749
|
+
return new Tile({
|
|
4750
|
+
...tile.tile,
|
|
4751
|
+
gid,
|
|
4752
|
+
index: tileIndex,
|
|
4753
|
+
layerIndex
|
|
4754
|
+
});
|
|
4755
|
+
}
|
|
4756
|
+
return new Tile({
|
|
4757
|
+
gid,
|
|
4758
|
+
index: tileIndex,
|
|
4759
|
+
layerIndex
|
|
4760
|
+
});
|
|
4761
|
+
}
|
|
4762
|
+
mergePropertiesWithParent() {
|
|
4763
|
+
const parent = this.getLayerParent();
|
|
4764
|
+
if (!this.properties) this.properties = {};
|
|
4765
|
+
if (!parent) return;
|
|
4766
|
+
for (let key in parent.properties) {
|
|
4767
|
+
const val = parent.properties[key];
|
|
4768
|
+
const valChild = this.properties[key];
|
|
4769
|
+
if (valChild === void 0) {
|
|
4770
|
+
this.properties[key] = val;
|
|
4771
|
+
} else {
|
|
4772
|
+
if (key == "z") {
|
|
4773
|
+
this.properties[key] += val;
|
|
4774
|
+
} else {
|
|
4775
|
+
continue;
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
this.opacity = Math.round((parent.opacity ?? 1) * (this.opacity ?? 1) * 100) / 100;
|
|
4780
|
+
this.offsetx = (parent.offsetx ?? 0) + (this.offsetx ?? 0);
|
|
4781
|
+
this.offsety = (parent.offsety ?? 0) + (this.offsety ?? 0);
|
|
4782
|
+
this.locked = parent.locked ?? false;
|
|
4783
|
+
}
|
|
4784
|
+
propertiesTiles() {
|
|
4785
|
+
if (!this.data) return;
|
|
4786
|
+
const data = this.data;
|
|
4787
|
+
for (let i = 0; i < data.length; i++) {
|
|
4788
|
+
const id = data[i];
|
|
4789
|
+
this.tiles.push(this.createTile(id, i));
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
mapObjects() {
|
|
4793
|
+
if (this.objects) {
|
|
4794
|
+
this.objects = this.objects.map((object) => {
|
|
4795
|
+
const obj = new TiledObjectClass(object);
|
|
4796
|
+
obj.layerName = this.name;
|
|
4797
|
+
return obj;
|
|
4798
|
+
});
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4801
|
+
getTileByIndex(tileIndex) {
|
|
4802
|
+
if (this.cacheTiles) {
|
|
4803
|
+
return this.tiles[tileIndex];
|
|
4804
|
+
}
|
|
4805
|
+
return this.createTile(this.data[tileIndex], tileIndex);
|
|
4806
|
+
}
|
|
4807
|
+
static findTileSet(gid, tileSets) {
|
|
4808
|
+
let tileset;
|
|
4809
|
+
for (let i = tileSets.length - 1; i >= 0; i--) {
|
|
4810
|
+
tileset = tileSets[i];
|
|
4811
|
+
if (tileset.firstgid && tileset.firstgid <= gid) {
|
|
4812
|
+
break;
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
return tileset;
|
|
4816
|
+
}
|
|
4817
|
+
getLayerParent() {
|
|
4818
|
+
return this.parent;
|
|
4819
|
+
}
|
|
4820
|
+
tilesForEach(cb) {
|
|
4821
|
+
for (let i = 0; i < this.data.length; i++) {
|
|
4822
|
+
if (this.cacheTiles) {
|
|
4823
|
+
cb(this.tiles[i], i);
|
|
4824
|
+
continue;
|
|
4825
|
+
}
|
|
4826
|
+
cb(this.createTile(this.data[i], i), i);
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
setData(tileIndex, gid) {
|
|
4830
|
+
this.data[tileIndex] = gid;
|
|
4831
|
+
}
|
|
4832
|
+
}
|
|
4833
|
+
class Tileset extends TiledProperties {
|
|
4834
|
+
constructor(tileset) {
|
|
4835
|
+
super(tileset);
|
|
4836
|
+
this.tileset = tileset;
|
|
4837
|
+
this.cacheTileId = /* @__PURE__ */ new Map();
|
|
4838
|
+
Object.assign(this, tileset);
|
|
4839
|
+
this.margin = this.margin ?? 0;
|
|
4840
|
+
this.spacing = this.spacing ?? 0;
|
|
4841
|
+
const tilesArray = tileset.tiles || tileset.tile || [];
|
|
4842
|
+
for (let tile of tilesArray) {
|
|
4843
|
+
this.addTile(tile);
|
|
4844
|
+
}
|
|
4845
|
+
Reflect.deleteProperty(this, "tiles");
|
|
4846
|
+
Reflect.deleteProperty(this, "tile");
|
|
4847
|
+
}
|
|
4848
|
+
addTile(tileObj) {
|
|
4849
|
+
const tile = new Tile(tileObj);
|
|
4850
|
+
this.cacheTileId.set(tile.id, tile);
|
|
4851
|
+
return tile;
|
|
4852
|
+
}
|
|
4853
|
+
getTile(id) {
|
|
4854
|
+
return this.cacheTileId.get(+id);
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4857
|
+
let bufferTilesets = {};
|
|
4858
|
+
class MapClass extends TiledProperties {
|
|
4859
|
+
constructor(map) {
|
|
4860
|
+
super(map ?? {});
|
|
4861
|
+
this.tilesets = [];
|
|
4862
|
+
this.layers = [];
|
|
4863
|
+
this.tmpLayers = [];
|
|
4864
|
+
this.tilesIndex = {};
|
|
4865
|
+
this.allocateMemory = 0;
|
|
4866
|
+
this.lowMemory = false;
|
|
4867
|
+
if (map) this.load(map);
|
|
4868
|
+
}
|
|
4869
|
+
load(map) {
|
|
4870
|
+
Object.assign(this, map);
|
|
4871
|
+
if (this.hasProperty("low-memory")) {
|
|
4872
|
+
this.lowMemory = this.getProperty("low-memory", false);
|
|
4873
|
+
}
|
|
4874
|
+
this.tmpLayers = [];
|
|
4875
|
+
this.mapTilesets();
|
|
4876
|
+
this.mapLayers(this.layers);
|
|
4877
|
+
this.layers = [...this.tmpLayers];
|
|
4878
|
+
Reflect.deleteProperty(this, "tmpLayers");
|
|
4879
|
+
this.setTilesIndex();
|
|
4880
|
+
this.data = map;
|
|
4881
|
+
}
|
|
4882
|
+
/**
|
|
4883
|
+
* @title Width of the map in pixels
|
|
4884
|
+
* @prop {number} [widthPx]
|
|
4885
|
+
* @readonly
|
|
4886
|
+
* @memberof Map
|
|
4887
|
+
* @memberof RpgSceneMap
|
|
4888
|
+
* */
|
|
4889
|
+
get widthPx() {
|
|
4890
|
+
return this.width * this.tilewidth;
|
|
4891
|
+
}
|
|
4892
|
+
/**
|
|
4893
|
+
* @title Height of the map in pixels
|
|
4894
|
+
* @prop {number} [heightPx]
|
|
4895
|
+
* @readonly
|
|
4896
|
+
* @memberof Map
|
|
4897
|
+
* @memberof RpgSceneMap
|
|
4898
|
+
* */
|
|
4899
|
+
get heightPx() {
|
|
4900
|
+
return this.height * this.tileheight;
|
|
4901
|
+
}
|
|
4902
|
+
/**
|
|
4903
|
+
* @title The depth of the map in pixels (this is the height of a tile ;))
|
|
4904
|
+
* @prop {number} map.zTileHeight
|
|
4905
|
+
* @readonly
|
|
4906
|
+
* @memberof Map
|
|
4907
|
+
* @memberof RpgSceneMap
|
|
4908
|
+
* */
|
|
4909
|
+
get zTileHeight() {
|
|
4910
|
+
return this.tileheight;
|
|
4911
|
+
}
|
|
4912
|
+
/**
|
|
4913
|
+
* Find a layer by name. Returns `undefined` is the layer is not found
|
|
4914
|
+
|
|
4915
|
+
* @title Get Layer by name
|
|
4916
|
+
* @method map.getLayerByName(name)
|
|
4917
|
+
* @param {string} name layer name
|
|
4918
|
+
* @returns {LayerInfo | undefined}
|
|
4919
|
+
* @example
|
|
4920
|
+
* ```ts
|
|
4921
|
+
* const tiles = map.getLayerByName(0, 0)
|
|
4922
|
+
* ```
|
|
4923
|
+
* @memberof Map
|
|
4924
|
+
* @memberof RpgSceneMap
|
|
4925
|
+
*/
|
|
4926
|
+
getLayerByName(name) {
|
|
4927
|
+
return this.layers.find((layer) => layer.name == name);
|
|
4928
|
+
}
|
|
4929
|
+
/**
|
|
4930
|
+
* Get the tile index on the tileset
|
|
4931
|
+
*
|
|
4932
|
+
* @title Get index of tile
|
|
4933
|
+
* @method map.getTileIndex(x,y)
|
|
4934
|
+
* @param {number} x Position X
|
|
4935
|
+
* @param {number} x Position Y
|
|
4936
|
+
* @returns {number}
|
|
4937
|
+
* @memberof Map
|
|
4938
|
+
* @memberof RpgSceneMap
|
|
4939
|
+
*/
|
|
4940
|
+
getTileIndex(x, y, [z] = [0]) {
|
|
4941
|
+
return this.width * Math.floor((y - z) / this.tileheight) + Math.floor(x / this.tilewidth);
|
|
4942
|
+
}
|
|
4943
|
+
getTilePosition(index) {
|
|
4944
|
+
return {
|
|
4945
|
+
y: Math.floor(index / this.width) * this.tileheight,
|
|
4946
|
+
x: index % this.width * this.tilewidth
|
|
4947
|
+
};
|
|
4948
|
+
}
|
|
4949
|
+
/**
|
|
4950
|
+
* Find the point of origin (top left) of a tile. Of course, its position depends on the size of the tile
|
|
4951
|
+
|
|
4952
|
+
* @title Get origin position of tile
|
|
4953
|
+
* @method map.getTileOriginPosition(x,y)
|
|
4954
|
+
* @param {number} x Position X
|
|
4955
|
+
* @param {number} x Position Y
|
|
4956
|
+
* @returns { {x: number, y: number }}
|
|
4957
|
+
* @example
|
|
4958
|
+
* ```ts
|
|
4959
|
+
* // If the size of a tile is 32x32px
|
|
4960
|
+
* const position = map.getTileOriginPosition(35, 12)
|
|
4961
|
+
* console.log(position) // { x: 32, y: 0 }
|
|
4962
|
+
* ```
|
|
4963
|
+
* @memberof Map
|
|
4964
|
+
* @memberof RpgSceneMap
|
|
4965
|
+
*/
|
|
4966
|
+
getTileOriginPosition(x, y) {
|
|
4967
|
+
return {
|
|
4968
|
+
x: Math.floor(x / this.tilewidth) * this.tilewidth,
|
|
4969
|
+
y: Math.floor(y / this.tileheight) * this.tileheight
|
|
4970
|
+
};
|
|
4971
|
+
}
|
|
4972
|
+
/**
|
|
4973
|
+
* Recover tiles according to a position
|
|
4974
|
+
|
|
4975
|
+
* @title Get tile by position
|
|
4976
|
+
* @method map.getTileByPosition(x,y)
|
|
4977
|
+
* @param {number} x Position X
|
|
4978
|
+
* @param {number} x Position Y
|
|
4979
|
+
* @returns {TileInfo}
|
|
4980
|
+
* @example
|
|
4981
|
+
* ```ts
|
|
4982
|
+
* const tiles = map.getTileByPosition(0, 0)
|
|
4983
|
+
* ```
|
|
4984
|
+
* @memberof Map
|
|
4985
|
+
* @memberof RpgSceneMap
|
|
4986
|
+
*/
|
|
4987
|
+
getTileByPosition(x, y, z = [0, 0], options = {}) {
|
|
4988
|
+
const tileIndex = this.getTileIndex(x, y, [z[0]]);
|
|
4989
|
+
return this.getTileByIndex(tileIndex, z, options);
|
|
4990
|
+
}
|
|
4991
|
+
/**
|
|
4992
|
+
* Retrieves tiles according to its index
|
|
4993
|
+
|
|
4994
|
+
* @title Get tile by index
|
|
4995
|
+
* @method map.getTileByIndex(tileIndex)
|
|
4996
|
+
* @param {number} tileIndex tile index
|
|
4997
|
+
* @returns {TileInfo}
|
|
4998
|
+
* @example
|
|
4999
|
+
* ```ts
|
|
5000
|
+
* const index = map.getTileIndex(0, 0)
|
|
5001
|
+
* const tiles = map.getTileByIndex(index)
|
|
5002
|
+
* ```
|
|
5003
|
+
* @memberof Map
|
|
5004
|
+
* @memberof RpgSceneMap
|
|
5005
|
+
*/
|
|
5006
|
+
getTileByIndex(tileIndex, zPlayer = [0, 0], options = {
|
|
5007
|
+
populateTiles: true
|
|
5008
|
+
}) {
|
|
5009
|
+
const zA = Math.floor(zPlayer[0] / this.zTileHeight);
|
|
5010
|
+
Math.floor(zPlayer[1] / this.zTileHeight);
|
|
5011
|
+
const level = this.tilesIndex[zA];
|
|
5012
|
+
const obj = {
|
|
5013
|
+
tiles: [],
|
|
5014
|
+
hasCollision: false,
|
|
5015
|
+
isOverlay: false,
|
|
5016
|
+
objectGroups: [],
|
|
5017
|
+
tileIndex
|
|
5018
|
+
};
|
|
5019
|
+
if (!level) {
|
|
5020
|
+
return obj;
|
|
5021
|
+
}
|
|
5022
|
+
const [layer] = this.layers;
|
|
5023
|
+
const getTileByPointer = (pointer = 0) => {
|
|
5024
|
+
const pos = tileIndex * this.realAllocateMemory + pointer;
|
|
5025
|
+
const gid = level[pos];
|
|
5026
|
+
if (gid === 0) {
|
|
5027
|
+
return obj;
|
|
5028
|
+
}
|
|
5029
|
+
const tile2 = layer.createTile(gid, tileIndex, level[pos + 1]);
|
|
5030
|
+
if (tile2) obj.tiles.push(tile2);
|
|
5031
|
+
};
|
|
5032
|
+
if (options.populateTiles) {
|
|
5033
|
+
for (let i = 0; i < this.realAllocateMemory; i += 2) {
|
|
5034
|
+
getTileByPointer(i);
|
|
5035
|
+
}
|
|
5036
|
+
} else {
|
|
5037
|
+
getTileByPointer();
|
|
5038
|
+
}
|
|
5039
|
+
const [tile] = obj.tiles;
|
|
5040
|
+
if (tile) {
|
|
5041
|
+
obj.hasCollision = tile.getProperty("collision", false);
|
|
5042
|
+
obj.objectGroups = tile.objects ?? [];
|
|
5043
|
+
}
|
|
5044
|
+
return obj;
|
|
5045
|
+
}
|
|
5046
|
+
getAllObjects() {
|
|
5047
|
+
return this.layers.reduce((prev, current) => {
|
|
5048
|
+
if (!current.objects) return prev;
|
|
5049
|
+
return prev.concat(...current.objects);
|
|
5050
|
+
}, []);
|
|
5051
|
+
}
|
|
5052
|
+
getData() {
|
|
5053
|
+
return {
|
|
5054
|
+
...this.data,
|
|
5055
|
+
layers: this.layers
|
|
5056
|
+
};
|
|
5057
|
+
}
|
|
5058
|
+
setTile(x, y, layerFilter, tileInfo) {
|
|
5059
|
+
if (this.lowMemory) {
|
|
5060
|
+
throw "Impossible to change a tile with the lowMemory option";
|
|
5061
|
+
}
|
|
5062
|
+
const tileIndex = this.getTileIndex(x, y);
|
|
5063
|
+
let fnFilter;
|
|
5064
|
+
let tilesEdited = {};
|
|
5065
|
+
if (typeof layerFilter == "string") {
|
|
5066
|
+
fnFilter = (layer) => layer.name == layerFilter;
|
|
5067
|
+
} else {
|
|
5068
|
+
fnFilter = layerFilter;
|
|
5069
|
+
}
|
|
5070
|
+
for (let i = 0; i < this.layers.length; i++) {
|
|
5071
|
+
const layer = this.layers[i];
|
|
5072
|
+
if (!fnFilter(layer)) continue;
|
|
5073
|
+
let tile;
|
|
5074
|
+
const oldTile = this.getTileByIndex(tileIndex);
|
|
5075
|
+
if (tileInfo.gid) {
|
|
5076
|
+
tile = layer.createTile(tileInfo.gid, tileIndex);
|
|
5077
|
+
}
|
|
5078
|
+
if (!tile) continue;
|
|
5079
|
+
for (let key in tileInfo) {
|
|
5080
|
+
if (key == "gid") continue;
|
|
5081
|
+
tile[key] = tileInfo[key];
|
|
5082
|
+
}
|
|
5083
|
+
tilesEdited[layer.name] = {
|
|
5084
|
+
gid: tile.gid,
|
|
5085
|
+
properties: tile.properties
|
|
5086
|
+
};
|
|
5087
|
+
this.setTileIndex(layer, oldTile.tiles[0], tile, tileIndex, i);
|
|
5088
|
+
layer.setData(tileIndex, tile.gid);
|
|
5089
|
+
}
|
|
5090
|
+
return {
|
|
5091
|
+
x,
|
|
5092
|
+
y,
|
|
5093
|
+
tiles: tilesEdited
|
|
5094
|
+
};
|
|
5095
|
+
}
|
|
5096
|
+
removeCacheTileset(name) {
|
|
5097
|
+
delete bufferTilesets[name];
|
|
5098
|
+
}
|
|
5099
|
+
clearCacheTilesets() {
|
|
5100
|
+
bufferTilesets = {};
|
|
5101
|
+
}
|
|
5102
|
+
mapTilesets() {
|
|
5103
|
+
this.tilesets = this.tilesets.map((tileset) => {
|
|
5104
|
+
if (bufferTilesets[tileset.name]) {
|
|
5105
|
+
const instance = bufferTilesets[tileset.name];
|
|
5106
|
+
instance.firstgid = tileset.firstgid;
|
|
5107
|
+
return instance;
|
|
5108
|
+
}
|
|
5109
|
+
const _tileset = new Tileset(tileset);
|
|
5110
|
+
bufferTilesets[_tileset.name] = _tileset;
|
|
5111
|
+
return _tileset;
|
|
5112
|
+
});
|
|
5113
|
+
}
|
|
5114
|
+
mapLayers(layers = [], parent) {
|
|
5115
|
+
for (let layer of layers) {
|
|
5116
|
+
const layerInstance = new Layer(layer, this.tilesets, parent);
|
|
5117
|
+
this.tmpLayers.push(layerInstance);
|
|
5118
|
+
if (layer.layers) {
|
|
5119
|
+
this.mapLayers(layer.layers, layerInstance);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
if (this.lowMemory) this.allocateMemory = 1;
|
|
5123
|
+
if (!this.allocateMemory) this.allocateMemory = this.layers.length;
|
|
5124
|
+
}
|
|
5125
|
+
setTileIndex(layer, oldTile, newTile, tileIndex, layerIndex) {
|
|
5126
|
+
const startPos = tileIndex * this.realAllocateMemory;
|
|
5127
|
+
let pointer = startPos + this.realAllocateMemory - 2;
|
|
5128
|
+
const zLayer = layer.getProperty("z", 0);
|
|
5129
|
+
const zTile = oldTile.getProperty("z", 0);
|
|
5130
|
+
let z = zLayer + zTile;
|
|
5131
|
+
while (pointer >= startPos) {
|
|
5132
|
+
const zlayer = this.tilesIndex[z];
|
|
5133
|
+
if (zlayer[pointer] === oldTile.gid && zlayer[pointer + 1] === layerIndex) {
|
|
5134
|
+
this.tilesIndex[z][pointer] = newTile.gid;
|
|
5135
|
+
}
|
|
5136
|
+
pointer -= 2;
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
/**
|
|
5140
|
+
* We multiply by 2 because 2 entries are stored for a tile: its GID and the Layer Index
|
|
5141
|
+
*
|
|
5142
|
+
* Example If I have 3 layers, The array will have the following form
|
|
5143
|
+
*
|
|
5144
|
+
* [
|
|
5145
|
+
* GID of Layer 3,
|
|
5146
|
+
* Layer Index of Layer 3,
|
|
5147
|
+
* GID of Layer 2,
|
|
5148
|
+
* Layer Index of Layer 2,
|
|
5149
|
+
* GID of Layer 1,
|
|
5150
|
+
* Layer Index of Layer 1,
|
|
5151
|
+
* ... others tiles
|
|
5152
|
+
* ]
|
|
5153
|
+
*
|
|
5154
|
+
* The size in memory of the map is therefore:
|
|
5155
|
+
*
|
|
5156
|
+
* `(map width * map height * number of layers * 4) bytes`
|
|
5157
|
+
*
|
|
5158
|
+
* > We multiply by 4, because an element takes 2 bytes and has 2 elements for a tile is 4 bytes in all
|
|
5159
|
+
*
|
|
5160
|
+
* Example (a 100x100 map with 5 layers)
|
|
5161
|
+
*
|
|
5162
|
+
* `100 * 100 * 5 * 4 = 200000 bytes = ~195 Kb`
|
|
5163
|
+
*
|
|
5164
|
+
* If we define on lowMemory then the calculation is the following
|
|
5165
|
+
*
|
|
5166
|
+
* `(map width * map height * 4) bytes`
|
|
5167
|
+
*
|
|
5168
|
+
* Example
|
|
5169
|
+
*
|
|
5170
|
+
* `100 * 100 * 4 = 40000 bytes = ~39 Kb`
|
|
5171
|
+
*/
|
|
5172
|
+
get realAllocateMemory() {
|
|
5173
|
+
return this.allocateMemory * 2;
|
|
5174
|
+
}
|
|
5175
|
+
/**
|
|
5176
|
+
* 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
|
|
5177
|
+
*
|
|
5178
|
+
*/
|
|
5179
|
+
addTileIndex(layer, tile, tileIndex, layerIndex) {
|
|
5180
|
+
if (!tile || tile && tile.gid == 0) {
|
|
5181
|
+
return;
|
|
5182
|
+
}
|
|
5183
|
+
const zLayer = layer.getProperty("z", 0);
|
|
5184
|
+
const zTile = tile.getProperty("z", 0);
|
|
5185
|
+
let z = zLayer + zTile;
|
|
5186
|
+
if (!this.tilesIndex[z]) {
|
|
5187
|
+
const buffer2 = new ArrayBuffer(layer.size * this.realAllocateMemory * 2);
|
|
5188
|
+
this.tilesIndex[z] = new Uint16Array(buffer2);
|
|
5189
|
+
}
|
|
5190
|
+
const startPos = tileIndex * this.realAllocateMemory;
|
|
5191
|
+
let pointer = startPos + this.realAllocateMemory - 2;
|
|
5192
|
+
while (this.tilesIndex[z][pointer] !== 0 && pointer > startPos) {
|
|
5193
|
+
pointer -= 2;
|
|
5194
|
+
}
|
|
5195
|
+
this.tilesIndex[z][pointer] = tile.gid;
|
|
5196
|
+
this.tilesIndex[z][pointer + 1] = layerIndex;
|
|
5197
|
+
this.tilesIndex[z][startPos] = tile.gid;
|
|
5198
|
+
this.tilesIndex[z][startPos + 1] = layerIndex;
|
|
5199
|
+
}
|
|
5200
|
+
setTilesIndex() {
|
|
5201
|
+
for (let i = 0; i < this.layers.length; i++) {
|
|
5202
|
+
const layer = this.layers[i];
|
|
5203
|
+
if (layer.type != TiledLayerType.Tile) {
|
|
5204
|
+
continue;
|
|
5205
|
+
}
|
|
5206
|
+
layer.tilesForEach((tile, index) => {
|
|
5207
|
+
this.addTileIndex(layer, tile, index, i);
|
|
5208
|
+
});
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
}
|
|
4639
5212
|
export {
|
|
4640
|
-
|
|
5213
|
+
Layer,
|
|
5214
|
+
MapClass,
|
|
5215
|
+
Tile,
|
|
5216
|
+
TiledLayerType,
|
|
5217
|
+
TiledObjectClass,
|
|
5218
|
+
TiledParser,
|
|
5219
|
+
TiledProperties,
|
|
5220
|
+
Tileset
|
|
4641
5221
|
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { MapClass } from "./index3.js";
|
|
2
|
+
function prepareTiledPhysicsData(mapData, map) {
|
|
3
|
+
if (!mapData?.parsedMap) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
const tiledMap = new MapClass(mapData.parsedMap);
|
|
7
|
+
map.tiled = tiledMap;
|
|
8
|
+
mapData.hitboxes = mapData.hitboxes || [];
|
|
9
|
+
mapData.width = tiledMap.widthPx;
|
|
10
|
+
mapData.height = tiledMap.heightPx;
|
|
11
|
+
map._tiledTileWidth = tiledMap.tilewidth;
|
|
12
|
+
map._tiledTileHeight = tiledMap.tileheight;
|
|
13
|
+
map._blockedTiles = collectBlockedTiles(tiledMap);
|
|
14
|
+
}
|
|
15
|
+
function attachTiledCollisionToEntity(owner, map) {
|
|
16
|
+
if (!owner?.id || !map?._blockedTiles) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const entity = map.physic?.getEntityByUUID(owner.id);
|
|
20
|
+
if (!entity || typeof entity.canEnterTile !== "function") {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const unsubscribers = ensureUnsubscribers(map);
|
|
24
|
+
const previousUnsubscribe = unsubscribers.get(owner.id);
|
|
25
|
+
if (previousUnsubscribe) {
|
|
26
|
+
previousUnsubscribe();
|
|
27
|
+
unsubscribers.delete(owner.id);
|
|
28
|
+
}
|
|
29
|
+
const blockedTiles = map._blockedTiles;
|
|
30
|
+
const tiledTileWidth = map._tiledTileWidth ?? 32;
|
|
31
|
+
const tiledTileHeight = map._tiledTileHeight ?? 32;
|
|
32
|
+
const physicsTileWidth = 32;
|
|
33
|
+
const physicsTileHeight = 32;
|
|
34
|
+
const unsubscribe = entity.canEnterTile(({ x, y }) => {
|
|
35
|
+
const tiledX = Math.floor(x * physicsTileWidth / tiledTileWidth);
|
|
36
|
+
const tiledY = Math.floor(y * physicsTileHeight / tiledTileHeight);
|
|
37
|
+
return !blockedTiles.has(`${tiledX},${tiledY}`);
|
|
38
|
+
});
|
|
39
|
+
unsubscribers.set(owner.id, unsubscribe);
|
|
40
|
+
}
|
|
41
|
+
function detachTiledCollisionFromEntity(owner, map) {
|
|
42
|
+
if (!owner?.id) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const unsubscribers = map._tiledCollisionUnsubscribers;
|
|
46
|
+
if (!unsubscribers) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const unsubscribe = unsubscribers.get(owner.id);
|
|
50
|
+
if (!unsubscribe) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
unsubscribe();
|
|
54
|
+
unsubscribers.delete(owner.id);
|
|
55
|
+
}
|
|
56
|
+
function resetTiledCollisionHandlers(map) {
|
|
57
|
+
const unsubscribers = map._tiledCollisionUnsubscribers;
|
|
58
|
+
if (unsubscribers) {
|
|
59
|
+
for (const unsubscribe of unsubscribers.values()) {
|
|
60
|
+
unsubscribe();
|
|
61
|
+
}
|
|
62
|
+
unsubscribers.clear();
|
|
63
|
+
}
|
|
64
|
+
map._blockedTiles = void 0;
|
|
65
|
+
map._tiledTileWidth = void 0;
|
|
66
|
+
map._tiledTileHeight = void 0;
|
|
67
|
+
}
|
|
68
|
+
function collectBlockedTiles(tiledMap) {
|
|
69
|
+
const blockedTiles = /* @__PURE__ */ new Set();
|
|
70
|
+
const mapWidth = tiledMap.width;
|
|
71
|
+
const mapHeight = tiledMap.height;
|
|
72
|
+
const tileWidth = tiledMap.tilewidth;
|
|
73
|
+
const tileHeight = tiledMap.tileheight;
|
|
74
|
+
for (let y = 0; y < mapHeight; y++) {
|
|
75
|
+
for (let x = 0; x < mapWidth; x++) {
|
|
76
|
+
const tileInfo = tiledMap.getTileByPosition(x * tileWidth, y * tileHeight, [0, 0], {
|
|
77
|
+
populateTiles: true
|
|
78
|
+
});
|
|
79
|
+
if (tileInfo.hasCollision) {
|
|
80
|
+
blockedTiles.add(`${x},${y}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return blockedTiles;
|
|
85
|
+
}
|
|
86
|
+
function ensureUnsubscribers(map) {
|
|
87
|
+
map._tiledCollisionUnsubscribers = map._tiledCollisionUnsubscribers || /* @__PURE__ */ new Map();
|
|
88
|
+
return map._tiledCollisionUnsubscribers;
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
attachTiledCollisionToEntity,
|
|
92
|
+
detachTiledCollisionFromEntity,
|
|
93
|
+
prepareTiledPhysicsData,
|
|
94
|
+
resetTiledCollisionHandlers
|
|
95
|
+
};
|