Skip to content

Commit

Permalink
New Tiled Plugin Features per User Feedback (#485)
Browse files Browse the repository at this point in the history
New tile methods for convenience, all of these methods are also available at the layer level
* `TiledResource.getTilesByPoint` - Returns any excalibur Tile instances and any metadata for a tile below the world space point provided
* `TiledResource.getTileMetadataByClassName` - renamed from `getTilesByClassname`. This returns the Tiled metadata for a tile by classname.
* `TiledResource.getTileMetadataByProperty` - renamed from `getTilesByProperty`. This returns returns the Tiled metadata for a tile by property.
* `TiledResource.getTilesByGid` - get the Excalibur Tile instances and any Tiled metadata for a matching tile by global id
* `TiledResource.getTilesByClassName` - get the Excalibur Tile instances and any Tiled metadata for a mathcing tile by classname
* `TiledResource.getTilesByProperty` - get the Excalibur Tile instances and and any Tile metadata for a matching property.

* Entity factories can now be defined after load, but before adding to the scene!

This PR adds

* [x] The ability to run entity factories after load
* [x] Getting all Excalibur Tile instances that match a gid
* [x] Getting all Excalibur Tile instances that match a class name
* [x] Getting all Excalibur Tile instances that match a property
  • Loading branch information
eonarheim committed Jan 24, 2024
1 parent 2b0a9c8 commit 2bd697f
Show file tree
Hide file tree
Showing 23 changed files with 359 additions and 85 deletions.
45 changes: 0 additions & 45 deletions .github/workflows/deploy.yml

This file was deleted.

30 changes: 30 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Release to NPM
on:
release:
types: [published]

env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

jobs:
build:
uses: ./.github/workflows/build.yml
deploy_release:
name: Publish npm package
needs: [build]
runs-on: [ubuntu-latest]

steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 100
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
cache: npm
- run: npm ci
- run: npm run build
- run: npm publish --access public
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ game.start(loader).then(() => {

## Documentation

For information on how to use the plugin visit https://beta.excaliburjs.com/docs/plugin/tiled-plugin
For information on how to use the plugin visit https://excaliburjs.com/docs/plugin/tiled-plugin

## Contributing

Expand Down
1 change: 1 addition & 0 deletions example/formats/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const start = (mapFile: string) => {
const map = new TiledResource(mapFile, {
startZIndex: -2
});
(window as any).tiledMap = map;
const playercube = new ImageSource('./player-cube.png', true, ImageFiltering.Blended);
const loader = new ex.Loader([map, playercube]);

Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

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

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@excaliburjs/plugin-tiled",
"version": "0.29.0-alpha.1",
"version": "0.29.0-alpha.2",
"description": "excalibur-tiled provides Tiled map editor integration with Excalibur.js",
"main": "dist/excalibur-tiled.min.js",
"typings": "dist/src/index.d.ts",
Expand Down Expand Up @@ -50,7 +50,7 @@
"@types/pako": "1.0.7",
"@types/webpack-env": "1.18.4",
"cross-env": "7.0.3",
"excalibur": "~0.28.5",
"excalibur": "~0.29.0-alpha.870",
"http-server": "14.1.1",
"jasmine-core": "5.1.1",
"json-diff": "1.0.6",
Expand All @@ -76,7 +76,7 @@
"zstddec": "0.1.0"
},
"peerDependencies": {
"excalibur": "~0.28.5"
"excalibur": "~0.29.0-alpha.870"
},
"optionalDependencies": {
"jsdom": "^23.2.0"
Expand Down
1 change: 1 addition & 0 deletions src/deprecated/tiled-layer-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TiledLayer } from "./tiled-layer";
/**
* @deprecated
*/
// @ts-ignore
export class TiledLayerComponent extends Component<'ex.tiledlayer'> {
public readonly type = "ex.tiledlayer";
constructor(public layer: TiledLayer) {
Expand Down
4 changes: 4 additions & 0 deletions src/deprecated/tiled-map-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export class TiledMapResource implements Loadable<TiledMap> {
// FIXME no ellipse support yet for colliders in isometric
actor.collider.useCircleCollider(collider.radius);
}
// @ts-ignore
actor.addComponent(new TiledObjectComponent(collider.tiled));
scene.add(actor);
if (collider.zIndex) {
Expand Down Expand Up @@ -238,6 +239,7 @@ export class TiledMapResource implements Loadable<TiledMap> {
label.color = Color.fromHex(text.text?.color ?? '#000000');
label.collider.set(Shape.Box(text.width ?? 0, text.height ?? 0));
label.body.collisionType = CollisionType.PreventCollision;
// @ts-ignore
label.addComponent(new TiledObjectComponent(text));

label.z = this._calculateZIndex(text, objectLayer);
Expand Down Expand Up @@ -293,6 +295,7 @@ export class TiledMapResource implements Loadable<TiledMap> {
actor.collider.clear();
actor.collider.set(new CompositeCollider(colliders));
}
// @ts-ignore
actor.addComponent(new TiledObjectComponent(tile));
actor.graphics.anchor = this.isIsometric() ? vec(.5, 1) : vec(0, 1);
// respect tile size on sprite
Expand Down Expand Up @@ -710,6 +713,7 @@ export class TiledMapResource implements Loadable<TiledMap> {
columns: this.data.width,
rows: this.data.height
});
// @ts-ignore
tileMapLayer.addComponent(new TiledLayerComponent(layer));
if (layer.rawLayer.parallaxx || layer.rawLayer.parallaxy) {
const factor = vec(layer.rawLayer.parallaxx ?? 1.0, layer.rawLayer.parallaxy ?? 1.0);
Expand Down
1 change: 1 addition & 0 deletions src/deprecated/tiled-object-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TiledObject } from "./tiled-object";
/**
* @deprecated
*/
// @ts-ignore
export class TiledObjectComponent extends Component<'ex.tiledobject'> {
public readonly type = "ex.tiledobject";
constructor(public object: TiledObject) {
Expand Down
3 changes: 3 additions & 0 deletions src/resource/excalibur-properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Special excalibur properties
*/
export const ExcaliburTiledProperties = {
TileData: {
Tiled: 'ex-tiled'
},
ZIndex: {
/**
* Override the default z-index based on the ordering in Tiled
Expand Down
68 changes: 66 additions & 2 deletions src/resource/iso-tile-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ExcaliburTiledProperties } from "./excalibur-properties";
import { TiledLayerDataComponent } from "./tiled-layer-component";
import { Layer } from "./layer";
import { Tile } from "./tileset";
import { byClassCaseInsensitive, byPropertyCaseInsensitive } from "./filter-util";

export interface IsometricTileInfo {
/**
Expand Down Expand Up @@ -44,6 +45,9 @@ export class IsoTileLayer implements Layer {
* Excalibur IsometricMap structure for drawing in excalibur
*/
isometricMap!: IsometricMap;

private _gidToTileInfo = new Map<number, IsometricTileInfo[]>();

constructor(public tiledTileLayer: TiledTileLayer, public resource: TiledResource, public readonly order: number) {
this.name = tiledTileLayer.name;
this.class = tiledTileLayer.class;
Expand All @@ -52,6 +56,52 @@ export class IsoTileLayer implements Layer {
mapProps(this, tiledTileLayer.properties);
}

/**
* Returns the excalibur tiles that match a tiled gid
*/
getTilesByGid(gid: number): IsometricTileInfo[] {
return this._gidToTileInfo.get(gid) ?? [];
}

/**
* Returns the excalibur tiles that match a tiled class name
* @param className
*/
getTilesByClassName(className: string): IsometricTileInfo[] {
const tiles = this.isometricMap.tiles.filter(t => {
const maybeTiled = t.data.get(ExcaliburTiledProperties.TileData.Tiled) as Tile | undefined;
if (maybeTiled) {
return byClassCaseInsensitive(className)(maybeTiled);
}
return false;
});

return tiles.map(t => ({
exTile: t,
tiledTile: t.data.get(ExcaliburTiledProperties.TileData.Tiled)
}))
}

/**
* Returns the excalibur tiles that match a tiled property and optional value
* @param name
* @param value
*/
getTilesByProperty(name: string, value?: any): IsometricTileInfo[] {
const tiles = this.isometricMap.tiles.filter(t => {
const maybeTiled = t.data.get(ExcaliburTiledProperties.TileData.Tiled) as Tile | undefined;
if (maybeTiled) {
return byPropertyCaseInsensitive(name, value)(maybeTiled);
}
return false;
});

return tiles.map(t => ({
exTile: t,
tiledTile: t.data.get(ExcaliburTiledProperties.TileData.Tiled)
}))
}

getTileByPoint(worldPos: Vector): IsometricTileInfo | null {
if (!this.isometricMap) {
this.logger.warn('IsometricMap has not yet been loaded! getTileByPoint() will only return null');
Expand All @@ -75,7 +125,21 @@ export class IsoTileLayer implements Layer {
return null;
}

private _recordTileData(gid: number, tile: IsometricTile) {
let tiles: IsometricTileInfo[] | undefined = this._gidToTileInfo.get(gid);
let tileset = this.resource.getTilesetForTileGid(gid);
let maybeTile = tileset.getTileByGid(gid);
if (!tiles) {
tiles = [{exTile: tile, tiledTile: maybeTile}];
} else {
tiles.push({exTile: tile, tiledTile: maybeTile});
}
this._gidToTileInfo.set(gid, tiles);
tile.data.set(ExcaliburTiledProperties.TileData.Tiled, maybeTile);
}

private updateTile(tile: IsometricTile, gid: number, hasTint: boolean, tint: Color, isSolidLayer: boolean) {
this._recordTileData(gid, tile);
if (this.resource.useExcaliburWiring && isSolidLayer) {
tile.solid = true;
}
Expand Down Expand Up @@ -105,7 +169,7 @@ export class IsoTileLayer implements Layer {

// the whole tilemap uses a giant composite collider relative to the Tilemap
// not individual tiles
const colliders = tileset.getCollidersForGid(gid, {offset});
const colliders = tileset.getCollidersForGid(gid, { offset });
for (let collider of colliders) {
tile.addCollider(collider);
}
Expand Down Expand Up @@ -168,7 +232,7 @@ export class IsoTileLayer implements Layer {
if (typeof zoverride === 'number') {
order = zoverride;
}



if (this.resource.map.infinite && isInfiniteLayer(this.tiledTileLayer)) {
Expand Down
Loading

0 comments on commit 2bd697f

Please sign in to comment.