Files
GDevelop/SharedLibs/TileMapHelper/src/load/tiled/TiledTileMapLoaderHelper.ts
T
Baptiste Augrain 77320ce12e Add support for LDtk Tilemaps (#4575)
* 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>
2022-12-22 18:44:27 +01:00

112 lines
3.1 KiB
TypeScript

import {
FLIPPED_DIAGONALLY_FLAG,
FLIPPED_HORIZONTALLY_FLAG,
FLIPPED_VERTICALLY_FLAG,
} from "../../model/GID";
import { integer } from "../../model/CommonTypes";
import { TiledLayer } from "./TiledFormat";
/**
* Decodes a layer data, which can sometimes be store as a compressed base64 string
* by Tiled.
* See https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#data.
* @param pako The zlib library.
* @param tiledLayer The layer data from a Tiled JSON.
* @returns The decoded layer data.
*/
export const decodeBase64LayerData = (pako: any, tiledLayer: TiledLayer) => {
const { data, compression } = tiledLayer;
const dataBase64 = data as string;
if (!dataBase64) {
// The layer data is not encoded.
return data as number[];
}
let index = 4;
const decodedData: integer[] = [];
let step1 = atob(dataBase64)
.split("")
.map(function (x) {
return x.charCodeAt(0);
});
try {
const decodeArray = (arr: integer[] | Uint8Array, index: integer) =>
(arr[index] +
(arr[index + 1] << 8) +
(arr[index + 2] << 16) +
(arr[index + 3] << 24)) >>>
0;
if (compression === "zlib") {
const binData = new Uint8Array(step1);
const decompressedData = pako.inflate(binData);
while (index <= decompressedData.length) {
decodedData.push(decodeArray(decompressedData, index - 4));
index += 4;
}
} else if (compression === "zstd") {
console.error(
"Zstandard compression is not supported for layers in a Tilemap. Use instead zlib compression or no compression."
);
return null;
} else {
while (index <= step1.length) {
decodedData.push(decodeArray(step1, index - 4));
index += 4;
}
}
return decodedData;
} catch (error) {
console.error(
"Failed to decompress and unzip base64 layer.data string",
error
);
return null;
}
};
export type TiledGID = {
id: integer;
flippedHorizontally: boolean;
flippedVertically: boolean;
flippedDiagonally: boolean;
};
/**
* Extract information about the rotation of a tile from the tile id.
* @param globalTileUid The Tiled tile global uniq identifier.
* @returns The tile identifier and orientation.
*/
export const extractTileUidFlippedStates = (
globalTileUid: integer
): TiledGID => {
const flippedHorizontally = globalTileUid & FLIPPED_HORIZONTALLY_FLAG;
const flippedVertically = globalTileUid & FLIPPED_VERTICALLY_FLAG;
const flippedDiagonally = globalTileUid & FLIPPED_DIAGONALLY_FLAG;
const tileUid = getTileIdFromTiledGUI(
globalTileUid &
~(
FLIPPED_HORIZONTALLY_FLAG |
FLIPPED_VERTICALLY_FLAG |
FLIPPED_DIAGONALLY_FLAG
)
);
return {
id: tileUid,
flippedHorizontally: !!flippedHorizontally,
flippedVertically: !!flippedVertically,
flippedDiagonally: !!flippedDiagonally,
};
};
/**
* Tiled use 0 as null, we do too but it's black boxed.
* This is why the id needs to be decremented.
* @return the tile identifier.
*/
export function getTileIdFromTiledGUI(
tiledGUI: number | undefined
): number | undefined {
return tiledGUI === 0 ? undefined : tiledGUI - 1;
}