Skip to content

Commit

Permalink
Allow to filter tile map collision per layer
Browse files Browse the repository at this point in the history
  • Loading branch information
D8H committed Oct 1, 2024
1 parent de7f60b commit 8c56d21
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 53 deletions.
39 changes: 39 additions & 0 deletions Extensions/TileMap/JsExtension.js
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,14 @@ const defineCollisionMask = function (extension, _, gd) {
objectContent.collisionMaskTag = newValue;
return true;
}
if (propertyName === 'layerIndex') {
objectContent.layerIndex = parseFloat(newValue);
return true;
}
if (propertyName === 'useAllLayers') {
objectContent.useAllLayers = newValue === '1';
return true;
}
if (propertyName === 'debugMode') {
objectContent.debugMode = newValue === '1';
return true;
Expand Down Expand Up @@ -1149,6 +1157,28 @@ const defineCollisionMask = function (extension, _, gd) {
)
)
);
objectProperties.set(
'layerIndex',
new gd.PropertyDescriptor(objectContent.layerIndex.toString())
.setType('number')
.setLabel(_('Layer index'))
.setGroup(_('Layers'))
.setAdvanced()
);
objectProperties.set(
'useAllLayers',
new gd.PropertyDescriptor(
objectContent.useAllLayers ||
objectContent.useAllLayers === undefined ||
objectContent.useAllLayers === null
? 'true'
: 'false'
)
.setType('boolean')
.setLabel(_('Use all layers'))
.setGroup(_('Layers'))
.setAdvanced()
);
objectProperties.set(
'debugMode',
new gd.PropertyDescriptor(objectContent.debugMode ? 'true' : 'false')
Expand Down Expand Up @@ -1207,6 +1237,8 @@ const defineCollisionMask = function (extension, _, gd) {
tilemapJsonFile: '',
tilesetJsonFile: '',
collisionMaskTag: '',
layerIndex: 0,
useAllLayers: true,
debugMode: false,
fillColor: '255;255;255',
outlineColor: '255;255;255',
Expand Down Expand Up @@ -2381,6 +2413,7 @@ module.exports = {
_tilemapJsonFile = '';
_tilesetJsonFile = '';
_collisionMaskTag = '';
_layerIndex = null;
_outlineColor = 0xffffff;
_fillColor = 0xffffff;
_outlineOpacity = 0;
Expand Down Expand Up @@ -2481,6 +2514,7 @@ module.exports = {
const tilemapJsonFile = this._tilemapJsonFile;
const tilesetJsonFile = this._tilesetJsonFile;
const collisionMaskTag = this._collisionMaskTag;
const layerIndex = this._layerIndex;
const outlineColor = this._outlineColor;
const fillColor = this._fillColor;
const outlineOpacity = this._outlineOpacity;
Expand Down Expand Up @@ -2509,6 +2543,7 @@ module.exports = {
this._pixiObject,
tileMap,
collisionMaskTag,
layerIndex,
outlineSize,
outlineColor,
outlineOpacity,
Expand Down Expand Up @@ -2566,6 +2601,8 @@ module.exports = {
const tilemapJsonFile = object.content.tilemapJsonFile;
const tilesetJsonFile = object.content.tilesetJsonFile;
const collisionMaskTag = object.content.collisionMaskTag;
const useAllLayers = object.content.useAllLayers;
const layerIndex = useAllLayers ? null : object.content.layerIndex;
const outlineColor = objectsRenderingService.rgbOrHexToHexNumber(
object.content.outlineColor
);
Expand All @@ -2580,6 +2617,7 @@ module.exports = {
tilemapJsonFile !== this._tilemapJsonFile ||
tilesetJsonFile !== this._tilesetJsonFile ||
collisionMaskTag !== this._collisionMaskTag ||
layerIndex !== this._layerIndex ||
outlineColor !== this._outlineColor ||
fillColor !== this._fillColor ||
outlineOpacity !== this._outlineOpacity ||
Expand All @@ -2589,6 +2627,7 @@ module.exports = {
this._tilemapJsonFile = tilemapJsonFile;
this._tilesetJsonFile = tilesetJsonFile;
this._collisionMaskTag = collisionMaskTag;
this._layerIndex = layerIndex;
this._outlineColor = outlineColor;
this._fillColor = fillColor;
this._outlineOpacity = outlineOpacity;
Expand Down
18 changes: 17 additions & 1 deletion Extensions/TileMap/collision/TransformedTileMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace gdjs {
*/
private _source: TileMapHelper.EditableTileMap;
tag: string;
private _layerIndex: integer | null;
private _layers: Map<integer, TransformedCollisionTileMapLayer>;
// TODO Tiled allows to offset the layers
/**
Expand All @@ -37,9 +38,14 @@ namespace gdjs {
/**
* @param source The model that describes the tile map.
*/
constructor(source: TileMapHelper.EditableTileMap, tag: string) {
constructor(
source: TileMapHelper.EditableTileMap,
tag: string,
layerIndex: number | null = null
) {
this._source = source;
this.tag = tag;
this._layerIndex = layerIndex;
this._layers = new Map<integer, TransformedCollisionTileMapLayer>();
this._buildLayersFromTileMap(source, this._layers);
}
Expand All @@ -55,6 +61,16 @@ namespace gdjs {
tileMap: TileMapHelper.EditableTileMap,
layers: Map<integer, TransformedCollisionTileMapLayer>
) {
if (this._layerIndex) {
const tileLayer = tileMap.getTileLayer(this._layerIndex);
if (!tileLayer) {
return;
}
layers.set(
tileLayer.id,
new TransformedCollisionTileMapLayer(this, tileLayer)
);
}
for (const sourceLayer of tileMap.getLayers()) {
// TODO A visitor could be used to avoid a cast.
if (!(sourceLayer instanceof TileMapHelper.EditableTileMapLayer)) {
Expand Down
2 changes: 1 addition & 1 deletion Extensions/TileMap/helper/TileMapHelper.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Extensions/TileMap/helper/TileMapHelper.js.map

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export declare namespace PixiTileMapHelper {
pixiGraphics: PIXI.Graphics,
tileMap: EditableTileMap,
typeFilter: string,
layerIndex: integer | null,
outlineSize: integer,
outlineColor: integer,
outlineOpacity: float,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions Extensions/TileMap/tilemapcollisionmaskruntimeobject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace gdjs {
* For instance, platforms, jumpthru, ladder, spike, water...
*/
private _collisionMaskTag: string;
private _layerIndex: integer | null;
private _tileMapManager: gdjs.TileMap.TileMapRuntimeManager;

/**
Expand Down Expand Up @@ -80,6 +81,9 @@ namespace gdjs {
this._tilemapJsonFile = objectData.content.tilemapJsonFile;
this._tilesetJsonFile = objectData.content.tilesetJsonFile;
this._collisionMaskTag = objectData.content.collisionMaskTag;
this._layerIndex = objectData.content.useAllLayers
? null
: objectData.content.layerIndex;
this._debugMode = objectData.content.debugMode;
this._fillColor = gdjs.rgbOrHexStringToNumber(
objectData.content.fillColor
Expand Down Expand Up @@ -108,7 +112,8 @@ namespace gdjs {
);
this._collisionTileMap = new gdjs.TileMap.TransformedCollisionTileMap(
editableTileMap,
this._collisionMaskTag
this._collisionMaskTag,
this._layerIndex
);

this._renderer = new gdjs.TileMap.TileMapCollisionMaskRenderer(
Expand Down Expand Up @@ -178,6 +183,7 @@ namespace gdjs {
if (oldObjectData.outlineSize !== newObjectData.outlineSize) {
this.setOutlineSize(newObjectData.outlineSize);
}
// TODO Handle changes to collisionMaskTag, useAllLayers and layerIndex.
return true;
}

Expand Down Expand Up @@ -254,7 +260,8 @@ namespace gdjs {

this._collisionTileMap = new gdjs.TileMap.TransformedCollisionTileMap(
tileMap,
this._collisionMaskTag
this._collisionMaskTag,
this._layerIndex
);
// The tile map polygons always keep the same references.
// It works because the tilemap is never modified.
Expand Down
121 changes: 74 additions & 47 deletions SharedLibs/TileMapHelper/src/render/TileMapPixiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export namespace PixiTileMapHelper {
pixiGraphics: PIXI.Graphics,
tileMap: EditableTileMap,
typeFilter: string,
layerIndex: integer | null,
outlineSize: integer,
outlineColor: integer,
outlineOpacity: float,
Expand All @@ -233,60 +234,86 @@ export namespace PixiTileMapHelper {
pixiGraphics.lineStyle(outlineSize, outlineColor, outlineOpacity);
pixiGraphics.drawRect(0, 0, tileMap.getWidth(), tileMap.getHeight());

for (const layer of tileMap.getLayers()) {
const tileWidth = tileMap.getTileWidth();
const tileHeight = tileMap.getTileHeight();
if (layerIndex) {
const tileMapLayer = tileMap.getTileLayer(layerIndex);
drawCollisionLayer(
pixiGraphics,
tileMapLayer,
typeFilter,
fillColor,
fillOpacity
);
} else {
for (const layer of tileMap.getLayers()) {
if (layer instanceof EditableTileMapLayer) {
drawCollisionLayer(
pixiGraphics,
layer as EditableTileMapLayer,
typeFilter,
fillColor,
fillOpacity
);
}
}
}
}

if (layer instanceof EditableTileMapLayer) {
const tileLayer = layer as EditableTileMapLayer;
function drawCollisionLayer(
pixiGraphics: PIXI.Graphics,
tileLayer: EditableTileMapLayer,
typeFilter: string,
fillColor: integer,
fillOpacity: float
): void {
const tileMap = tileLayer.tileMap;
const tileWidth = tileMap.getTileWidth();
const tileHeight = tileMap.getTileHeight();

for (let y = 0; y < tileLayer.tileMap.getDimensionY(); y++) {
for (let x = 0; x < tileLayer.tileMap.getDimensionX(); x++) {
const xPos = tileWidth * x;
const yPos = tileHeight * y;
for (let y = 0; y < tileMap.getDimensionY(); y++) {
for (let x = 0; x < tileMap.getDimensionX(); x++) {
const xPos = tileWidth * x;
const yPos = tileHeight * y;

const tileId = tileLayer.getTileId(x, y)!;
const isFlippedHorizontally = tileLayer.isFlippedHorizontally(x, y);
const isFlippedVertically = tileLayer.isFlippedVertically(x, y);
const isFlippedDiagonally = tileLayer.isFlippedDiagonally(x, y);
const tileDefinition = tileLayer.tileMap.getTileDefinition(tileId);
if (!tileDefinition) {
continue;
const tileId = tileLayer.getTileId(x, y)!;
const isFlippedHorizontally = tileLayer.isFlippedHorizontally(x, y);
const isFlippedVertically = tileLayer.isFlippedVertically(x, y);
const isFlippedDiagonally = tileLayer.isFlippedDiagonally(x, y);
const tileDefinition = tileMap.getTileDefinition(tileId);
if (!tileDefinition) {
continue;
}
const hitboxes = tileDefinition.getHitBoxes(typeFilter);
if (!hitboxes) {
continue;
}
for (const vertices of hitboxes) {
if (vertices.length === 0) continue;

pixiGraphics.beginFill(fillColor, fillOpacity);
for (let index = 0; index < vertices.length; index++) {
let vertexX = vertices[index][0];
let vertexY = vertices[index][1];
// It's important to do the diagonal flipping first,
// because the other flipping "move" the origin.
if (isFlippedDiagonally) {
const swap = vertexX;
vertexX = vertexY;
vertexY = swap;
}
const hitboxes = tileDefinition.getHitBoxes(typeFilter);
if (!hitboxes) {
continue;
if (isFlippedHorizontally) {
vertexX = tileWidth - vertexX;
}
for (const vertices of hitboxes) {
if (vertices.length === 0) continue;

pixiGraphics.beginFill(fillColor, fillOpacity);
for (let index = 0; index < vertices.length; index++) {
let vertexX = vertices[index][0];
let vertexY = vertices[index][1];
// It's important to do the diagonal flipping first,
// because the other flipping "move" the origin.
if (isFlippedDiagonally) {
const swap = vertexX;
vertexX = vertexY;
vertexY = swap;
}
if (isFlippedHorizontally) {
vertexX = tileWidth - vertexX;
}
if (isFlippedVertically) {
vertexY = tileHeight - vertexY;
}
if (index === 0) {
pixiGraphics.moveTo(xPos + vertexX, yPos + vertexY);
} else {
pixiGraphics.lineTo(xPos + vertexX, yPos + vertexY);
}
}
pixiGraphics.closePath();
pixiGraphics.endFill();
if (isFlippedVertically) {
vertexY = tileHeight - vertexY;
}
if (index === 0) {
pixiGraphics.moveTo(xPos + vertexX, yPos + vertexY);
} else {
pixiGraphics.lineTo(xPos + vertexX, yPos + vertexY);
}
}
pixiGraphics.closePath();
pixiGraphics.endFill();
}
}
}
Expand Down

0 comments on commit 8c56d21

Please sign in to comment.