Project export format
File ▸ Export ▸ Export Project writes the whole project as one ZIP archive. Live Sync serves exactly the same files to a running game. This page describes those files so you can load them in your own engine.
Archive layout
Section titled “Archive layout”Map_1.lostproj the manifest, named after the first mapmaps/<name>.lostmap one per maptilesets/<name>.lostset one per tilesetentities/<name>.lostentity one per entityresources/<name>.png tileset imagesindex.json the list of texture sprite sheets and animation filessprites/<name>_<id>.png one sprite sheet per textureanimations/<name>_<id>.lostanim one per textureAn animated tileset also writes resources/<name>_frame<N>.png for each frame. The export is deterministic: the same project always gives the same bytes.
File names
Section titled “File names”A name becomes a file name like this: letters, digits, _ and - are kept, spaces become _, and everything else is dropped. Case is kept, so My Map! becomes My_Map. Names that only differ in case get _2, _3 and so on. A name with nothing left becomes unnamed.
Renaming something in the editor renames its file, so to your game it looks like one file deleted and another added.
Conventions
Section titled “Conventions”- All text files are UTF-8 JSON.
- Positions and sizes are in pixels. X runs right and y runs down.
- Ids are 64-bit integers, such as
4378603846990036993. Read them as 64-bit integers. JavaScript’sJSON.parserounds them, so in Node.js 22 or a Chromium browser, keep them exact with a reviver:
const data = JSON.parse(text, (key, value, { source }) => typeof value === 'number' && !Number.isSafeInteger(value) ? BigInt(source) : value,);The manifest: .lostproj
Section titled “The manifest: .lostproj”Lists every other file and the project’s physics layers.
{ "version": "2.1", "name": "Map 1", "hash": null, "lastModified": "live", "resources": { "tilesets": ["tilesets/Ground.lostset", "tilesets/Tiles.lostset"], "maps": ["maps/Map_1.lostmap"], "entities": ["entities/Coin.lostentity"] }, "physicsLayers": [{ "index": 0, "name": "Default", "collidesWith": [0] }]}physicsLayers comes from Project Settings ▸ Physics. Colliders refer to a layer by its index.
Maps: .lostmap
Section titled “Maps: .lostmap”{ "version": "7.2", "id": 4378603846990036993, "name": "Map 1", "layers": [ ... ], "entities": [ ... ], "points": [ ... ], "colliders": [ ... ]}Layers
Section titled “Layers”layers is in draw order, back to front. Layer groups from the editor are flattened out. Every layer has id, name, type, visible, order, parallaxX, parallaxY, offsetX, offsetY, tint (r, g, b, a, where a already includes the layer’s opacity), blendMode and properties. type is tile, entity or collision.
A tile layer also has tileWidth, tileHeight and mode:
mode: "grid": tiles are stored inchunksofchunkWidth×chunkHeightcells (8 × 8). The key is the chunk’s position,"cx,cy", and the value is 64 tile ids, row by row. Celliof chunk"cx,cy"is map cell(cx * 8 + i % 8, cy * 8 + floor(i / 8)). A0is an empty cell.mode: "free": tiles are placed anywhere, astiles: [{ "x", "y", "tileId" }]in pixels.
Tile ids
Section titled “Tile ids”A tile id packs a tile’s place in a tileset into one number:
| Bits | Meaning |
|---|---|
| 0–15 | x of the tile in the tileset image, in pixels |
| 16–31 | y of the tile in the tileset image, in pixels |
| 32–45 | the tileset’s order, from its .lostset (tilesets are numbered from 1 by name) |
| 46 | flipped horizontally |
| 47 | flipped vertically |
Tile ids stay below 2⁵³, so plain numbers are safe in JavaScript. Use division rather than bit operators, which only work on 32 bits:
function decodeTile(id) { return { x: id % 65536, y: Math.floor(id / 65536) % 65536, tileset: Math.floor(id / 2 ** 32) % 2 ** 14, flipX: Math.floor(id / 2 ** 46) % 2 === 1, flipY: Math.floor(id / 2 ** 47) % 2 === 1, };}
decodeTile(4294967296); // { x: 0, y: 0, tileset: 1, ... }: the top-left tile of tileset 1Entities on a map
Section titled “Entities on a map”Each item in entities is one placed entity:
{ "id": 9, "name": "", "entityDefId": 2, "layerId": 4, "x": 64, "y": 32, "rotation": 0, "flipX": false, "flipY": false, "scale": { "x": 1, "y": 1 }, "zIndex": 0, "properties": { "value": "5" }, "refs": {}}entityDefId is the id of an entity’s .lostentity file. properties only holds the values changed on this instance; everything else is the entity’s default. Property values are written as strings, even numbers and booleans: convert them with the property’s type from the .lostentity.
Points and colliders
Section titled “Points and colliders”points are named positions, with x, y, name, type, nodes (for paths) and properties. colliders are polygons: position is the centre and points are relative to it, plus name, type, physicsLayer and properties.
Tilesets: .lostset
Section titled “Tilesets: .lostset”{ "version": "1.0", "id": 4378603846990036994, "name": "Ground", "order": 1, "imagePath": "resources/Ground.png", "textureId": 4378603846990036995, "tileWidth": 16, "tileHeight": 16, "tiles": [], "terrainLayers": []}tiles only lists tiles that carry extra data from the tileset editor: a name, type, colliders, properties or animation frames. order is the number used in tile ids.
Entities: .lostentity
Section titled “Entities: .lostentity”An entity has id, name, type, sprites, colliders and properties. Each property is defined as { "name": "value", "type": "integer", "default": "1", "options": [] }: type is one of string, number, integer, float, boolean, enum, color and ref, and options lists an enum’s choices. Each sprite has its source and how it is drawn:
- From a tileset:
tilesetIdandrect(x,y,width,heightin the tileset image). - From a texture:
textureIdandanimation, which point into the sprite sheets below. - Placement:
offset,origin,scale,rotation,panX,panY,tint,blendModeandzIndex. name,typeandmask, as set on the sprite in the entity editor.
Textures and animations
Section titled “Textures and animations”index.json lists one sprite sheet per texture and its animation file:
{ "name": "Textures", "resources": [{ "id": "tex_4378603846990036997", "name": "Coin", "path": "sprites/Coin_4378603846990036997.png", "tileWidth": 16, "tileHeight": 16, "imageWidth": 12, "imageHeight": 12, "packed": true }], "animationFiles": [{ "name": "Coin", "path": "animations/Coin_4378603846990036997.lostanim" }]}A .lostanim holds the texture’s animations. Each has a name, loop, durationMs and tracks. A sprite track lists keys: at timeMs, draw rect from the sprite sheet named by spritesheetId.
With Project Settings ▸ Pack sprite sheets on (the default), frames are trimmed to their pixels and identical frames are stored once. That is why the 16 × 16 coin above has a 12 × 12 sheet. rect is where the trimmed frame sits in the sheet, and trim is where it goes inside the full tileWidth × tileHeight frame. With it off, the sheet is a plain grid with one cell per frame.
