mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-08-27 03:01:28 -04:00
77320ce12e
* Tilemaps made with [LDtk](https://ldtk.io/), a modern 2D level editor, can be now used directly. Make sure to save your map made in LDtk as a JSON file, create a new Tilemap object in GDevelop and in the Tilemap field, choose the LDtk file. * Tilesets used by the LDtk Tilemap are automatically imported in your game - you don't need to import them separately. * For more information, read about the [Tilemap object on the wiki](https://wiki.gdevelop.io/gdevelop5/objects/tilemap). Co-authored-by: Davy Hélard <davy.helard@gmail.com> Co-authored-by: Florian Rival <Florian.Rival@gmail.com>
164 lines
5.7 KiB
TypeScript
164 lines
5.7 KiB
TypeScript
/// <reference path="helper/TileMapHelper.d.ts" />
|
|
namespace gdjs {
|
|
export interface RuntimeInstanceContainer {
|
|
tileMapCollisionMaskManager: gdjs.TileMap.TileMapRuntimeManager;
|
|
}
|
|
export namespace TileMap {
|
|
import PIXI = GlobalPIXIModule.PIXI;
|
|
|
|
const logger = new gdjs.Logger('Tilemap object');
|
|
|
|
/**
|
|
* A holder to share tile maps across the 2 extension objects.
|
|
*
|
|
* Every instance with the same files path in properties will
|
|
* share the same {@link EditableTileMap} and {@link TileTextureCache}.
|
|
*
|
|
* To use a tile map with collisions, a user can create 4 objects:
|
|
* - one for the the rendering
|
|
* - one for the solid platforms
|
|
* - one for the jumpthrus
|
|
* - one for the ladders
|
|
*
|
|
* To avoid to have 4 copies of the same tile map in memory, this manager
|
|
* puts the tile map in cache and avoid unnecessary parsing.
|
|
*
|
|
* @see {@link TileMapManager}
|
|
*/
|
|
export class TileMapRuntimeManager {
|
|
private _instanceContainer: gdjs.RuntimeInstanceContainer;
|
|
/**
|
|
* Delegate that actually manage the caches without anything specific to
|
|
* GDJS.
|
|
* It allows to factorize code with the IDE.
|
|
*/
|
|
private _manager: TileMapHelper.TileMapManager;
|
|
/**
|
|
* @param instanceContainer The instance container.
|
|
*/
|
|
private constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
|
this._instanceContainer = instanceContainer;
|
|
this._manager = new TileMapHelper.TileMapManager();
|
|
}
|
|
|
|
/**
|
|
* @param instanceContainer Where to set the manager instance.
|
|
* @returns The shared manager.
|
|
*/
|
|
static getManager(
|
|
instanceContainer: gdjs.RuntimeInstanceContainer
|
|
): TileMapRuntimeManager {
|
|
if (!instanceContainer.tileMapCollisionMaskManager) {
|
|
// Create the shared manager if necessary.
|
|
instanceContainer.tileMapCollisionMaskManager = new TileMapRuntimeManager(
|
|
instanceContainer
|
|
);
|
|
}
|
|
return instanceContainer.tileMapCollisionMaskManager;
|
|
}
|
|
|
|
/**
|
|
* @param tileMapJsonResourceName The resource name of the tile map.
|
|
* @param tileSetJsonResourceName The resource name of the tile set.
|
|
* @param levelIndex The level of the tile map.
|
|
* @param callback A function called when the tile map is parsed.
|
|
*/
|
|
getOrLoadTileMap(
|
|
tileMapJsonResourceName: string,
|
|
tileSetJsonResourceName: string,
|
|
levelIndex: number,
|
|
callback: (tileMap: TileMapHelper.EditableTileMap | null) => void
|
|
): void {
|
|
this._manager.getOrLoadTileMap(
|
|
this._loadTileMap.bind(this),
|
|
tileMapJsonResourceName,
|
|
tileSetJsonResourceName,
|
|
levelIndex,
|
|
pako,
|
|
callback
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param getTexture The method that loads the atlas image file in memory.
|
|
* @param atlasImageResourceName The resource name of the atlas image.
|
|
* @param tileMapJsonResourceName The resource name of the tile map.
|
|
* @param tileSetJsonResourceName The resource name of the tile set.
|
|
* @param levelIndex The level of the tile map.
|
|
* @param callback A function called when the tiles textures are split.
|
|
*/
|
|
getOrLoadTextureCache(
|
|
getTexture: (textureName: string) => PIXI.BaseTexture<PIXI.Resource>,
|
|
atlasImageResourceName: string,
|
|
tileMapJsonResourceName: string,
|
|
tileSetJsonResourceName: string,
|
|
levelIndex: number,
|
|
callback: (textureCache: TileMapHelper.TileTextureCache | null) => void
|
|
): void {
|
|
this._manager.getOrLoadTextureCache(
|
|
this._loadTileMap.bind(this),
|
|
getTexture,
|
|
atlasImageResourceName,
|
|
tileMapJsonResourceName,
|
|
tileSetJsonResourceName,
|
|
levelIndex,
|
|
callback
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Parse both JSON and set the content of the tile set in the right
|
|
* attribute in the tile map to merge both parsed data.
|
|
*/
|
|
private _loadTileMap(
|
|
tileMapJsonResourceName: string,
|
|
tileSetJsonResourceName: string,
|
|
callback: (tileMap: TileMapHelper.TileMap | null) => void
|
|
): void {
|
|
this._instanceContainer
|
|
.getGame()
|
|
.getJsonManager()
|
|
.loadJson(tileMapJsonResourceName, (error, tileMapJsonData) => {
|
|
if (error) {
|
|
logger.error(
|
|
'An error happened while loading a Tilemap JSON data:',
|
|
error
|
|
);
|
|
callback(null);
|
|
return;
|
|
}
|
|
const tileMap = TileMapHelper.TileMapManager.identify(
|
|
tileMapJsonData
|
|
);
|
|
if (!tileMap) {
|
|
callback(null);
|
|
return;
|
|
}
|
|
if (tileMap.kind === 'tiled' && tileSetJsonResourceName) {
|
|
this._instanceContainer
|
|
.getGame()
|
|
.getJsonManager()
|
|
.loadJson(tileSetJsonResourceName, (error, tileSetJsonData) => {
|
|
if (error) {
|
|
logger.error(
|
|
'An error happened while loading Tileset JSON data:',
|
|
error
|
|
);
|
|
callback(null);
|
|
return;
|
|
}
|
|
const tiledMap = tileMap.data;
|
|
const tileSet = tileSetJsonData as TileMapHelper.TiledTileset;
|
|
tileSet.firstgid = tiledMap.tilesets[0].firstgid;
|
|
tiledMap.tilesets = [tileSet];
|
|
callback(tileMap);
|
|
});
|
|
} else {
|
|
callback(tileMap);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|