├── .github
├── FUNDING.yml
└── workflows
│ └── unitTests.yml
├── .gitignore
├── .vscode
├── commandbar.json
├── launch.json
├── settings.json
└── tasks.json
├── LICENSE
├── README.md
├── haxelib.json
├── samples
├── Flixel - Render tile layer
│ ├── .vscode
│ │ ├── launch.json
│ │ └── tasks.json
│ ├── Project.xml
│ └── src
│ │ ├── Main.hx
│ │ └── PlayState.hx
├── Generic - Read project
│ ├── ReadProject.hx
│ ├── build.hxml
│ └── index.html
├── Heaps - Object tiles
│ ├── Heaps_ObjectTiles.hx
│ ├── build.hxml
│ └── index.html
├── Heaps - Render IntGrid layer
│ ├── Heaps_IntGrid.hx
│ ├── build.hxml
│ └── index.html
├── Heaps - Render full world
│ ├── Heaps_FullWorld.hx
│ ├── build.hxml
│ └── index.html
├── Heaps - Render tile layers
│ ├── Heaps_TileLayers.hx
│ ├── build.hxml
│ └── index.html
├── _assets
│ ├── Cavernas_by_Adam_Saltsman-Extended.png
│ ├── Cavernas_by_Adam_Saltsman-Extended_hued.png
│ ├── Minecraft_texture_pack.gif
│ ├── N2D - SpaceWallpaper1280x448.png
│ ├── RPG_Assets_by_ssugmi.png
│ ├── sample.cdb
│ ├── sample.ldtk
│ ├── sample
│ │ ├── 0000-West.ldtkl
│ │ ├── 0001-East.ldtkl
│ │ ├── 0002-Pit.ldtkl
│ │ ├── 0003-Treasure_room.ldtkl
│ │ └── png
│ │ │ ├── East.png
│ │ │ ├── Pit.png
│ │ │ ├── Treasure_room.png
│ │ │ └── West.png
│ ├── unitTest.ldtk
│ └── unitTest
│ │ ├── Main_tests.ldtkl
│ │ ├── Offset_tests.ldtkl
│ │ ├── Target_level_ref.ldtkl
│ │ ├── World1_Level_3.ldtkl
│ │ ├── World2_Level_0.ldtkl
│ │ ├── v1_4_0.ldtkl
│ │ └── v1_4_0_overlap.ldtkl
├── _initSamples
│ ├── README.md
│ ├── SamplesInitializer.hx
│ └── initSamples.hxml
├── _srcCommon
│ ├── ExternCastleDbTest.hx
│ ├── ExternEnumTest.hx
│ └── LdtkProject.hx
└── buildAll.hxml
├── src
└── ldtk
│ ├── Entity.hx
│ ├── Json.hx
│ ├── Layer.hx
│ ├── Layer_AutoLayer.hx
│ ├── Layer_Entities.hx
│ ├── Layer_IntGrid.hx
│ ├── Layer_IntGrid_AutoLayer.hx
│ ├── Layer_Tiles.hx
│ ├── Level.hx
│ ├── Point.hx
│ ├── Project.hx
│ ├── Tileset.hx
│ ├── World.hx
│ └── macro
│ └── TypeBuilder.hx
├── tests
├── ProjectNoPackage.hx
├── Tests.hx
├── _base.hxml
├── hl.hxml
├── js.hxml
├── lab
│ ├── .gitignore
│ ├── .vscode
│ │ ├── launch.json
│ │ └── tasks.json
│ ├── README.md
│ ├── hl.hxml
│ ├── res
│ │ ├── Cavernas_by_Adam_Saltsman-Extended.png
│ │ └── apiLab.ldtk
│ └── src
│ │ ├── Boot.hx
│ │ ├── LdtkProject.hx
│ │ └── Main.hx
└── packageTest
│ └── ProjectPackage.hx
└── tidy.cmd
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: deepnight
--------------------------------------------------------------------------------
/.github/workflows/unitTests.yml:
--------------------------------------------------------------------------------
1 | name: Unit tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - dev*
8 | pull_request:
9 | branches:
10 | - master
11 | - dev*
12 |
13 | jobs:
14 | build:
15 |
16 | strategy:
17 | matrix:
18 | os: [windows-latest]
19 | haxe: [4.3.3]
20 | fail-fast: true
21 | runs-on: windows-latest
22 |
23 | steps:
24 | # Checkout & install haxe
25 | - uses: actions/checkout@v2
26 | - uses: krdlab/setup-haxe@v1
27 | with:
28 | haxe-version: ${{ matrix.haxe }}
29 | - run: haxe -version
30 |
31 | # Install libs
32 | - run: haxelib install tests/js.hxml --always
33 | - run: haxelib git deepnightLibs https://github.com/deepnight/deepnightLibs.git
34 | - run: haxelib git heaps https://github.com/deepnight/heaps.git
35 | - run: haxelib git hlsdl https://github.com/HaxeFoundation/hashlink.git master libs/sdl
36 | - run: haxelib list
37 |
38 | # Run tests
39 | - name: JS tests
40 | run: haxe tests/js.hxml
41 |
42 | # Samples
43 | - name: Samples building
44 | working-directory: ./samples/_initSamples
45 | run: haxe initSamples.hxml
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.vscode/extensions.json
2 | bin
3 | dump
4 | *.hl
5 | *.js
6 |
--------------------------------------------------------------------------------
/.vscode/commandbar.json:
--------------------------------------------------------------------------------
1 | {
2 | "skipTerminateQuickPick": true,
3 | "skipSwitchToOutput": false,
4 | "skipErrorMessage": true,
5 | "commands": [
6 | {
7 | "text": "JS",
8 | "color": "#cfdd40",
9 | "command": "haxe tests/js.hxml",
10 | "alignment": "right",
11 | "skipTerminateQuickPick": false,
12 | "priority": 0
13 | },
14 | {
15 | "text": "HL",
16 | "color": "#1edd8e",
17 | "command": "haxe tests/hl.hxml",
18 | "alignment": "right",
19 | "skipTerminateQuickPick": false,
20 | "priority": -1
21 | },
22 | {
23 | "text": "Samples",
24 | "color": "#ff8600",
25 | "command": "cd samples && cd _initSamples && haxe initSamples.hxml",
26 | "alignment": "right",
27 | "skipTerminateQuickPick": false,
28 | "priority": -21
29 | },
30 | {
31 | "text": "🖥️ Term",
32 | "color": "#aaaaaa",
33 | "command": "start /d samples cmd",
34 | "alignment": "right",
35 | "skipTerminateQuickPick": false,
36 | "priority": -30
37 | },
38 | {
39 | "text": "➠ Submit to haxelib",
40 | "color": "white",
41 | "command": "start haxelib submit .",
42 | "alignment": "right",
43 | "skipTerminateQuickPick": false,
44 | "priority": -40
45 | }
46 |
47 | ]
48 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Debug macros",
9 | "type": "haxe-eval",
10 | "request": "launch",
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "haxe.configurations": [
3 | ["tests/hl.hxml"],
4 | ["tests/js.hxml"],
5 | ["tests/neko.hxml"],
6 | ],
7 | "haxe.enableServerView": true
8 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "haxe",
8 | "args": "active configuration",
9 | "problemMatcher": [
10 | "$haxe-absolute",
11 | "$haxe",
12 | "$haxe-error",
13 | "$haxe-trace"
14 | ],
15 | "group": {
16 | "kind": "build",
17 | "isDefault": true
18 | },
19 | "presentation": {
20 | "reveal": "never",
21 | "panel": "dedicated",
22 | "clear": true
23 | },
24 | "label": "haxe: active configuration"
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020, Sébastien Benard - Deepnight Games
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # About
2 |
3 | ## What is this?
4 |
5 | This is the Haxe API to load **LDtk Project JSON** files.
6 |
7 | *LDtk is a modern and open-source 2D level editor.*
8 |
9 | [Issue tracker (shared)](https://github.com/deepnight/ldtk/issues) |
10 | [API documentation](https://ldtk.io/docs/game-dev/haxe-in-game-api/) |
11 | [LDtk official page](https://ldtk.io)
12 |
13 | [](https://github.com/deepnight/ldtk-haxe-api/actions/workflows/unitTests.yml)
14 |
15 | ## Features
16 |
17 | - Compatible with all Haxe based frameworks and engines.
18 | - Dedicated API for the following frameworks:
19 | - Heaps.io
20 | - [HaxeFlixel](https://haxeflixel.com/)
21 | - **Completely typed at compilation**: if you rename any element in your project (ie. level, layer, entity, etc.), the corresponding references in your code will break accordingly, avoiding typical errors or mistypings.
22 | - **Full completion in VScode**: if you have vs-haxe installed, you will get full completion while exploring your project file, based on its actual content, right from VScode.
23 |
24 | # Usage
25 |
26 | ## Install
27 |
28 | ```
29 | haxelib install ldtk-haxe-api
30 | ```
31 | ## Documentation
32 |
33 | Please check the **full documentation and tutorials** here:
34 |
35 | https://deepnight.net/docs/ldtk/haxe-api/
36 |
37 | ## Samples
38 |
39 | You can check some examples in [samples](samples) folder.
40 |
41 | Samples are built to **WebGL** (Javascript) and **Hashlink** targets, but you can try them on other compatible platforms too.
42 |
43 | ### Requirements
44 |
45 | You need a standard **Haxe** install, and the following libraries installed: *heaps* (from source), *deepnightLibs* (from source), *hlsdl*:
46 |
47 | ```
48 | haxelib git heaps https://github.com/HeapsIO/heaps.git
49 |
50 | haxelib git deepnightLibs https://github.com/deepnight/deepnightLibs.git
51 |
52 | haxelib install hlsdl
53 | ```
54 |
55 | ### Building samples
56 |
57 | Open a folder in the `samples` folder (eg. `samples\Generic - Generic - Read project`) and run:
58 |
59 | ```
60 | haxe build.hxml
61 | ```
62 |
63 | You can also build all samples in one go. Go in `samples` folder and run:
64 |
65 | ```
66 | haxe buildAll.hxml
67 | ```
68 |
69 | ### Rebuild samples HXMLs
70 |
71 | If you modify the API, you might need to rebuild samples `HXML`s files themselves. In the root of the repo, run:
72 |
73 | ```
74 | haxe genSamples.hxml
75 | ```
76 |
77 | ## Unit tests
78 |
79 | You can build and run unit tests manually using the following commands **from the repository root**.
80 |
81 | ### JS/WebGL target
82 |
83 | You will need Node interpreter to run the tests.
84 |
85 | ```
86 | haxe tests\js.hxml
87 | ```
88 |
89 | ### Neko target
90 |
91 | You will need Neko VM interpreter to run the tests.
92 |
93 | ```
94 | haxe tests\neko.hxml
95 | ```
96 |
--------------------------------------------------------------------------------
/haxelib.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ldtk-haxe-api",
3 | "url" : "https://github.com/deepnight/ldtk-haxe-api",
4 | "license": "Apache",
5 | "tags": ["Haxe","Heaps","Hashlink","LDtk","Led","L-Ed","api","level","editor","deepnight"],
6 | "description": "The haxe API for LDtk JSON files - https://deepnight.net/tools/led-2d-level-editor/",
7 | "version": "1.5.3-rc.1",
8 | "classPath": "src/",
9 | "releasenote": "See https://ldtk.io/ for more information",
10 | "contributors": ["sbenard"],
11 | "dependencies": {
12 | "deepnightLibs": ""
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/samples/Flixel - Render tile layer/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Build + Debug",
6 | "type": "lime",
7 | "request": "launch"
8 | },
9 | {
10 | "name": "Debug",
11 | "type": "lime",
12 | "request": "launch",
13 | "preLaunchTask": null
14 | },
15 | {
16 | "name": "Macro",
17 | "type": "haxe-eval",
18 | "request": "launch"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/samples/Flixel - Render tile layer/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "type": "lime",
6 | "command": "test",
7 | "presentation": {
8 | "echo": true,
9 | "reveal": "never",
10 | "focus": false,
11 | "panel": "shared",
12 | "showReuseMessage": false,
13 | "clear": false
14 | },
15 | "group": {
16 | "kind": "build",
17 | "isDefault": true
18 | }
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/samples/Flixel - Render tile layer/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/samples/Flixel - Render tile layer/src/Main.hx:
--------------------------------------------------------------------------------
1 | package;
2 |
3 | import flixel.FlxGame;
4 | import openfl.display.Sprite;
5 |
6 | class Main extends Sprite
7 | {
8 | public function new()
9 | {
10 | super();
11 | addChild(new FlxGame(800, 400, PlayState));
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/samples/Flixel - Render tile layer/src/PlayState.hx:
--------------------------------------------------------------------------------
1 | package;
2 |
3 | import flixel.FlxG;
4 | import flixel.FlxState;
5 |
6 | class PlayState extends FlxState
7 | {
8 | override public function create()
9 | {
10 | super.create();
11 |
12 | // Create project instance
13 | var project = new LdtkProject();
14 |
15 |
16 | // Iterate all world levels
17 | for( level in project.all_worlds.SampleWorld.levels ) {
18 | // Create a FlxGroup for all level layers
19 | var container = new flixel.group.FlxSpriteGroup();
20 | add(container);
21 |
22 | // Place it using level world coordinates (in pixels)
23 | container.x = level.worldX;
24 | container.y = level.worldY;
25 |
26 | // Attach level background image, if any
27 | if( level.hasBgImage() )
28 | container.add( level.getBgSprite() );
29 |
30 | // Render layer "Background"
31 | level.l_Cavern_background.render( container );
32 |
33 | // Render layer "Collisions"
34 | level.l_Collisions.render( container );
35 |
36 | // Render layer "Custom_Tiles"
37 | level.l_Custom_tiles.render( container );
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/samples/Generic - Read project/ReadProject.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This sample shows how to access some of the Project data using Haxe API.
3 | **/
4 |
5 | import ExternEnumTest;
6 |
7 | class ReadProject {
8 | static function main() {
9 | hxd.Res.initEmbed();
10 | var project = new LdtkProject();
11 |
12 | var myLevel = project.all_worlds.SampleWorld.all_levels.West;
13 |
14 | // IntGrid ASCII render
15 | var layer = myLevel.l_Collisions;
16 | for( cy in 0...layer.cHei ) {
17 | var row = "";
18 | for( cx in 0...layer.cWid )
19 | if( layer.hasValue(cx,cy) )
20 | row+="#";
21 | else
22 | row+=".";
23 | print(row+" "+cy);
24 | }
25 |
26 | // Entity access
27 | for( playerEntity in myLevel.l_Entities.all_Player )
28 | print( "Found: "+playerEntity.identifier );
29 |
30 | for( itemEntity in myLevel.l_Entities.all_Item ) {
31 | print( "Found: "+itemEntity.identifier );
32 | print( " type = "+itemEntity.f_type );
33 |
34 | var displayName = switch itemEntity.f_type {
35 | case Pickaxe: 'A rusty pickaxe';
36 | case Potion: 'A fresh vial of Healing potion';
37 | case Food: 'Some tasty food';
38 | }
39 | print(' "$displayName"');
40 | }
41 | }
42 |
43 |
44 |
45 |
46 | /**
47 | Print some text
48 | **/
49 | #if js
50 | static var _htmlLog : js.html.Element;
51 | #end
52 |
53 | static function print(msg:String) {
54 | #if sys
55 |
56 | Sys.println(msg);
57 |
58 | #elseif js
59 |
60 | if( _htmlLog==null ) {
61 | // Hide HTML canvas
62 | js.Browser.document.querySelector("canvas").remove();
63 |
64 | // Create a PRE element to display text
65 | _htmlLog = js.Browser.document.createPreElement();
66 | js.Browser.document.body.appendChild(_htmlLog);
67 | _htmlLog.style.marginLeft = "16px";
68 | _htmlLog.innerText = "CONSOLE OUTPUT:\n\n";
69 | }
70 | _htmlLog.append(msg+"\n");
71 | js.html.Console.info(msg);
72 |
73 | #else
74 |
75 | trace(msg);
76 |
77 | #end
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/samples/Generic - Read project/build.hxml:
--------------------------------------------------------------------------------
1 |
2 | # ReadProject (Javascript/WebGL)
3 | -cp .
4 | -cp ../_srcCommon
5 | -cp ../../src
6 | -lib heaps
7 | -lib deepnightLibs
8 | -D resourcesPath=../_assets
9 | --dce full
10 | -main ReadProject
11 | -js _javascript.js
12 |
13 | # ReadProject (Hashlink)
14 | --next
15 | -cp .
16 | -cp ../_srcCommon
17 | -cp ../../src
18 | -lib heaps
19 | -lib deepnightLibs
20 | -D resourcesPath=../_assets
21 | -lib hlsdl
22 | --dce full
23 | -main ReadProject
24 | -hl _hashlink.hl
25 |
--------------------------------------------------------------------------------
/samples/Generic - Read project/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ReadProject
7 |
50 |
51 |
52 |
53 |
54 | Failed to load JS script! Please build it using the HXML file (run: haxe build.hxml
).
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/samples/Heaps - Object tiles/Heaps_ObjectTiles.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This sample for Heaps.io engine demonstrates how to render any layer using the
3 | provided render() method.
4 | **/
5 |
6 | import LdtkProject;
7 |
8 | class Heaps_ObjectTiles extends hxd.App {
9 |
10 | static function main() {
11 | // Boot
12 | new Heaps_ObjectTiles();
13 | }
14 |
15 | override function init() {
16 | super.init();
17 |
18 | // Init general heaps stuff
19 | hxd.Res.initEmbed();
20 | s2d.setScale( dn.heaps.Scaler.bestFit_i(256,256) ); // scale view to fit
21 |
22 | // Read project JSON
23 | var project = new LdtkProject();
24 |
25 | // Get level data
26 | var level = project.all_worlds.SampleWorld.all_levels.West;
27 |
28 | // Prepare a container for the level layers
29 | var levelBg = new h2d.Object();
30 | s2d.addChild(levelBg);
31 | levelBg.alpha = 0.5; // opacity
32 | levelBg.filter = new h2d.filter.Blur(4,1,2); // blur it a little bit
33 |
34 | // Render IntGrid layer named "Collisions"
35 | levelBg.addChild( level.l_Collisions.render() );
36 |
37 | // Render tiles layer named "Custom_tiles"
38 | levelBg.addChild( level.l_Custom_tiles.render() );
39 |
40 |
41 | // Render each "Item" entity
42 | for( item in level.l_Entities.all_Item ) {
43 | // Read h2d.Tile based on the "type" enum value from the entity
44 | var tile = project.getEnumTile( item.f_type );
45 |
46 | // Apply the same pivot coord as the Entity to the Tile
47 | // (in this case, the pivot is the bottom-center point of the tile)
48 | tile.setCenterRatio( item.pivotX, item.pivotY );
49 |
50 | // Display it
51 | var bitmap = new h2d.Bitmap(tile);
52 | s2d.addChild(bitmap);
53 | bitmap.x = item.pixelX;
54 | bitmap.y = item.pixelY;
55 | }
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/samples/Heaps - Object tiles/build.hxml:
--------------------------------------------------------------------------------
1 |
2 | # Heaps_ObjectTiles (Javascript/WebGL)
3 | -cp .
4 | -cp ../_srcCommon
5 | -cp ../../src
6 | -lib heaps
7 | -lib deepnightLibs
8 | -D resourcesPath=../_assets
9 | --dce full
10 | -main Heaps_ObjectTiles
11 | -js _javascript.js
12 |
13 | # Heaps_ObjectTiles (Hashlink)
14 | --next
15 | -cp .
16 | -cp ../_srcCommon
17 | -cp ../../src
18 | -lib heaps
19 | -lib deepnightLibs
20 | -D resourcesPath=../_assets
21 | -lib hlsdl
22 | --dce full
23 | -main Heaps_ObjectTiles
24 | -hl _hashlink.hl
25 |
--------------------------------------------------------------------------------
/samples/Heaps - Object tiles/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Heaps_ObjectTiles
7 |
50 |
51 |
52 |
53 |
54 | Failed to load JS script! Please build it using the HXML file (run: haxe build.hxml
).
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/samples/Heaps - Render IntGrid layer/Heaps_IntGrid.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This sample for Heaps.io engine demonstrates how to manually render a "raw" IntGrid layer (ie. "without tiles")
3 | using Heaps API.
4 | **/
5 |
6 | import LdtkProject;
7 |
8 | class Heaps_IntGrid extends hxd.App {
9 | static function main() {
10 | // Boot
11 | new Heaps_IntGrid();
12 | }
13 |
14 | override function init() {
15 | super.init();
16 |
17 | // Init general stuff
18 | hxd.Res.initEmbed();
19 | s2d.setScale( dn.heaps.Scaler.bestFit_i(256,256) ); // scale view to fit
20 |
21 | // Read project JSON
22 | var project = new LdtkProject();
23 |
24 | // Layer data
25 | var layer = project.all_worlds.SampleWorld.all_levels.West.l_Collisions;
26 |
27 | // Prepare a h2d.Graphics to render layer
28 | var g = new h2d.Graphics(s2d);
29 |
30 | // Render background
31 | g.beginFill(project.bgColor_int);
32 | g.drawRect(0, 0, layer.cWid*layer.gridSize, layer.cHei*layer.gridSize);
33 | g.endFill();
34 |
35 | // Render IntGrid layer cells
36 | for(cx in 0...layer.cWid)
37 | for(cy in 0...layer.cHei) {
38 | if( !layer.hasValue(cx,cy) ) // skip empty cells
39 | continue;
40 |
41 | var color = layer.getColorInt(cx,cy);
42 | g.beginFill(color);
43 | g.drawRect(cx*layer.gridSize, cy*layer.gridSize, layer.gridSize, layer.gridSize);
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/samples/Heaps - Render IntGrid layer/build.hxml:
--------------------------------------------------------------------------------
1 |
2 | # Heaps_IntGrid (Javascript/WebGL)
3 | -cp .
4 | -cp ../_srcCommon
5 | -cp ../../src
6 | -lib heaps
7 | -lib deepnightLibs
8 | -D resourcesPath=../_assets
9 | --dce full
10 | -main Heaps_IntGrid
11 | -js _javascript.js
12 |
13 | # Heaps_IntGrid (Hashlink)
14 | --next
15 | -cp .
16 | -cp ../_srcCommon
17 | -cp ../../src
18 | -lib heaps
19 | -lib deepnightLibs
20 | -D resourcesPath=../_assets
21 | -lib hlsdl
22 | --dce full
23 | -main Heaps_IntGrid
24 | -hl _hashlink.hl
25 |
--------------------------------------------------------------------------------
/samples/Heaps - Render IntGrid layer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Heaps_IntGrid
7 |
50 |
51 |
52 |
53 |
54 | Failed to load JS script! Please build it using the HXML file (run: haxe build.hxml
).
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/samples/Heaps - Render full world/Heaps_FullWorld.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This sample for Heaps.io engine demonstrates how to render all layers and all levels in the project world.
3 | **/
4 |
5 | import LdtkProject;
6 |
7 | class Heaps_FullWorld extends hxd.App {
8 |
9 | static function main() {
10 | // Boot
11 | new Heaps_FullWorld();
12 | }
13 |
14 | override function init() {
15 | super.init();
16 |
17 | // Init general heaps stuff
18 | hxd.Res.initEmbed();
19 | s2d.setScale( dn.heaps.Scaler.bestFit_i(650,256) ); // scale view to fit
20 |
21 | // Read project JSON
22 | var project = new LdtkProject();
23 |
24 | // Render each level
25 | for( level in project.all_worlds.SampleWorld.levels ) {
26 | // Create a wrapper to render all layers in it
27 | var levelWrapper = new h2d.Object( s2d );
28 |
29 | // Position accordingly to world pixel coords
30 | levelWrapper.x = level.worldX;
31 | levelWrapper.y = level.worldY;
32 |
33 | // Level background image
34 | if( level.hasBgImage() )
35 | levelWrapper.addChild( level.getBgBitmap() );
36 |
37 | // Render background layer
38 | levelWrapper.addChild( level.l_Cavern_background.render() );
39 |
40 | // Render collision layer tiles
41 | levelWrapper.addChild( level.l_Collisions.render() );
42 |
43 | // Render custom tiles layer
44 | levelWrapper.addChild( level.l_Custom_tiles.render() );
45 | }
46 |
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/samples/Heaps - Render full world/build.hxml:
--------------------------------------------------------------------------------
1 |
2 | # Heaps_FullWorld (Javascript/WebGL)
3 | -cp .
4 | -cp ../_srcCommon
5 | -cp ../../src
6 | -lib heaps
7 | -lib deepnightLibs
8 | -D resourcesPath=../_assets
9 | --dce full
10 | -main Heaps_FullWorld
11 | -js _javascript.js
12 |
13 | # Heaps_FullWorld (Hashlink)
14 | --next
15 | -cp .
16 | -cp ../_srcCommon
17 | -cp ../../src
18 | -lib heaps
19 | -lib deepnightLibs
20 | -D resourcesPath=../_assets
21 | -lib hlsdl
22 | --dce full
23 | -main Heaps_FullWorld
24 | -hl _hashlink.hl
25 |
--------------------------------------------------------------------------------
/samples/Heaps - Render full world/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Heaps_FullWorld
7 |
50 |
51 |
52 |
53 |
54 | Failed to load JS script! Please build it using the HXML file (run: haxe build.hxml
).
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/samples/Heaps - Render tile layers/Heaps_TileLayers.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This sample for Heaps.io engine demonstrates how to render any layer using the
3 | provided render() method.
4 | **/
5 |
6 | import LdtkProject;
7 |
8 | class Heaps_TileLayers extends hxd.App {
9 |
10 | static function main() {
11 | // Boot
12 | new Heaps_TileLayers();
13 | }
14 |
15 | override function init() {
16 | super.init();
17 |
18 | // Init general heaps stuff
19 | hxd.Res.initEmbed();
20 | s2d.setScale( dn.heaps.Scaler.bestFit_i(256,256) ); // scale view to fit
21 |
22 | // Read project JSON
23 | var project = new LdtkProject();
24 |
25 | // Get level data
26 | var level = project.all_worlds.SampleWorld.all_levels.West;
27 |
28 | // Level background image
29 | s2d.addChild( level.getBgBitmap() );
30 |
31 | // Render "pure" auto-layer (ie. background walls)
32 | s2d.addChild( level.l_Cavern_background.render() );
33 |
34 | // Render IntGrid Auto-layer tiles (ie. walls, ladders, etc.)
35 | s2d.addChild( level.l_Collisions.render() );
36 |
37 | // Render traditional Tiles layer (ie. manually added details)
38 | s2d.addChild( level.l_Custom_tiles.render() );
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/samples/Heaps - Render tile layers/build.hxml:
--------------------------------------------------------------------------------
1 |
2 | # Heaps_TileLayers (Javascript/WebGL)
3 | -cp .
4 | -cp ../_srcCommon
5 | -cp ../../src
6 | -lib heaps
7 | -lib deepnightLibs
8 | -D resourcesPath=../_assets
9 | --dce full
10 | -main Heaps_TileLayers
11 | -js _javascript.js
12 |
13 | # Heaps_TileLayers (Hashlink)
14 | --next
15 | -cp .
16 | -cp ../_srcCommon
17 | -cp ../../src
18 | -lib heaps
19 | -lib deepnightLibs
20 | -D resourcesPath=../_assets
21 | -lib hlsdl
22 | --dce full
23 | -main Heaps_TileLayers
24 | -hl _hashlink.hl
25 |
--------------------------------------------------------------------------------
/samples/Heaps - Render tile layers/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Heaps_TileLayers
7 |
50 |
51 |
52 |
53 |
54 | Failed to load JS script! Please build it using the HXML file (run: haxe build.hxml
).
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/samples/_assets/Cavernas_by_Adam_Saltsman-Extended.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/Cavernas_by_Adam_Saltsman-Extended.png
--------------------------------------------------------------------------------
/samples/_assets/Cavernas_by_Adam_Saltsman-Extended_hued.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/Cavernas_by_Adam_Saltsman-Extended_hued.png
--------------------------------------------------------------------------------
/samples/_assets/Minecraft_texture_pack.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/Minecraft_texture_pack.gif
--------------------------------------------------------------------------------
/samples/_assets/N2D - SpaceWallpaper1280x448.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/N2D - SpaceWallpaper1280x448.png
--------------------------------------------------------------------------------
/samples/_assets/RPG_Assets_by_ssugmi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/RPG_Assets_by_ssugmi.png
--------------------------------------------------------------------------------
/samples/_assets/sample.cdb:
--------------------------------------------------------------------------------
1 | {
2 | "sheets": [
3 | {
4 | "name": "CdbEnumTest",
5 | "columns": [
6 | {
7 | "typeStr": "0",
8 | "name": "id"
9 | }
10 | ],
11 | "lines": [
12 | {
13 | "id": "CdbA"
14 | },
15 | {
16 | "id": "CdbB"
17 | },
18 | {
19 | "id": "CdbC"
20 | }
21 | ],
22 | "separators": [],
23 | "props": {}
24 | }
25 | ],
26 | "customTypes": [],
27 | "compress": false
28 | }
--------------------------------------------------------------------------------
/samples/_assets/sample/0003-Treasure_room.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "1.5.3",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "Treasure_room",
12 | "iid": "6004c190-66b0-11ec-a36b-37ad7b095a6c",
13 | "uid": 41,
14 | "worldX": 544,
15 | "worldY": 224,
16 | "worldDepth": 0,
17 | "pxWid": 160,
18 | "pxHei": 128,
19 | "__bgColor": "#121331",
20 | "bgColor": null,
21 | "useAutoIdentifier": false,
22 | "bgRelPath": "N2D - SpaceWallpaper1280x448.png",
23 | "bgPos": "Cover",
24 | "bgPivotX": 0.5,
25 | "bgPivotY": 0.5,
26 | "__smartColor": "#7D7D8E",
27 | "__bgPos": { "topLeftPx": [0,0], "scale": [0.5714285714285714,0.5714285714285714], "cropRect": [180,0,280,224] },
28 | "externalRelPath": null,
29 | "fieldInstances": [],
30 | "layerInstances": [
31 | {
32 | "__identifier": "Entities",
33 | "__type": "Entities",
34 | "__cWid": 20,
35 | "__cHei": 16,
36 | "__gridSize": 8,
37 | "__opacity": 1,
38 | "__pxTotalOffsetX": 0,
39 | "__pxTotalOffsetY": 0,
40 | "__tilesetDefUid": null,
41 | "__tilesetRelPath": null,
42 | "iid": "6004c195-66b0-11ec-a36b-7deaadd71cf6",
43 | "levelId": 41,
44 | "layerDefUid": 28,
45 | "pxOffsetX": 0,
46 | "pxOffsetY": 0,
47 | "visible": true,
48 | "optionalRules": [],
49 | "intGridCsv": [],
50 | "autoLayerTiles": [],
51 | "seed": 7317663,
52 | "overrideTilesetUid": null,
53 | "gridTiles": [],
54 | "entityInstances": [
55 | {
56 | "__identifier": "Item",
57 | "__grid": [10,9],
58 | "__pivot": [0.5,1],
59 | "__tags": [],
60 | "__tile": { "tilesetUid": 31, "x": 0, "y": 0, "w": 16, "h": 16 },
61 | "__smartColor": "#FFDD00",
62 | "iid": "6004c196-66b0-11ec-a36b-230838ef99d1",
63 | "width": 10,
64 | "height": 10,
65 | "defUid": 29,
66 | "px": [84,80],
67 | "fieldInstances": [{ "__identifier": "type", "__type": "LocalEnum.Items", "__value": "Pickaxe", "__tile": { "tilesetUid": 31, "x": 0, "y": 0, "w": 16, "h": 16 }, "defUid": 32, "realEditorValues": [{
68 | "id": "V_String",
69 | "params": ["Pickaxe"]
70 | }] }],
71 | "__worldX": 628,
72 | "__worldY": 304
73 | }
74 | ]
75 | },
76 | {
77 | "__identifier": "Custom_tiles",
78 | "__type": "Tiles",
79 | "__cWid": 20,
80 | "__cHei": 16,
81 | "__gridSize": 8,
82 | "__opacity": 1,
83 | "__pxTotalOffsetX": 0,
84 | "__pxTotalOffsetY": 0,
85 | "__tilesetDefUid": 1,
86 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
87 | "iid": "6004c197-66b0-11ec-a36b-a73c51bcd20e",
88 | "levelId": 41,
89 | "layerDefUid": 34,
90 | "pxOffsetX": 0,
91 | "pxOffsetY": 0,
92 | "visible": true,
93 | "optionalRules": [],
94 | "intGridCsv": [],
95 | "autoLayerTiles": [],
96 | "seed": 5965368,
97 | "overrideTilesetUid": null,
98 | "gridTiles": [],
99 | "entityInstances": []
100 | },
101 | {
102 | "__identifier": "Collisions",
103 | "__type": "IntGrid",
104 | "__cWid": 20,
105 | "__cHei": 16,
106 | "__gridSize": 8,
107 | "__opacity": 1,
108 | "__pxTotalOffsetX": 0,
109 | "__pxTotalOffsetY": 0,
110 | "__tilesetDefUid": 58,
111 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended_hued.png",
112 | "iid": "6004c198-66b0-11ec-a36b-010522b658ac",
113 | "levelId": 41,
114 | "layerDefUid": 2,
115 | "pxOffsetX": 0,
116 | "pxOffsetY": 0,
117 | "visible": true,
118 | "optionalRules": [],
119 | "intGridCsv": [
120 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
121 | 1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,
122 | 1,1,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,
123 | 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
124 | 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
125 | 0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,
126 | 1,1,0,0,0,0,0,0,1,1,1,1,1,3,3,3,3,3,3,1,1,1,3,3,3,3,3,3,1,1,1,1,1,1,3,
127 | 3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
128 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
129 | 1,1,1,1,1
130 | ],
131 | "autoLayerTiles": [
132 | { "px": [8,0], "src": [0,0], "f": 0, "t": 0, "d": [36,1], "a": 1 },
133 | { "px": [16,0], "src": [0,0], "f": 0, "t": 0, "d": [36,2], "a": 1 },
134 | { "px": [48,0], "src": [0,0], "f": 0, "t": 0, "d": [36,6], "a": 1 },
135 | { "px": [56,0], "src": [0,0], "f": 0, "t": 0, "d": [36,7], "a": 1 },
136 | { "px": [88,0], "src": [0,0], "f": 0, "t": 0, "d": [36,11], "a": 1 },
137 | { "px": [96,0], "src": [0,0], "f": 0, "t": 0, "d": [36,12], "a": 1 },
138 | { "px": [104,0], "src": [0,0], "f": 0, "t": 0, "d": [36,13], "a": 1 },
139 | { "px": [112,0], "src": [0,0], "f": 0, "t": 0, "d": [36,14], "a": 1 },
140 | { "px": [120,0], "src": [0,0], "f": 0, "t": 0, "d": [36,15], "a": 1 },
141 | { "px": [128,0], "src": [0,0], "f": 0, "t": 0, "d": [36,16], "a": 1 },
142 | { "px": [152,0], "src": [0,0], "f": 0, "t": 0, "d": [36,19], "a": 1 },
143 | { "px": [72,8], "src": [0,0], "f": 0, "t": 0, "d": [36,29], "a": 1 },
144 | { "px": [88,8], "src": [0,0], "f": 0, "t": 0, "d": [36,31], "a": 1 },
145 | { "px": [152,8], "src": [0,0], "f": 0, "t": 0, "d": [36,39], "a": 1 },
146 | { "px": [80,16], "src": [0,0], "f": 0, "t": 0, "d": [36,50], "a": 1 },
147 | { "px": [152,16], "src": [0,0], "f": 0, "t": 0, "d": [36,59], "a": 1 },
148 | { "px": [152,24], "src": [0,0], "f": 0, "t": 0, "d": [36,79], "a": 1 },
149 | { "px": [152,32], "src": [0,0], "f": 0, "t": 0, "d": [36,99], "a": 1 },
150 | { "px": [0,40], "src": [0,0], "f": 0, "t": 0, "d": [36,100], "a": 1 },
151 | { "px": [0,48], "src": [0,0], "f": 0, "t": 0, "d": [36,120], "a": 1 },
152 | { "px": [152,48], "src": [0,0], "f": 0, "t": 0, "d": [36,139], "a": 1 },
153 | { "px": [0,64], "src": [0,0], "f": 0, "t": 0, "d": [36,160], "a": 1 },
154 | { "px": [0,72], "src": [0,0], "f": 0, "t": 0, "d": [36,180], "a": 1 },
155 | { "px": [8,72], "src": [0,0], "f": 0, "t": 0, "d": [36,181], "a": 1 },
156 | { "px": [0,80], "src": [0,0], "f": 0, "t": 0, "d": [36,200], "a": 1 },
157 | { "px": [8,80], "src": [0,0], "f": 0, "t": 0, "d": [36,201], "a": 1 },
158 | { "px": [152,80], "src": [0,0], "f": 0, "t": 0, "d": [36,219], "a": 1 },
159 | { "px": [16,96], "src": [0,0], "f": 0, "t": 0, "d": [36,242], "a": 1 },
160 | { "px": [152,96], "src": [0,0], "f": 0, "t": 0, "d": [36,259], "a": 1 },
161 | { "px": [0,104], "src": [0,0], "f": 0, "t": 0, "d": [36,260], "a": 1 },
162 | { "px": [16,104], "src": [0,0], "f": 0, "t": 0, "d": [36,262], "a": 1 },
163 | { "px": [24,104], "src": [0,0], "f": 0, "t": 0, "d": [36,263], "a": 1 },
164 | { "px": [144,104], "src": [0,0], "f": 0, "t": 0, "d": [36,278], "a": 1 },
165 | { "px": [152,104], "src": [0,0], "f": 0, "t": 0, "d": [36,279], "a": 1 },
166 | { "px": [0,112], "src": [0,0], "f": 0, "t": 0, "d": [36,280], "a": 1 },
167 | { "px": [8,112], "src": [0,0], "f": 0, "t": 0, "d": [36,281], "a": 1 },
168 | { "px": [16,112], "src": [0,0], "f": 0, "t": 0, "d": [36,282], "a": 1 },
169 | { "px": [24,112], "src": [0,0], "f": 0, "t": 0, "d": [36,283], "a": 1 },
170 | { "px": [32,112], "src": [0,0], "f": 0, "t": 0, "d": [36,284], "a": 1 },
171 | { "px": [48,112], "src": [0,0], "f": 0, "t": 0, "d": [36,286], "a": 1 },
172 | { "px": [56,112], "src": [0,0], "f": 0, "t": 0, "d": [36,287], "a": 1 },
173 | { "px": [64,112], "src": [0,0], "f": 0, "t": 0, "d": [36,288], "a": 1 },
174 | { "px": [72,112], "src": [0,0], "f": 0, "t": 0, "d": [36,289], "a": 1 },
175 | { "px": [80,112], "src": [0,0], "f": 0, "t": 0, "d": [36,290], "a": 1 },
176 | { "px": [88,112], "src": [0,0], "f": 0, "t": 0, "d": [36,291], "a": 1 },
177 | { "px": [112,112], "src": [0,0], "f": 0, "t": 0, "d": [36,294], "a": 1 },
178 | { "px": [120,112], "src": [0,0], "f": 0, "t": 0, "d": [36,295], "a": 1 },
179 | { "px": [136,112], "src": [0,0], "f": 0, "t": 0, "d": [36,297], "a": 1 },
180 | { "px": [152,112], "src": [0,0], "f": 0, "t": 0, "d": [36,299], "a": 1 },
181 | { "px": [0,120], "src": [0,0], "f": 0, "t": 0, "d": [36,300], "a": 1 },
182 | { "px": [8,120], "src": [0,0], "f": 0, "t": 0, "d": [36,301], "a": 1 },
183 | { "px": [16,120], "src": [0,0], "f": 0, "t": 0, "d": [36,302], "a": 1 },
184 | { "px": [56,120], "src": [0,0], "f": 0, "t": 0, "d": [36,307], "a": 1 },
185 | { "px": [64,120], "src": [0,0], "f": 0, "t": 0, "d": [36,308], "a": 1 },
186 | { "px": [72,120], "src": [0,0], "f": 0, "t": 0, "d": [36,309], "a": 1 },
187 | { "px": [80,120], "src": [0,0], "f": 0, "t": 0, "d": [36,310], "a": 1 },
188 | { "px": [88,120], "src": [0,0], "f": 0, "t": 0, "d": [36,311], "a": 1 },
189 | { "px": [120,120], "src": [0,0], "f": 0, "t": 0, "d": [36,315], "a": 1 },
190 | { "px": [128,120], "src": [0,0], "f": 0, "t": 0, "d": [36,316], "a": 1 },
191 | { "px": [136,120], "src": [0,0], "f": 0, "t": 0, "d": [36,317], "a": 1 },
192 | { "px": [144,120], "src": [0,0], "f": 0, "t": 0, "d": [36,318], "a": 1 },
193 | { "px": [152,120], "src": [0,0], "f": 0, "t": 0, "d": [36,319], "a": 1 },
194 | { "px": [0,0], "src": [8,16], "f": 0, "t": 25, "d": [57,0], "a": 1 },
195 | { "px": [24,0], "src": [8,16], "f": 0, "t": 25, "d": [57,3], "a": 1 },
196 | { "px": [32,0], "src": [8,16], "f": 0, "t": 25, "d": [57,4], "a": 1 },
197 | { "px": [40,0], "src": [8,16], "f": 0, "t": 25, "d": [57,5], "a": 1 },
198 | { "px": [64,0], "src": [8,16], "f": 0, "t": 25, "d": [57,8], "a": 1 },
199 | { "px": [72,0], "src": [8,16], "f": 0, "t": 25, "d": [57,9], "a": 1 },
200 | { "px": [80,0], "src": [8,16], "f": 0, "t": 25, "d": [57,10], "a": 1 },
201 | { "px": [136,0], "src": [8,16], "f": 0, "t": 25, "d": [57,17], "a": 1 },
202 | { "px": [144,0], "src": [8,16], "f": 0, "t": 25, "d": [57,18], "a": 1 },
203 | { "px": [80,8], "src": [8,16], "f": 0, "t": 25, "d": [57,30], "a": 1 },
204 | { "px": [144,8], "src": [8,16], "f": 0, "t": 25, "d": [57,38], "a": 1 },
205 | { "px": [8,40], "src": [8,16], "f": 0, "t": 25, "d": [57,101], "a": 1 },
206 | { "px": [152,40], "src": [8,16], "f": 0, "t": 25, "d": [57,119], "a": 1 },
207 | { "px": [8,48], "src": [8,16], "f": 0, "t": 25, "d": [57,121], "a": 1 },
208 | { "px": [0,56], "src": [8,16], "f": 0, "t": 25, "d": [57,140], "a": 1 },
209 | { "px": [8,56], "src": [8,16], "f": 0, "t": 25, "d": [57,141], "a": 1 },
210 | { "px": [152,56], "src": [8,16], "f": 0, "t": 25, "d": [57,159], "a": 1 },
211 | { "px": [8,64], "src": [8,16], "f": 0, "t": 25, "d": [57,161], "a": 1 },
212 | { "px": [152,64], "src": [8,16], "f": 0, "t": 25, "d": [57,179], "a": 1 },
213 | { "px": [152,72], "src": [8,16], "f": 0, "t": 25, "d": [57,199], "a": 1 },
214 | { "px": [0,88], "src": [8,16], "f": 0, "t": 25, "d": [57,220], "a": 1 },
215 | { "px": [8,88], "src": [8,16], "f": 0, "t": 25, "d": [57,221], "a": 1 },
216 | { "px": [152,88], "src": [8,16], "f": 0, "t": 25, "d": [57,239], "a": 1 },
217 | { "px": [0,96], "src": [8,16], "f": 0, "t": 25, "d": [57,240], "a": 1 },
218 | { "px": [8,96], "src": [8,16], "f": 0, "t": 25, "d": [57,241], "a": 1 },
219 | { "px": [8,104], "src": [8,16], "f": 0, "t": 25, "d": [57,261], "a": 1 },
220 | { "px": [40,112], "src": [8,16], "f": 0, "t": 25, "d": [57,285], "a": 1 },
221 | { "px": [96,112], "src": [8,16], "f": 0, "t": 25, "d": [57,292], "a": 1 },
222 | { "px": [104,112], "src": [8,16], "f": 0, "t": 25, "d": [57,293], "a": 1 },
223 | { "px": [128,112], "src": [8,16], "f": 0, "t": 25, "d": [57,296], "a": 1 },
224 | { "px": [144,112], "src": [8,16], "f": 0, "t": 25, "d": [57,298], "a": 1 },
225 | { "px": [24,120], "src": [8,16], "f": 0, "t": 25, "d": [57,303], "a": 1 },
226 | { "px": [32,120], "src": [8,16], "f": 0, "t": 25, "d": [57,304], "a": 1 },
227 | { "px": [40,120], "src": [8,16], "f": 0, "t": 25, "d": [57,305], "a": 1 },
228 | { "px": [48,120], "src": [8,16], "f": 0, "t": 25, "d": [57,306], "a": 1 },
229 | { "px": [96,120], "src": [8,16], "f": 0, "t": 25, "d": [57,312], "a": 1 },
230 | { "px": [104,120], "src": [8,16], "f": 0, "t": 25, "d": [57,313], "a": 1 },
231 | { "px": [112,120], "src": [8,16], "f": 0, "t": 25, "d": [57,314], "a": 1 },
232 | { "px": [72,16], "src": [0,16], "f": 0, "t": 24, "d": [6,49], "a": 1 },
233 | { "px": [88,16], "src": [0,16], "f": 1, "t": 24, "d": [6,51], "a": 1 },
234 | { "px": [144,16], "src": [0,16], "f": 0, "t": 24, "d": [6,58], "a": 1 },
235 | { "px": [144,24], "src": [0,16], "f": 0, "t": 24, "d": [6,78], "a": 1 },
236 | { "px": [144,32], "src": [0,16], "f": 0, "t": 24, "d": [6,98], "a": 1 },
237 | { "px": [16,40], "src": [0,16], "f": 1, "t": 24, "d": [6,102], "a": 1 },
238 | { "px": [144,40], "src": [0,16], "f": 0, "t": 24, "d": [6,118], "a": 1 },
239 | { "px": [16,48], "src": [0,16], "f": 1, "t": 24, "d": [6,122], "a": 1 },
240 | { "px": [144,48], "src": [0,16], "f": 0, "t": 24, "d": [6,138], "a": 1 },
241 | { "px": [16,56], "src": [0,16], "f": 1, "t": 24, "d": [6,142], "a": 1 },
242 | { "px": [144,56], "src": [0,16], "f": 0, "t": 24, "d": [6,158], "a": 1 },
243 | { "px": [16,64], "src": [0,16], "f": 1, "t": 24, "d": [6,162], "a": 1 },
244 | { "px": [144,64], "src": [0,16], "f": 0, "t": 24, "d": [6,178], "a": 1 },
245 | { "px": [16,72], "src": [0,16], "f": 1, "t": 24, "d": [6,182], "a": 1 },
246 | { "px": [144,72], "src": [0,16], "f": 0, "t": 24, "d": [6,198], "a": 1 },
247 | { "px": [16,80], "src": [0,16], "f": 1, "t": 24, "d": [6,202], "a": 1 },
248 | { "px": [144,80], "src": [0,16], "f": 0, "t": 24, "d": [6,218], "a": 1 },
249 | { "px": [16,88], "src": [0,16], "f": 1, "t": 24, "d": [6,222], "a": 1 },
250 | { "px": [144,88], "src": [0,16], "f": 0, "t": 24, "d": [6,238], "a": 1 },
251 | { "px": [144,96], "src": [0,16], "f": 0, "t": 24, "d": [6,258], "a": 1 },
252 | { "px": [0,8], "src": [8,8], "f": 2, "t": 13, "d": [7,20], "a": 1 },
253 | { "px": [8,8], "src": [8,8], "f": 2, "t": 13, "d": [7,21], "a": 1 },
254 | { "px": [16,8], "src": [8,8], "f": 2, "t": 13, "d": [7,22], "a": 1 },
255 | { "px": [24,8], "src": [8,8], "f": 2, "t": 13, "d": [7,23], "a": 1 },
256 | { "px": [32,8], "src": [8,8], "f": 2, "t": 13, "d": [7,24], "a": 1 },
257 | { "px": [40,8], "src": [8,8], "f": 2, "t": 13, "d": [7,25], "a": 1 },
258 | { "px": [48,8], "src": [8,8], "f": 2, "t": 13, "d": [7,26], "a": 1 },
259 | { "px": [56,8], "src": [8,8], "f": 2, "t": 13, "d": [7,27], "a": 1 },
260 | { "px": [64,8], "src": [8,8], "f": 2, "t": 13, "d": [7,28], "a": 1 },
261 | { "px": [96,8], "src": [8,8], "f": 2, "t": 13, "d": [7,32], "a": 1 },
262 | { "px": [104,8], "src": [8,8], "f": 2, "t": 13, "d": [7,33], "a": 1 },
263 | { "px": [112,8], "src": [8,8], "f": 2, "t": 13, "d": [7,34], "a": 1 },
264 | { "px": [120,8], "src": [8,8], "f": 2, "t": 13, "d": [7,35], "a": 1 },
265 | { "px": [128,8], "src": [8,8], "f": 2, "t": 13, "d": [7,36], "a": 1 },
266 | { "px": [136,8], "src": [8,8], "f": 2, "t": 13, "d": [7,37], "a": 1 },
267 | { "px": [80,24], "src": [8,8], "f": 2, "t": 13, "d": [7,70], "a": 1 },
268 | { "px": [0,32], "src": [8,8], "f": 0, "t": 13, "d": [7,80], "a": 1 },
269 | { "px": [8,32], "src": [8,8], "f": 0, "t": 13, "d": [7,81], "a": 1 },
270 | { "px": [80,80], "src": [8,8], "f": 0, "t": 13, "d": [7,210], "a": 1 },
271 | { "px": [80,88], "src": [8,8], "f": 2, "t": 13, "d": [7,230], "a": 1 },
272 | { "px": [32,104], "src": [8,8], "f": 0, "t": 13, "d": [7,264], "a": 1 },
273 | { "px": [40,104], "src": [8,8], "f": 0, "t": 13, "d": [7,265], "a": 1 },
274 | { "px": [48,104], "src": [8,8], "f": 0, "t": 13, "d": [7,266], "a": 1 },
275 | { "px": [56,104], "src": [8,8], "f": 0, "t": 13, "d": [7,267], "a": 1 },
276 | { "px": [64,104], "src": [8,8], "f": 0, "t": 13, "d": [7,268], "a": 1 },
277 | { "px": [72,104], "src": [8,8], "f": 0, "t": 13, "d": [7,269], "a": 1 },
278 | { "px": [80,104], "src": [8,8], "f": 0, "t": 13, "d": [7,270], "a": 1 },
279 | { "px": [88,104], "src": [8,8], "f": 0, "t": 13, "d": [7,271], "a": 1 },
280 | { "px": [96,104], "src": [8,8], "f": 0, "t": 13, "d": [7,272], "a": 1 },
281 | { "px": [104,104], "src": [8,8], "f": 0, "t": 13, "d": [7,273], "a": 1 },
282 | { "px": [112,104], "src": [8,8], "f": 0, "t": 13, "d": [7,274], "a": 1 },
283 | { "px": [120,104], "src": [8,8], "f": 0, "t": 13, "d": [7,275], "a": 1 },
284 | { "px": [128,104], "src": [8,8], "f": 0, "t": 13, "d": [7,276], "a": 1 },
285 | { "px": [136,104], "src": [8,8], "f": 0, "t": 13, "d": [7,277], "a": 1 },
286 | { "px": [72,24], "src": [0,8], "f": 2, "t": 12, "d": [5,69], "a": 1 },
287 | { "px": [88,24], "src": [0,8], "f": 3, "t": 12, "d": [5,71], "a": 1 },
288 | { "px": [16,32], "src": [0,8], "f": 1, "t": 12, "d": [5,82], "a": 1 },
289 | { "px": [72,80], "src": [0,8], "f": 0, "t": 12, "d": [5,209], "a": 1 },
290 | { "px": [88,80], "src": [0,8], "f": 1, "t": 12, "d": [5,211], "a": 1 },
291 | { "px": [72,88], "src": [0,8], "f": 2, "t": 12, "d": [5,229], "a": 1 },
292 | { "px": [88,88], "src": [0,8], "f": 3, "t": 12, "d": [5,231], "a": 1 },
293 | { "px": [24,96], "src": [0,8], "f": 1, "t": 12, "d": [5,243], "a": 1 },
294 | { "px": [0,16], "src": [80,56], "f": 0, "t": 94, "d": [47,40], "a": 1 },
295 | { "px": [8,16], "src": [80,56], "f": 0, "t": 94, "d": [47,41], "a": 1 },
296 | { "px": [16,16], "src": [80,56], "f": 0, "t": 94, "d": [47,42], "a": 1 },
297 | { "px": [24,16], "src": [80,56], "f": 0, "t": 94, "d": [47,43], "a": 1 },
298 | { "px": [32,16], "src": [80,56], "f": 0, "t": 94, "d": [47,44], "a": 1 },
299 | { "px": [40,16], "src": [80,56], "f": 0, "t": 94, "d": [47,45], "a": 1 },
300 | { "px": [48,16], "src": [80,56], "f": 0, "t": 94, "d": [47,46], "a": 1 },
301 | { "px": [56,16], "src": [80,56], "f": 0, "t": 94, "d": [47,47], "a": 1 },
302 | { "px": [64,16], "src": [80,56], "f": 0, "t": 94, "d": [47,48], "a": 1 },
303 | { "px": [96,16], "src": [80,56], "f": 0, "t": 94, "d": [47,52], "a": 1 },
304 | { "px": [104,16], "src": [80,56], "f": 0, "t": 94, "d": [47,53], "a": 1 },
305 | { "px": [112,16], "src": [80,56], "f": 0, "t": 94, "d": [47,54], "a": 1 },
306 | { "px": [120,16], "src": [80,56], "f": 0, "t": 94, "d": [47,55], "a": 1 },
307 | { "px": [128,16], "src": [80,56], "f": 0, "t": 94, "d": [47,56], "a": 1 },
308 | { "px": [136,16], "src": [80,56], "f": 0, "t": 94, "d": [47,57], "a": 1 },
309 | { "px": [72,32], "src": [80,56], "f": 0, "t": 94, "d": [47,89], "a": 1 },
310 | { "px": [80,32], "src": [80,56], "f": 0, "t": 94, "d": [47,90], "a": 1 },
311 | { "px": [88,32], "src": [80,56], "f": 0, "t": 94, "d": [47,91], "a": 1 },
312 | { "px": [80,72], "src": [32,40], "f": 0, "t": 64, "d": [38,190], "a": 1 },
313 | { "px": [16,24], "src": [64,16], "f": 0, "t": 32, "d": [12,62], "a": 1 },
314 | { "px": [0,24], "src": [72,32], "f": 0, "t": 57, "d": [11,60], "a": 1 },
315 | { "px": [8,24], "src": [88,32], "f": 0, "t": 59, "d": [11,61], "a": 1 },
316 | { "px": [16,24], "src": [80,32], "f": 0, "t": 58, "d": [11,62], "a": 1 },
317 | { "px": [72,72], "src": [88,32], "f": 0, "t": 59, "d": [11,189], "a": 1 },
318 | { "px": [80,72], "src": [88,32], "f": 0, "t": 59, "d": [11,190], "a": 1 },
319 | { "px": [88,72], "src": [64,32], "f": 0, "t": 56, "d": [11,191], "a": 1 },
320 | { "px": [8,16], "src": [24,96], "f": 0, "t": 147, "d": [14,41], "a": 1 },
321 | { "px": [56,16], "src": [56,80], "f": 0, "t": 127, "d": [14,47], "a": 1 },
322 | { "px": [72,32], "src": [32,96], "f": 0, "t": 148, "d": [14,89], "a": 1 },
323 | { "px": [88,32], "src": [32,96], "f": 0, "t": 148, "d": [14,91], "a": 1 },
324 | { "px": [32,96], "src": [32,64], "f": 0, "t": 100, "d": [43,244], "a": 1 },
325 | { "px": [40,96], "src": [32,64], "f": 0, "t": 100, "d": [43,245], "a": 1 },
326 | { "px": [48,96], "src": [32,64], "f": 0, "t": 100, "d": [43,246], "a": 1 },
327 | { "px": [56,96], "src": [32,64], "f": 0, "t": 100, "d": [43,247], "a": 1 },
328 | { "px": [64,96], "src": [32,64], "f": 0, "t": 100, "d": [43,248], "a": 1 },
329 | { "px": [72,96], "src": [32,64], "f": 0, "t": 100, "d": [43,249], "a": 1 },
330 | { "px": [80,96], "src": [32,64], "f": 0, "t": 100, "d": [43,250], "a": 1 },
331 | { "px": [88,96], "src": [32,64], "f": 0, "t": 100, "d": [43,251], "a": 1 },
332 | { "px": [96,96], "src": [32,64], "f": 0, "t": 100, "d": [43,252], "a": 1 },
333 | { "px": [104,96], "src": [32,64], "f": 0, "t": 100, "d": [43,253], "a": 1 },
334 | { "px": [112,96], "src": [32,64], "f": 0, "t": 100, "d": [43,254], "a": 1 },
335 | { "px": [120,96], "src": [32,64], "f": 0, "t": 100, "d": [43,255], "a": 1 },
336 | { "px": [128,96], "src": [32,64], "f": 0, "t": 100, "d": [43,256], "a": 1 },
337 | { "px": [136,96], "src": [32,64], "f": 0, "t": 100, "d": [43,257], "a": 1 },
338 | { "px": [24,88], "src": [32,80], "f": 0, "t": 124, "d": [44,223], "a": 1 },
339 | { "px": [32,88], "src": [32,80], "f": 0, "t": 124, "d": [44,224], "a": 1 },
340 | { "px": [40,88], "src": [32,80], "f": 0, "t": 124, "d": [44,225], "a": 1 },
341 | { "px": [48,88], "src": [32,80], "f": 0, "t": 124, "d": [44,226], "a": 1 },
342 | { "px": [56,88], "src": [32,80], "f": 0, "t": 124, "d": [44,227], "a": 1 },
343 | { "px": [64,88], "src": [32,80], "f": 0, "t": 124, "d": [44,228], "a": 1 },
344 | { "px": [96,88], "src": [32,80], "f": 0, "t": 124, "d": [44,232], "a": 1 },
345 | { "px": [104,88], "src": [32,80], "f": 0, "t": 124, "d": [44,233], "a": 1 },
346 | { "px": [112,88], "src": [32,80], "f": 0, "t": 124, "d": [44,234], "a": 1 },
347 | { "px": [120,88], "src": [32,80], "f": 0, "t": 124, "d": [44,235], "a": 1 },
348 | { "px": [128,88], "src": [32,80], "f": 0, "t": 124, "d": [44,236], "a": 1 },
349 | { "px": [136,88], "src": [32,80], "f": 0, "t": 124, "d": [44,237], "a": 1 }
350 | ],
351 | "seed": 4561620,
352 | "overrideTilesetUid": 58,
353 | "gridTiles": [],
354 | "entityInstances": []
355 | },
356 | {
357 | "__identifier": "Cavern_background",
358 | "__type": "IntGrid",
359 | "__cWid": 20,
360 | "__cHei": 16,
361 | "__gridSize": 8,
362 | "__opacity": 1,
363 | "__pxTotalOffsetX": 0,
364 | "__pxTotalOffsetY": 0,
365 | "__tilesetDefUid": 1,
366 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
367 | "iid": "6004e8a0-66b0-11ec-a36b-81200e7178cb",
368 | "levelId": 41,
369 | "layerDefUid": 48,
370 | "pxOffsetX": 0,
371 | "pxOffsetY": 0,
372 | "visible": true,
373 | "optionalRules": [],
374 | "intGridCsv": [
375 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
376 | 1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,
377 | 0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,
378 | 1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,
379 | 0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,
380 | 1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,
381 | 0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
382 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
383 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
384 | 0,0,0,0,0
385 | ],
386 | "autoLayerTiles": [
387 | { "px": [72,40], "src": [0,0], "f": 0, "t": 0, "d": [50,109], "a": 1 },
388 | { "px": [72,48], "src": [0,0], "f": 0, "t": 0, "d": [50,129], "a": 1 },
389 | { "px": [72,56], "src": [0,0], "f": 0, "t": 0, "d": [50,149], "a": 1 },
390 | { "px": [80,56], "src": [0,0], "f": 0, "t": 0, "d": [50,150], "a": 1 },
391 | { "px": [88,56], "src": [0,0], "f": 0, "t": 0, "d": [50,151], "a": 1 },
392 | { "px": [80,64], "src": [0,0], "f": 0, "t": 0, "d": [50,170], "a": 1 },
393 | { "px": [80,40], "src": [32,0], "f": 0, "t": 4, "d": [51,110], "a": 1 },
394 | { "px": [88,40], "src": [48,0], "f": 0, "t": 6, "d": [51,111], "a": 1 },
395 | { "px": [80,48], "src": [40,0], "f": 0, "t": 5, "d": [51,130], "a": 1 },
396 | { "px": [88,48], "src": [8,0], "f": 0, "t": 1, "d": [51,131], "a": 1 },
397 | { "px": [72,64], "src": [8,0], "f": 0, "t": 1, "d": [51,169], "a": 1 },
398 | { "px": [88,64], "src": [24,0], "f": 0, "t": 3, "d": [51,171], "a": 1 },
399 | { "px": [40,16], "src": [40,88], "f": 0, "t": 137, "d": [52,45], "a": 1 },
400 | { "px": [120,16], "src": [40,88], "f": 0, "t": 137, "d": [52,55], "a": 1 },
401 | { "px": [40,24], "src": [40,88], "f": 0, "t": 137, "d": [52,65], "a": 1 },
402 | { "px": [64,24], "src": [40,88], "f": 0, "t": 137, "d": [52,68], "a": 1 },
403 | { "px": [96,24], "src": [40,88], "f": 0, "t": 137, "d": [52,72], "a": 1 },
404 | { "px": [120,24], "src": [40,88], "f": 0, "t": 137, "d": [52,75], "a": 1 },
405 | { "px": [40,32], "src": [40,88], "f": 0, "t": 137, "d": [52,85], "a": 1 },
406 | { "px": [64,32], "src": [40,88], "f": 1, "t": 137, "d": [52,88], "a": 1 },
407 | { "px": [96,32], "src": [40,88], "f": 0, "t": 137, "d": [52,92], "a": 1 },
408 | { "px": [120,32], "src": [40,88], "f": 0, "t": 137, "d": [52,95], "a": 1 },
409 | { "px": [40,40], "src": [40,88], "f": 0, "t": 137, "d": [52,105], "a": 1 },
410 | { "px": [64,40], "src": [40,88], "f": 1, "t": 137, "d": [52,108], "a": 1 },
411 | { "px": [96,40], "src": [40,88], "f": 0, "t": 137, "d": [52,112], "a": 1 },
412 | { "px": [120,40], "src": [40,88], "f": 0, "t": 137, "d": [52,115], "a": 1 },
413 | { "px": [40,48], "src": [40,88], "f": 0, "t": 137, "d": [52,125], "a": 1 },
414 | { "px": [64,48], "src": [40,88], "f": 1, "t": 137, "d": [52,128], "a": 1 },
415 | { "px": [96,48], "src": [40,88], "f": 0, "t": 137, "d": [52,132], "a": 1 },
416 | { "px": [120,48], "src": [40,88], "f": 0, "t": 137, "d": [52,135], "a": 1 },
417 | { "px": [40,56], "src": [40,88], "f": 0, "t": 137, "d": [52,145], "a": 1 },
418 | { "px": [64,56], "src": [40,88], "f": 1, "t": 137, "d": [52,148], "a": 1 },
419 | { "px": [96,56], "src": [40,88], "f": 0, "t": 137, "d": [52,152], "a": 1 },
420 | { "px": [120,56], "src": [40,88], "f": 0, "t": 137, "d": [52,155], "a": 1 },
421 | { "px": [40,64], "src": [40,88], "f": 0, "t": 137, "d": [52,165], "a": 1 },
422 | { "px": [64,64], "src": [40,88], "f": 1, "t": 137, "d": [52,168], "a": 1 },
423 | { "px": [96,64], "src": [40,88], "f": 0, "t": 137, "d": [52,172], "a": 1 },
424 | { "px": [120,64], "src": [40,88], "f": 0, "t": 137, "d": [52,175], "a": 1 },
425 | { "px": [40,72], "src": [40,88], "f": 0, "t": 137, "d": [52,185], "a": 1 },
426 | { "px": [64,72], "src": [40,88], "f": 1, "t": 137, "d": [52,188], "a": 1 },
427 | { "px": [96,72], "src": [40,88], "f": 0, "t": 137, "d": [52,192], "a": 1 },
428 | { "px": [120,72], "src": [40,88], "f": 0, "t": 137, "d": [52,195], "a": 1 },
429 | { "px": [40,80], "src": [40,88], "f": 0, "t": 137, "d": [52,205], "a": 1 },
430 | { "px": [120,80], "src": [40,88], "f": 0, "t": 137, "d": [52,215], "a": 1 },
431 | { "px": [40,8], "src": [40,96], "f": 0, "t": 149, "d": [54,25], "a": 1 },
432 | { "px": [120,8], "src": [40,96], "f": 0, "t": 149, "d": [54,35], "a": 1 },
433 | { "px": [64,16], "src": [40,96], "f": 0, "t": 149, "d": [54,48], "a": 1 },
434 | { "px": [96,16], "src": [40,96], "f": 0, "t": 149, "d": [54,52], "a": 1 },
435 | { "px": [72,32], "src": [40,96], "f": 0, "t": 149, "d": [54,89], "a": 1 },
436 | { "px": [80,32], "src": [40,96], "f": 0, "t": 149, "d": [54,90], "a": 1 },
437 | { "px": [88,32], "src": [40,96], "f": 0, "t": 149, "d": [54,91], "a": 1 },
438 | { "px": [72,72], "src": [40,96], "f": 2, "t": 149, "d": [54,189], "a": 1 },
439 | { "px": [80,72], "src": [40,96], "f": 2, "t": 149, "d": [54,190], "a": 1 },
440 | { "px": [88,72], "src": [40,96], "f": 2, "t": 149, "d": [54,191], "a": 1 },
441 | { "px": [64,80], "src": [40,96], "f": 2, "t": 149, "d": [54,208], "a": 1 },
442 | { "px": [96,80], "src": [40,96], "f": 2, "t": 149, "d": [54,212], "a": 1 },
443 | { "px": [40,88], "src": [40,96], "f": 2, "t": 149, "d": [54,225], "a": 1 },
444 | { "px": [120,88], "src": [40,96], "f": 2, "t": 149, "d": [54,235], "a": 1 },
445 | { "px": [32,8], "src": [88,56], "f": 1, "t": 95, "d": [55,24], "a": 1 },
446 | { "px": [48,8], "src": [88,56], "f": 0, "t": 95, "d": [55,26], "a": 1 },
447 | { "px": [112,8], "src": [88,56], "f": 1, "t": 95, "d": [55,34], "a": 1 },
448 | { "px": [128,8], "src": [88,56], "f": 0, "t": 95, "d": [55,36], "a": 1 },
449 | { "px": [32,16], "src": [88,56], "f": 1, "t": 95, "d": [55,44], "a": 1 },
450 | { "px": [48,16], "src": [88,56], "f": 0, "t": 95, "d": [55,46], "a": 1 },
451 | { "px": [56,16], "src": [88,56], "f": 1, "t": 95, "d": [55,47], "a": 1 },
452 | { "px": [72,16], "src": [88,56], "f": 0, "t": 95, "d": [55,49], "a": 1 },
453 | { "px": [88,16], "src": [88,56], "f": 1, "t": 95, "d": [55,51], "a": 1 },
454 | { "px": [104,16], "src": [88,56], "f": 0, "t": 95, "d": [55,53], "a": 1 },
455 | { "px": [112,16], "src": [88,56], "f": 1, "t": 95, "d": [55,54], "a": 1 },
456 | { "px": [128,16], "src": [88,56], "f": 0, "t": 95, "d": [55,56], "a": 1 },
457 | { "px": [32,24], "src": [88,56], "f": 1, "t": 95, "d": [55,64], "a": 1 },
458 | { "px": [48,24], "src": [88,56], "f": 0, "t": 95, "d": [55,66], "a": 1 },
459 | { "px": [56,24], "src": [88,56], "f": 1, "t": 95, "d": [55,67], "a": 1 },
460 | { "px": [104,24], "src": [88,56], "f": 0, "t": 95, "d": [55,73], "a": 1 },
461 | { "px": [112,24], "src": [88,56], "f": 1, "t": 95, "d": [55,74], "a": 1 },
462 | { "px": [128,24], "src": [88,56], "f": 0, "t": 95, "d": [55,76], "a": 1 },
463 | { "px": [32,32], "src": [88,56], "f": 1, "t": 95, "d": [55,84], "a": 1 },
464 | { "px": [48,32], "src": [88,56], "f": 0, "t": 95, "d": [55,86], "a": 1 },
465 | { "px": [56,32], "src": [88,56], "f": 1, "t": 95, "d": [55,87], "a": 1 },
466 | { "px": [104,32], "src": [88,56], "f": 0, "t": 95, "d": [55,93], "a": 1 },
467 | { "px": [112,32], "src": [88,56], "f": 1, "t": 95, "d": [55,94], "a": 1 },
468 | { "px": [128,32], "src": [88,56], "f": 0, "t": 95, "d": [55,96], "a": 1 },
469 | { "px": [32,40], "src": [88,56], "f": 1, "t": 95, "d": [55,104], "a": 1 },
470 | { "px": [48,40], "src": [88,56], "f": 0, "t": 95, "d": [55,106], "a": 1 },
471 | { "px": [56,40], "src": [88,56], "f": 1, "t": 95, "d": [55,107], "a": 1 },
472 | { "px": [104,40], "src": [88,56], "f": 0, "t": 95, "d": [55,113], "a": 1 },
473 | { "px": [112,40], "src": [88,56], "f": 1, "t": 95, "d": [55,114], "a": 1 },
474 | { "px": [128,40], "src": [88,56], "f": 0, "t": 95, "d": [55,116], "a": 1 },
475 | { "px": [32,48], "src": [88,56], "f": 1, "t": 95, "d": [55,124], "a": 1 },
476 | { "px": [48,48], "src": [88,56], "f": 0, "t": 95, "d": [55,126], "a": 1 },
477 | { "px": [56,48], "src": [88,56], "f": 1, "t": 95, "d": [55,127], "a": 1 },
478 | { "px": [104,48], "src": [88,56], "f": 0, "t": 95, "d": [55,133], "a": 1 },
479 | { "px": [112,48], "src": [88,56], "f": 1, "t": 95, "d": [55,134], "a": 1 },
480 | { "px": [128,48], "src": [88,56], "f": 0, "t": 95, "d": [55,136], "a": 1 },
481 | { "px": [32,56], "src": [88,56], "f": 1, "t": 95, "d": [55,144], "a": 1 },
482 | { "px": [48,56], "src": [88,56], "f": 0, "t": 95, "d": [55,146], "a": 1 },
483 | { "px": [56,56], "src": [88,56], "f": 1, "t": 95, "d": [55,147], "a": 1 },
484 | { "px": [104,56], "src": [88,56], "f": 0, "t": 95, "d": [55,153], "a": 1 },
485 | { "px": [112,56], "src": [88,56], "f": 1, "t": 95, "d": [55,154], "a": 1 },
486 | { "px": [128,56], "src": [88,56], "f": 0, "t": 95, "d": [55,156], "a": 1 },
487 | { "px": [32,64], "src": [88,56], "f": 1, "t": 95, "d": [55,164], "a": 1 },
488 | { "px": [48,64], "src": [88,56], "f": 0, "t": 95, "d": [55,166], "a": 1 },
489 | { "px": [56,64], "src": [88,56], "f": 1, "t": 95, "d": [55,167], "a": 1 },
490 | { "px": [104,64], "src": [88,56], "f": 0, "t": 95, "d": [55,173], "a": 1 },
491 | { "px": [112,64], "src": [88,56], "f": 1, "t": 95, "d": [55,174], "a": 1 },
492 | { "px": [128,64], "src": [88,56], "f": 0, "t": 95, "d": [55,176], "a": 1 },
493 | { "px": [32,72], "src": [88,56], "f": 1, "t": 95, "d": [55,184], "a": 1 },
494 | { "px": [48,72], "src": [88,56], "f": 0, "t": 95, "d": [55,186], "a": 1 },
495 | { "px": [56,72], "src": [88,56], "f": 1, "t": 95, "d": [55,187], "a": 1 },
496 | { "px": [104,72], "src": [88,56], "f": 0, "t": 95, "d": [55,193], "a": 1 },
497 | { "px": [112,72], "src": [88,56], "f": 1, "t": 95, "d": [55,194], "a": 1 },
498 | { "px": [128,72], "src": [88,56], "f": 0, "t": 95, "d": [55,196], "a": 1 },
499 | { "px": [32,80], "src": [88,56], "f": 1, "t": 95, "d": [55,204], "a": 1 },
500 | { "px": [48,80], "src": [88,56], "f": 0, "t": 95, "d": [55,206], "a": 1 },
501 | { "px": [56,80], "src": [88,56], "f": 1, "t": 95, "d": [55,207], "a": 1 },
502 | { "px": [104,80], "src": [88,56], "f": 0, "t": 95, "d": [55,213], "a": 1 },
503 | { "px": [112,80], "src": [88,56], "f": 1, "t": 95, "d": [55,214], "a": 1 },
504 | { "px": [128,80], "src": [88,56], "f": 0, "t": 95, "d": [55,216], "a": 1 },
505 | { "px": [32,88], "src": [88,56], "f": 1, "t": 95, "d": [55,224], "a": 1 },
506 | { "px": [48,88], "src": [88,56], "f": 0, "t": 95, "d": [55,226], "a": 1 },
507 | { "px": [112,88], "src": [88,56], "f": 1, "t": 95, "d": [55,234], "a": 1 },
508 | { "px": [128,88], "src": [88,56], "f": 0, "t": 95, "d": [55,236], "a": 1 },
509 | { "px": [40,0], "src": [80,56], "f": 2, "t": 94, "d": [56,5], "a": 1 },
510 | { "px": [120,0], "src": [80,56], "f": 2, "t": 94, "d": [56,15], "a": 1 },
511 | { "px": [64,8], "src": [80,56], "f": 2, "t": 94, "d": [56,28], "a": 1 },
512 | { "px": [96,8], "src": [80,56], "f": 2, "t": 94, "d": [56,32], "a": 1 },
513 | { "px": [72,24], "src": [80,56], "f": 2, "t": 94, "d": [56,69], "a": 1 },
514 | { "px": [80,24], "src": [80,56], "f": 2, "t": 94, "d": [56,70], "a": 1 },
515 | { "px": [88,24], "src": [80,56], "f": 2, "t": 94, "d": [56,71], "a": 1 },
516 | { "px": [72,80], "src": [80,56], "f": 0, "t": 94, "d": [56,209], "a": 1 },
517 | { "px": [80,80], "src": [80,56], "f": 0, "t": 94, "d": [56,210], "a": 1 },
518 | { "px": [88,80], "src": [80,56], "f": 0, "t": 94, "d": [56,211], "a": 1 },
519 | { "px": [64,88], "src": [80,56], "f": 0, "t": 94, "d": [56,228], "a": 1 },
520 | { "px": [96,88], "src": [80,56], "f": 0, "t": 94, "d": [56,232], "a": 1 },
521 | { "px": [40,96], "src": [80,56], "f": 0, "t": 94, "d": [56,245], "a": 1 },
522 | { "px": [120,96], "src": [80,56], "f": 0, "t": 94, "d": [56,255], "a": 1 }
523 | ],
524 | "seed": 7498828,
525 | "overrideTilesetUid": null,
526 | "gridTiles": [],
527 | "entityInstances": []
528 | }
529 | ],
530 | "__neighbours": [{ "levelIid": "60038910-66b0-11ec-a36b-1ff7a8a0ffd4", "dir": "w" }]
531 | }
--------------------------------------------------------------------------------
/samples/_assets/sample/png/East.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/sample/png/East.png
--------------------------------------------------------------------------------
/samples/_assets/sample/png/Pit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/sample/png/Pit.png
--------------------------------------------------------------------------------
/samples/_assets/sample/png/Treasure_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/sample/png/Treasure_room.png
--------------------------------------------------------------------------------
/samples/_assets/sample/png/West.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/samples/_assets/sample/png/West.png
--------------------------------------------------------------------------------
/samples/_assets/unitTest/Offset_tests.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "1.5.3",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "Offset_tests",
12 | "iid": "f2f66840-66b0-11ec-91ab-e506cb005a35",
13 | "uid": 88,
14 | "worldX": 512,
15 | "worldY": 256,
16 | "worldDepth": 0,
17 | "pxWid": 256,
18 | "pxHei": 256,
19 | "__bgColor": "#7F8093",
20 | "bgColor": null,
21 | "useAutoIdentifier": false,
22 | "bgRelPath": null,
23 | "bgPos": null,
24 | "bgPivotX": 0.5,
25 | "bgPivotY": 0.5,
26 | "__smartColor": "#B9B9C4",
27 | "__bgPos": null,
28 | "externalRelPath": null,
29 | "fieldInstances": [
30 | { "__identifier": "level_int", "__type": "Int", "__value": 2, "__tile": null, "defUid": 93, "realEditorValues": [{ "id": "V_Int", "params": [2] }] },
31 | { "__identifier": "level_string", "__type": "String", "__value": "other", "__tile": null, "defUid": 94, "realEditorValues": [{
32 | "id": "V_String",
33 | "params": ["other"]
34 | }] },
35 | { "__identifier": "level_reward", "__type": "ExternEnum.DroppedItemType", "__value": "Key", "__tile": null, "defUid": 95, "realEditorValues": [{
36 | "id": "V_String",
37 | "params": ["Key"]
38 | }] },
39 | { "__identifier": "lowercase_enum", "__type": "Array", "__value": [], "__tile": null, "defUid": 106, "realEditorValues": [] }
40 | ],
41 | "layerInstances": [
42 | {
43 | "__identifier": "IntGrid_AutoLayer",
44 | "__type": "IntGrid",
45 | "__cWid": 32,
46 | "__cHei": 32,
47 | "__gridSize": 8,
48 | "__opacity": 1,
49 | "__pxTotalOffsetX": 0,
50 | "__pxTotalOffsetY": 0,
51 | "__tilesetDefUid": 46,
52 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
53 | "iid": "2737c0a6-66b0-11ec-8446-3f4faacc597c",
54 | "levelId": 88,
55 | "layerDefUid": 41,
56 | "pxOffsetX": 0,
57 | "pxOffsetY": 0,
58 | "visible": true,
59 | "optionalRules": [],
60 | "intGridCsv": [
61 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
65 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
66 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
68 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
69 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
70 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
78 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
79 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
80 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
81 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
82 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
83 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
85 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
86 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
87 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
88 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
89 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
90 | 0,0,0,0,0,0,0,0,0
91 | ],
92 | "autoLayerTiles": [
93 | { "px": [152,96], "src": [32,32], "f": 0, "t": 52, "d": [53,403], "a": 1 },
94 | { "px": [152,88], "src": [80,32], "f": 0, "t": 58, "d": [48,371], "a": 1 },
95 | { "px": [144,104], "src": [80,32], "f": 2, "t": 58, "d": [48,434], "a": 1 },
96 | { "px": [152,104], "src": [80,32], "f": 2, "t": 58, "d": [48,435], "a": 1 },
97 | { "px": [160,104], "src": [88,32], "f": 2, "t": 59, "d": [48,436], "a": 1 },
98 | { "px": [160,184], "src": [80,32], "f": 2, "t": 58, "d": [48,756], "a": 1 },
99 | { "px": [152,88], "src": [72,16], "f": 0, "t": 33, "d": [54,371], "a": 1 },
100 | { "px": [144,80], "src": [0,112], "f": 0, "t": 168, "d": [80,370], "a": 1 },
101 | { "px": [144,88], "src": [0,120], "f": 0, "t": 180, "d": [80,370], "a": 1 },
102 | { "px": [160,80], "src": [0,112], "f": 0, "t": 168, "d": [80,372], "a": 1 },
103 | { "px": [160,88], "src": [0,120], "f": 0, "t": 180, "d": [80,372], "a": 1 },
104 | { "px": [160,160], "src": [0,112], "f": 0, "t": 168, "d": [80,692], "a": 1 },
105 | { "px": [160,168], "src": [0,120], "f": 0, "t": 180, "d": [80,692], "a": 1 },
106 | { "px": [140,92], "src": [0,152], "f": 0, "t": 228, "d": [81,402], "a": 1 },
107 | { "px": [140,100], "src": [0,160], "f": 0, "t": 240, "d": [81,402], "a": 1 },
108 | { "px": [148,92], "src": [8,152], "f": 0, "t": 229, "d": [81,402], "a": 1 },
109 | { "px": [148,100], "src": [8,160], "f": 0, "t": 241, "d": [81,402], "a": 1 },
110 | { "px": [164,92], "src": [0,152], "f": 1, "t": 228, "d": [81,404], "a": 1 },
111 | { "px": [164,100], "src": [0,160], "f": 1, "t": 240, "d": [81,404], "a": 1 },
112 | { "px": [156,92], "src": [8,152], "f": 1, "t": 229, "d": [81,404], "a": 1 },
113 | { "px": [156,100], "src": [8,160], "f": 1, "t": 241, "d": [81,404], "a": 1 },
114 | { "px": [156,172], "src": [0,152], "f": 0, "t": 228, "d": [81,724], "a": 1 },
115 | { "px": [156,180], "src": [0,160], "f": 0, "t": 240, "d": [81,724], "a": 1 },
116 | { "px": [164,172], "src": [8,152], "f": 0, "t": 229, "d": [81,724], "a": 1 },
117 | { "px": [164,180], "src": [8,160], "f": 0, "t": 241, "d": [81,724], "a": 1 }
118 | ],
119 | "seed": 2453189,
120 | "overrideTilesetUid": null,
121 | "gridTiles": [],
122 | "entityInstances": []
123 | },
124 | {
125 | "__identifier": "Pure_AutoLayer",
126 | "__type": "AutoLayer",
127 | "__cWid": 32,
128 | "__cHei": 32,
129 | "__gridSize": 8,
130 | "__opacity": 1,
131 | "__pxTotalOffsetX": 0,
132 | "__pxTotalOffsetY": 0,
133 | "__tilesetDefUid": 46,
134 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
135 | "iid": "2737c0a7-66b0-11ec-8446-67da903cc393",
136 | "levelId": 88,
137 | "layerDefUid": 82,
138 | "pxOffsetX": 0,
139 | "pxOffsetY": 0,
140 | "visible": true,
141 | "optionalRules": [],
142 | "intGridCsv": [],
143 | "autoLayerTiles": [
144 | { "px": [144,104], "src": [32,96], "f": 0, "t": 148, "d": [85,434], "a": 1 },
145 | { "px": [152,104], "src": [48,80], "f": 0, "t": 126, "d": [85,435], "a": 1 },
146 | { "px": [160,104], "src": [56,80], "f": 0, "t": 127, "d": [85,436], "a": 1 },
147 | { "px": [160,184], "src": [24,96], "f": 0, "t": 147, "d": [85,756], "a": 1 },
148 | { "px": [144,88], "src": [80,32], "f": 0, "t": 58, "d": [84,370], "a": 1 },
149 | { "px": [152,88], "src": [64,32], "f": 0, "t": 56, "d": [84,371], "a": 1 },
150 | { "px": [160,88], "src": [80,32], "f": 0, "t": 58, "d": [84,372], "a": 1 },
151 | { "px": [160,168], "src": [88,32], "f": 0, "t": 59, "d": [84,692], "a": 1 }
152 | ],
153 | "seed": 8276094,
154 | "overrideTilesetUid": null,
155 | "gridTiles": [],
156 | "entityInstances": []
157 | },
158 | {
159 | "__identifier": "EntityWithTag",
160 | "__type": "Entities",
161 | "__cWid": 16,
162 | "__cHei": 16,
163 | "__gridSize": 16,
164 | "__opacity": 1,
165 | "__pxTotalOffsetX": 0,
166 | "__pxTotalOffsetY": 0,
167 | "__tilesetDefUid": null,
168 | "__tilesetRelPath": null,
169 | "iid": "b4eeea40-b4d0-11ec-a74c-ab342815632c",
170 | "levelId": 88,
171 | "layerDefUid": 118,
172 | "pxOffsetX": 0,
173 | "pxOffsetY": 0,
174 | "visible": true,
175 | "optionalRules": [],
176 | "intGridCsv": [],
177 | "autoLayerTiles": [],
178 | "seed": 1220562,
179 | "overrideTilesetUid": null,
180 | "gridTiles": [],
181 | "entityInstances": []
182 | },
183 | {
184 | "__identifier": "EntityTest",
185 | "__type": "Entities",
186 | "__cWid": 16,
187 | "__cHei": 16,
188 | "__gridSize": 16,
189 | "__opacity": 1,
190 | "__pxTotalOffsetX": 8,
191 | "__pxTotalOffsetY": 8,
192 | "__tilesetDefUid": null,
193 | "__tilesetRelPath": null,
194 | "iid": "2737e7b0-66b0-11ec-8446-8d36042559a5",
195 | "levelId": 88,
196 | "layerDefUid": 4,
197 | "pxOffsetX": 8,
198 | "pxOffsetY": 8,
199 | "visible": true,
200 | "optionalRules": [],
201 | "intGridCsv": [],
202 | "autoLayerTiles": [],
203 | "seed": 9962612,
204 | "overrideTilesetUid": null,
205 | "gridTiles": [],
206 | "entityInstances": [
207 | {
208 | "__identifier": "OffsetTest",
209 | "__grid": [0,0],
210 | "__pivot": [0,0],
211 | "__tags": [],
212 | "__tile": null,
213 | "__smartColor": "#FF00C8",
214 | "iid": "f2f66841-66b0-11ec-91ab-554b0e889009",
215 | "width": 16,
216 | "height": 16,
217 | "defUid": 89,
218 | "px": [0,0],
219 | "fieldInstances": [],
220 | "__worldX": 512,
221 | "__worldY": 256
222 | }
223 | ]
224 | },
225 | {
226 | "__identifier": "TileTest",
227 | "__type": "Tiles",
228 | "__cWid": 8,
229 | "__cHei": 8,
230 | "__gridSize": 32,
231 | "__opacity": 1,
232 | "__pxTotalOffsetX": 8,
233 | "__pxTotalOffsetY": 8,
234 | "__tilesetDefUid": 14,
235 | "__tilesetRelPath": "Minecraft_texture_pack.gif",
236 | "iid": "2737e7b1-66b0-11ec-8446-3f9ba678aab8",
237 | "levelId": 88,
238 | "layerDefUid": 15,
239 | "pxOffsetX": 8,
240 | "pxOffsetY": 8,
241 | "visible": true,
242 | "optionalRules": [],
243 | "intGridCsv": [],
244 | "autoLayerTiles": [],
245 | "seed": 1968104,
246 | "overrideTilesetUid": null,
247 | "gridTiles": [],
248 | "entityInstances": []
249 | },
250 | {
251 | "__identifier": "IntGridTest",
252 | "__type": "IntGrid",
253 | "__cWid": 16,
254 | "__cHei": 16,
255 | "__gridSize": 16,
256 | "__opacity": 0.62,
257 | "__pxTotalOffsetX": 8,
258 | "__pxTotalOffsetY": 8,
259 | "__tilesetDefUid": null,
260 | "__tilesetRelPath": null,
261 | "iid": "2737e7b2-66b0-11ec-8446-dfadd425d977",
262 | "levelId": 88,
263 | "layerDefUid": 13,
264 | "pxOffsetX": 8,
265 | "pxOffsetY": 8,
266 | "visible": true,
267 | "optionalRules": [],
268 | "intGridCsv": [
269 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
270 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
271 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
272 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
273 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
274 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
275 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
276 | 0,0,0,0,0,0,0,0,0,0,0
277 | ],
278 | "autoLayerTiles": [],
279 | "seed": 5650967,
280 | "overrideTilesetUid": null,
281 | "gridTiles": [],
282 | "entityInstances": []
283 | },
284 | {
285 | "__identifier": "IntGrid8",
286 | "__type": "IntGrid",
287 | "__cWid": 32,
288 | "__cHei": 32,
289 | "__gridSize": 8,
290 | "__opacity": 1,
291 | "__pxTotalOffsetX": 4,
292 | "__pxTotalOffsetY": 4,
293 | "__tilesetDefUid": null,
294 | "__tilesetRelPath": null,
295 | "iid": "2737e7b3-66b0-11ec-8446-51880ef2561a",
296 | "levelId": 88,
297 | "layerDefUid": 87,
298 | "pxOffsetX": 0,
299 | "pxOffsetY": 0,
300 | "visible": true,
301 | "optionalRules": [],
302 | "intGridCsv": [
303 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
304 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
305 | 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
306 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
307 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
308 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
309 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
310 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
311 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
312 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
313 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
314 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
315 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
316 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
317 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
318 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
319 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
320 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
321 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
322 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
323 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
324 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
325 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
326 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
327 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
328 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
329 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
330 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
331 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
332 | 0,0,0,0,0,0,0,0,0
333 | ],
334 | "autoLayerTiles": [],
335 | "seed": 9897278,
336 | "overrideTilesetUid": null,
337 | "gridTiles": [],
338 | "entityInstances": []
339 | }
340 | ],
341 | "__neighbours": [ { "levelIid": "f2f3d030-66b0-11ec-91ab-fd4b3030ab4e", "dir": "w" }, { "levelIid": "bdabeb40-66b0-11ec-88f3-5d5bfa64cc93", "dir": "n" } ]
342 | }
--------------------------------------------------------------------------------
/samples/_assets/unitTest/Target_level_ref.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "1.5.3",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "Target_level_ref",
12 | "iid": "bdabeb40-66b0-11ec-88f3-5d5bfa64cc93",
13 | "uid": 109,
14 | "worldX": 512,
15 | "worldY": 0,
16 | "worldDepth": 0,
17 | "pxWid": 256,
18 | "pxHei": 256,
19 | "__bgColor": "#7F8093",
20 | "bgColor": null,
21 | "useAutoIdentifier": false,
22 | "bgRelPath": null,
23 | "bgPos": null,
24 | "bgPivotX": 0.5,
25 | "bgPivotY": 0.5,
26 | "__smartColor": "#B9B9C4",
27 | "__bgPos": null,
28 | "externalRelPath": null,
29 | "fieldInstances": [
30 | { "__identifier": "level_int", "__type": "Int", "__value": 0, "__tile": null, "defUid": 93, "realEditorValues": [] },
31 | { "__identifier": "level_string", "__type": "String", "__value": "", "__tile": null, "defUid": 94, "realEditorValues": [] },
32 | { "__identifier": "level_reward", "__type": "ExternEnum.DroppedItemType", "__value": "Ammo", "__tile": null, "defUid": 95, "realEditorValues": [{
33 | "id": "V_String",
34 | "params": ["Ammo"]
35 | }] },
36 | { "__identifier": "lowercase_enum", "__type": "Array", "__value": [], "__tile": null, "defUid": 106, "realEditorValues": [] }
37 | ],
38 | "layerInstances": [
39 | {
40 | "__identifier": "IntGrid_AutoLayer",
41 | "__type": "IntGrid",
42 | "__cWid": 32,
43 | "__cHei": 32,
44 | "__gridSize": 8,
45 | "__opacity": 1,
46 | "__pxTotalOffsetX": 0,
47 | "__pxTotalOffsetY": 0,
48 | "__tilesetDefUid": 46,
49 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
50 | "iid": "bdabeb41-66b0-11ec-88f3-b9a751052e5d",
51 | "levelId": 109,
52 | "layerDefUid": 41,
53 | "pxOffsetX": 0,
54 | "pxOffsetY": 0,
55 | "visible": true,
56 | "optionalRules": [],
57 | "intGridCsv": [
58 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
59 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
60 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
65 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
66 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
68 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
69 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
70 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
78 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
79 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
80 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
81 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
82 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
83 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
85 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
86 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
87 | 0,0,0,0,0,0,0,0,0
88 | ],
89 | "autoLayerTiles": [],
90 | "seed": 3402616,
91 | "overrideTilesetUid": null,
92 | "gridTiles": [],
93 | "entityInstances": []
94 | },
95 | {
96 | "__identifier": "Pure_AutoLayer",
97 | "__type": "AutoLayer",
98 | "__cWid": 32,
99 | "__cHei": 32,
100 | "__gridSize": 8,
101 | "__opacity": 1,
102 | "__pxTotalOffsetX": 0,
103 | "__pxTotalOffsetY": 0,
104 | "__tilesetDefUid": 46,
105 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
106 | "iid": "bdabeb42-66b0-11ec-88f3-870d6a0bd606",
107 | "levelId": 109,
108 | "layerDefUid": 82,
109 | "pxOffsetX": 0,
110 | "pxOffsetY": 0,
111 | "visible": true,
112 | "optionalRules": [],
113 | "intGridCsv": [],
114 | "autoLayerTiles": [],
115 | "seed": 9463295,
116 | "overrideTilesetUid": null,
117 | "gridTiles": [],
118 | "entityInstances": []
119 | },
120 | {
121 | "__identifier": "EntityWithTag",
122 | "__type": "Entities",
123 | "__cWid": 16,
124 | "__cHei": 16,
125 | "__gridSize": 16,
126 | "__opacity": 1,
127 | "__pxTotalOffsetX": 0,
128 | "__pxTotalOffsetY": 0,
129 | "__tilesetDefUid": null,
130 | "__tilesetRelPath": null,
131 | "iid": "b4ef5f70-b4d0-11ec-a74c-d36276c61819",
132 | "levelId": 109,
133 | "layerDefUid": 118,
134 | "pxOffsetX": 0,
135 | "pxOffsetY": 0,
136 | "visible": true,
137 | "optionalRules": [],
138 | "intGridCsv": [],
139 | "autoLayerTiles": [],
140 | "seed": 7874079,
141 | "overrideTilesetUid": null,
142 | "gridTiles": [],
143 | "entityInstances": []
144 | },
145 | {
146 | "__identifier": "EntityTest",
147 | "__type": "Entities",
148 | "__cWid": 16,
149 | "__cHei": 16,
150 | "__gridSize": 16,
151 | "__opacity": 1,
152 | "__pxTotalOffsetX": 0,
153 | "__pxTotalOffsetY": 0,
154 | "__tilesetDefUid": null,
155 | "__tilesetRelPath": null,
156 | "iid": "bdabeb43-66b0-11ec-88f3-f17ff25d77e6",
157 | "levelId": 109,
158 | "layerDefUid": 4,
159 | "pxOffsetX": 0,
160 | "pxOffsetY": 0,
161 | "visible": true,
162 | "optionalRules": [],
163 | "intGridCsv": [],
164 | "autoLayerTiles": [],
165 | "seed": 7619210,
166 | "overrideTilesetUid": null,
167 | "gridTiles": [],
168 | "entityInstances": [
169 | {
170 | "__identifier": "SymRef",
171 | "__grid": [7,7],
172 | "__pivot": [0,0],
173 | "__tags": [],
174 | "__tile": null,
175 | "__smartColor": "#FF6700",
176 | "iid": "be92c8d0-66b0-11ec-88f3-df87634ca4af",
177 | "width": 16,
178 | "height": 16,
179 | "defUid": 107,
180 | "px": [112,112],
181 | "fieldInstances": [{ "__identifier": "ref", "__type": "EntityRef", "__value": {
182 | "entityIid": "bcf852b0-66b0-11ec-88f3-f1c676c28598",
183 | "layerIid": "27359dc1-66b0-11ec-8446-ff4b9136ca03",
184 | "levelIid": "f2f3d030-66b0-11ec-91ab-fd4b3030ab4e",
185 | "worldIid": "9df6b3c0-c640-11ed-b633-f10db708ef70"
186 | }, "__tile": null, "defUid": 108, "realEditorValues": [{
187 | "id": "V_String",
188 | "params": ["bcf852b0-66b0-11ec-88f3-f1c676c28598"]
189 | }] }],
190 | "__worldX": 624,
191 | "__worldY": 112
192 | }
193 | ]
194 | },
195 | {
196 | "__identifier": "TileTest",
197 | "__type": "Tiles",
198 | "__cWid": 8,
199 | "__cHei": 8,
200 | "__gridSize": 32,
201 | "__opacity": 1,
202 | "__pxTotalOffsetX": 0,
203 | "__pxTotalOffsetY": 0,
204 | "__tilesetDefUid": 14,
205 | "__tilesetRelPath": "Minecraft_texture_pack.gif",
206 | "iid": "bdabeb44-66b0-11ec-88f3-e5d422c87149",
207 | "levelId": 109,
208 | "layerDefUid": 15,
209 | "pxOffsetX": 0,
210 | "pxOffsetY": 0,
211 | "visible": true,
212 | "optionalRules": [],
213 | "intGridCsv": [],
214 | "autoLayerTiles": [],
215 | "seed": 8025879,
216 | "overrideTilesetUid": null,
217 | "gridTiles": [],
218 | "entityInstances": []
219 | },
220 | {
221 | "__identifier": "IntGridTest",
222 | "__type": "IntGrid",
223 | "__cWid": 16,
224 | "__cHei": 16,
225 | "__gridSize": 16,
226 | "__opacity": 0.62,
227 | "__pxTotalOffsetX": 0,
228 | "__pxTotalOffsetY": 0,
229 | "__tilesetDefUid": null,
230 | "__tilesetRelPath": null,
231 | "iid": "bdabeb45-66b0-11ec-88f3-bb4e53d38c23",
232 | "levelId": 109,
233 | "layerDefUid": 13,
234 | "pxOffsetX": 0,
235 | "pxOffsetY": 0,
236 | "visible": true,
237 | "optionalRules": [],
238 | "intGridCsv": [
239 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
240 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
241 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
242 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
243 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
244 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
245 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
246 | 0,0,0,0,0,0,0,0,0,0,0
247 | ],
248 | "autoLayerTiles": [],
249 | "seed": 4729756,
250 | "overrideTilesetUid": null,
251 | "gridTiles": [],
252 | "entityInstances": []
253 | },
254 | {
255 | "__identifier": "IntGrid8",
256 | "__type": "IntGrid",
257 | "__cWid": 32,
258 | "__cHei": 32,
259 | "__gridSize": 8,
260 | "__opacity": 1,
261 | "__pxTotalOffsetX": 4,
262 | "__pxTotalOffsetY": 4,
263 | "__tilesetDefUid": null,
264 | "__tilesetRelPath": null,
265 | "iid": "bdabeb46-66b0-11ec-88f3-63b465c9499f",
266 | "levelId": 109,
267 | "layerDefUid": 87,
268 | "pxOffsetX": 0,
269 | "pxOffsetY": 0,
270 | "visible": true,
271 | "optionalRules": [],
272 | "intGridCsv": [
273 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
274 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
275 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
276 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
277 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
278 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
279 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
280 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
281 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
282 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
283 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
284 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
285 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
286 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
287 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
288 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
289 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
290 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
291 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
292 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
293 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
294 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
295 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
296 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
297 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
298 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
299 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
300 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
301 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
302 | 0,0,0,0,0,0,0,0,0
303 | ],
304 | "autoLayerTiles": [],
305 | "seed": 6195883,
306 | "overrideTilesetUid": null,
307 | "gridTiles": [],
308 | "entityInstances": []
309 | }
310 | ],
311 | "__neighbours": [ { "levelIid": "f2f3d030-66b0-11ec-91ab-fd4b3030ab4e", "dir": "w" }, { "levelIid": "f2f66840-66b0-11ec-91ab-e506cb005a35", "dir": "s" } ]
312 | }
--------------------------------------------------------------------------------
/samples/_assets/unitTest/World1_Level_3.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "1.5.3",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "World1_Level_3",
12 | "iid": "b1e31860-7820-11ed-b18d-6339f608f11d",
13 | "uid": 120,
14 | "worldX": 0,
15 | "worldY": 768,
16 | "worldDepth": 0,
17 | "pxWid": 256,
18 | "pxHei": 256,
19 | "__bgColor": "#7F8093",
20 | "bgColor": null,
21 | "useAutoIdentifier": true,
22 | "bgRelPath": null,
23 | "bgPos": null,
24 | "bgPivotX": 0.5,
25 | "bgPivotY": 0.5,
26 | "__smartColor": "#B9B9C4",
27 | "__bgPos": null,
28 | "externalRelPath": null,
29 | "fieldInstances": [
30 | { "__identifier": "level_int", "__type": "Int", "__value": 0, "__tile": null, "defUid": 93, "realEditorValues": [] },
31 | { "__identifier": "level_string", "__type": "String", "__value": "", "__tile": null, "defUid": 94, "realEditorValues": [] },
32 | { "__identifier": "level_reward", "__type": "ExternEnum.DroppedItemType", "__value": null, "__tile": null, "defUid": 95, "realEditorValues": [] },
33 | { "__identifier": "lowercase_enum", "__type": "Array", "__value": [], "__tile": null, "defUid": 106, "realEditorValues": [] }
34 | ],
35 | "layerInstances": [
36 | {
37 | "__identifier": "IntGrid_AutoLayer",
38 | "__type": "IntGrid",
39 | "__cWid": 32,
40 | "__cHei": 32,
41 | "__gridSize": 8,
42 | "__opacity": 1,
43 | "__pxTotalOffsetX": 0,
44 | "__pxTotalOffsetY": 0,
45 | "__tilesetDefUid": 46,
46 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
47 | "iid": "b1e33f70-7820-11ed-b18d-e705c345d973",
48 | "levelId": 120,
49 | "layerDefUid": 41,
50 | "pxOffsetX": 0,
51 | "pxOffsetY": 0,
52 | "visible": true,
53 | "optionalRules": [],
54 | "intGridCsv": [
55 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
59 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
60 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
65 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
66 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
68 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
69 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
70 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
78 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
79 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
80 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
81 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
82 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
83 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 | 0,0,0,0,0,0,0,0,0
85 | ],
86 | "autoLayerTiles": [],
87 | "seed": 7573409,
88 | "overrideTilesetUid": null,
89 | "gridTiles": [],
90 | "entityInstances": []
91 | },
92 | {
93 | "__identifier": "Pure_AutoLayer",
94 | "__type": "AutoLayer",
95 | "__cWid": 32,
96 | "__cHei": 32,
97 | "__gridSize": 8,
98 | "__opacity": 1,
99 | "__pxTotalOffsetX": 0,
100 | "__pxTotalOffsetY": 0,
101 | "__tilesetDefUid": 46,
102 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
103 | "iid": "b1e33f71-7820-11ed-b18d-6b1e8f1612eb",
104 | "levelId": 120,
105 | "layerDefUid": 82,
106 | "pxOffsetX": 0,
107 | "pxOffsetY": 0,
108 | "visible": true,
109 | "optionalRules": [],
110 | "intGridCsv": [],
111 | "autoLayerTiles": [],
112 | "seed": 1804637,
113 | "overrideTilesetUid": null,
114 | "gridTiles": [],
115 | "entityInstances": []
116 | },
117 | {
118 | "__identifier": "EntityWithTag",
119 | "__type": "Entities",
120 | "__cWid": 16,
121 | "__cHei": 16,
122 | "__gridSize": 16,
123 | "__opacity": 1,
124 | "__pxTotalOffsetX": 0,
125 | "__pxTotalOffsetY": 0,
126 | "__tilesetDefUid": null,
127 | "__tilesetRelPath": null,
128 | "iid": "b1e33f72-7820-11ed-b18d-b79666e3e725",
129 | "levelId": 120,
130 | "layerDefUid": 118,
131 | "pxOffsetX": 0,
132 | "pxOffsetY": 0,
133 | "visible": true,
134 | "optionalRules": [],
135 | "intGridCsv": [],
136 | "autoLayerTiles": [],
137 | "seed": 5544938,
138 | "overrideTilesetUid": null,
139 | "gridTiles": [],
140 | "entityInstances": []
141 | },
142 | {
143 | "__identifier": "EntityTest",
144 | "__type": "Entities",
145 | "__cWid": 16,
146 | "__cHei": 16,
147 | "__gridSize": 16,
148 | "__opacity": 1,
149 | "__pxTotalOffsetX": 0,
150 | "__pxTotalOffsetY": 0,
151 | "__tilesetDefUid": null,
152 | "__tilesetRelPath": null,
153 | "iid": "b1e33f73-7820-11ed-b18d-c3f6df89dcec",
154 | "levelId": 120,
155 | "layerDefUid": 4,
156 | "pxOffsetX": 0,
157 | "pxOffsetY": 0,
158 | "visible": true,
159 | "optionalRules": [],
160 | "intGridCsv": [],
161 | "autoLayerTiles": [],
162 | "seed": 2307796,
163 | "overrideTilesetUid": null,
164 | "gridTiles": [],
165 | "entityInstances": [
166 | {
167 | "__identifier": "Hero",
168 | "__grid": [1,2],
169 | "__pivot": [0.5,1],
170 | "__tags": [],
171 | "__tile": null,
172 | "__smartColor": "#BAF236",
173 | "iid": "bee74f40-7820-11ed-b18d-b5db23763aff",
174 | "width": 16,
175 | "height": 24,
176 | "defUid": 23,
177 | "px": [24,48],
178 | "fieldInstances": [{ "__identifier": "startWeapon", "__type": "LocalEnum.Weapons", "__value": "Grenade", "__tile": null, "defUid": 39, "realEditorValues": [{
179 | "id": "V_String",
180 | "params": ["Grenade"]
181 | }] }],
182 | "__worldX": 24,
183 | "__worldY": 816
184 | }
185 | ]
186 | },
187 | {
188 | "__identifier": "TileTest",
189 | "__type": "Tiles",
190 | "__cWid": 8,
191 | "__cHei": 8,
192 | "__gridSize": 32,
193 | "__opacity": 1,
194 | "__pxTotalOffsetX": 0,
195 | "__pxTotalOffsetY": 0,
196 | "__tilesetDefUid": 14,
197 | "__tilesetRelPath": "Minecraft_texture_pack.gif",
198 | "iid": "b1e33f74-7820-11ed-b18d-a93114fcbf75",
199 | "levelId": 120,
200 | "layerDefUid": 15,
201 | "pxOffsetX": 0,
202 | "pxOffsetY": 0,
203 | "visible": true,
204 | "optionalRules": [],
205 | "intGridCsv": [],
206 | "autoLayerTiles": [],
207 | "seed": 7003341,
208 | "overrideTilesetUid": null,
209 | "gridTiles": [],
210 | "entityInstances": []
211 | },
212 | {
213 | "__identifier": "IntGridTest",
214 | "__type": "IntGrid",
215 | "__cWid": 16,
216 | "__cHei": 16,
217 | "__gridSize": 16,
218 | "__opacity": 0.62,
219 | "__pxTotalOffsetX": 0,
220 | "__pxTotalOffsetY": 0,
221 | "__tilesetDefUid": null,
222 | "__tilesetRelPath": null,
223 | "iid": "b1e33f75-7820-11ed-b18d-6792610805ca",
224 | "levelId": 120,
225 | "layerDefUid": 13,
226 | "pxOffsetX": 0,
227 | "pxOffsetY": 0,
228 | "visible": true,
229 | "optionalRules": [],
230 | "intGridCsv": [
231 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
232 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
233 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
234 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
235 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
236 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
237 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
238 | 0,0,0,0,0,0,0,0,0,0,0
239 | ],
240 | "autoLayerTiles": [],
241 | "seed": 3817194,
242 | "overrideTilesetUid": null,
243 | "gridTiles": [],
244 | "entityInstances": []
245 | },
246 | {
247 | "__identifier": "IntGrid8",
248 | "__type": "IntGrid",
249 | "__cWid": 32,
250 | "__cHei": 32,
251 | "__gridSize": 8,
252 | "__opacity": 1,
253 | "__pxTotalOffsetX": 4,
254 | "__pxTotalOffsetY": 4,
255 | "__tilesetDefUid": null,
256 | "__tilesetRelPath": null,
257 | "iid": "b1e33f76-7820-11ed-b18d-33642a8a18c6",
258 | "levelId": 120,
259 | "layerDefUid": 87,
260 | "pxOffsetX": 0,
261 | "pxOffsetY": 0,
262 | "visible": true,
263 | "optionalRules": [],
264 | "intGridCsv": [
265 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
266 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
267 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
268 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
269 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
270 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
271 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
272 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
273 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
274 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
275 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
276 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
277 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
278 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
279 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
280 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
281 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
282 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
283 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
284 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
285 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
286 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
287 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
288 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
289 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
290 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
291 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
292 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
293 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
294 | 0,0,0,0,0,0,0,0,0
295 | ],
296 | "autoLayerTiles": [],
297 | "seed": 4152312,
298 | "overrideTilesetUid": null,
299 | "gridTiles": [],
300 | "entityInstances": []
301 | }
302 | ],
303 | "__neighbours": []
304 | }
--------------------------------------------------------------------------------
/samples/_assets/unitTest/World2_Level_0.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "1.5.3",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "World2_Level_0",
12 | "iid": "746c2ab0-c640-11ed-ad34-b9f1e407c5b4",
13 | "uid": 121,
14 | "worldX": 0,
15 | "worldY": 0,
16 | "worldDepth": 0,
17 | "pxWid": 256,
18 | "pxHei": 256,
19 | "__bgColor": "#7F8093",
20 | "bgColor": null,
21 | "useAutoIdentifier": true,
22 | "bgRelPath": null,
23 | "bgPos": null,
24 | "bgPivotX": 0.5,
25 | "bgPivotY": 0.5,
26 | "__smartColor": "#B9B9C4",
27 | "__bgPos": null,
28 | "externalRelPath": null,
29 | "fieldInstances": [
30 | { "__identifier": "level_int", "__type": "Int", "__value": 0, "__tile": null, "defUid": 93, "realEditorValues": [] },
31 | { "__identifier": "level_string", "__type": "String", "__value": "", "__tile": null, "defUid": 94, "realEditorValues": [] },
32 | { "__identifier": "level_reward", "__type": "ExternEnum.DroppedItemType", "__value": null, "__tile": null, "defUid": 95, "realEditorValues": [] },
33 | { "__identifier": "lowercase_enum", "__type": "Array", "__value": [], "__tile": null, "defUid": 106, "realEditorValues": [] }
34 | ],
35 | "layerInstances": [
36 | {
37 | "__identifier": "IntGrid_AutoLayer",
38 | "__type": "IntGrid",
39 | "__cWid": 32,
40 | "__cHei": 32,
41 | "__gridSize": 8,
42 | "__opacity": 1,
43 | "__pxTotalOffsetX": 0,
44 | "__pxTotalOffsetY": 0,
45 | "__tilesetDefUid": 46,
46 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
47 | "iid": "746c2ab1-c640-11ed-ad34-fb2471a87c8b",
48 | "levelId": 121,
49 | "layerDefUid": 41,
50 | "pxOffsetX": 0,
51 | "pxOffsetY": 0,
52 | "visible": true,
53 | "optionalRules": [],
54 | "intGridCsv": [
55 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
59 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
60 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
65 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
66 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
68 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
69 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
70 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
78 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
79 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
80 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
81 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
82 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
83 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 | 0,0,0,0,0,0,0,0,0
85 | ],
86 | "autoLayerTiles": [],
87 | "seed": 9488732,
88 | "overrideTilesetUid": null,
89 | "gridTiles": [],
90 | "entityInstances": []
91 | },
92 | {
93 | "__identifier": "Pure_AutoLayer",
94 | "__type": "AutoLayer",
95 | "__cWid": 32,
96 | "__cHei": 32,
97 | "__gridSize": 8,
98 | "__opacity": 1,
99 | "__pxTotalOffsetX": 0,
100 | "__pxTotalOffsetY": 0,
101 | "__tilesetDefUid": 46,
102 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
103 | "iid": "746c2ab2-c640-11ed-ad34-c1e8f59038fd",
104 | "levelId": 121,
105 | "layerDefUid": 82,
106 | "pxOffsetX": 0,
107 | "pxOffsetY": 0,
108 | "visible": true,
109 | "optionalRules": [],
110 | "intGridCsv": [],
111 | "autoLayerTiles": [],
112 | "seed": 2752519,
113 | "overrideTilesetUid": null,
114 | "gridTiles": [],
115 | "entityInstances": []
116 | },
117 | {
118 | "__identifier": "EntityWithTag",
119 | "__type": "Entities",
120 | "__cWid": 16,
121 | "__cHei": 16,
122 | "__gridSize": 16,
123 | "__opacity": 1,
124 | "__pxTotalOffsetX": 0,
125 | "__pxTotalOffsetY": 0,
126 | "__tilesetDefUid": null,
127 | "__tilesetRelPath": null,
128 | "iid": "746c2ab3-c640-11ed-ad34-bbe9b1181dc1",
129 | "levelId": 121,
130 | "layerDefUid": 118,
131 | "pxOffsetX": 0,
132 | "pxOffsetY": 0,
133 | "visible": true,
134 | "optionalRules": [],
135 | "intGridCsv": [],
136 | "autoLayerTiles": [],
137 | "seed": 3039604,
138 | "overrideTilesetUid": null,
139 | "gridTiles": [],
140 | "entityInstances": []
141 | },
142 | {
143 | "__identifier": "EntityTest",
144 | "__type": "Entities",
145 | "__cWid": 16,
146 | "__cHei": 16,
147 | "__gridSize": 16,
148 | "__opacity": 1,
149 | "__pxTotalOffsetX": 0,
150 | "__pxTotalOffsetY": 0,
151 | "__tilesetDefUid": null,
152 | "__tilesetRelPath": null,
153 | "iid": "746c2ab4-c640-11ed-ad34-594e17ac196c",
154 | "levelId": 121,
155 | "layerDefUid": 4,
156 | "pxOffsetX": 0,
157 | "pxOffsetY": 0,
158 | "visible": true,
159 | "optionalRules": [],
160 | "intGridCsv": [],
161 | "autoLayerTiles": [],
162 | "seed": 486717,
163 | "overrideTilesetUid": null,
164 | "gridTiles": [],
165 | "entityInstances": []
166 | },
167 | {
168 | "__identifier": "TileTest",
169 | "__type": "Tiles",
170 | "__cWid": 8,
171 | "__cHei": 8,
172 | "__gridSize": 32,
173 | "__opacity": 1,
174 | "__pxTotalOffsetX": 0,
175 | "__pxTotalOffsetY": 0,
176 | "__tilesetDefUid": 14,
177 | "__tilesetRelPath": "Minecraft_texture_pack.gif",
178 | "iid": "746c2ab5-c640-11ed-ad34-45684508f2a2",
179 | "levelId": 121,
180 | "layerDefUid": 15,
181 | "pxOffsetX": 0,
182 | "pxOffsetY": 0,
183 | "visible": true,
184 | "optionalRules": [],
185 | "intGridCsv": [],
186 | "autoLayerTiles": [],
187 | "seed": 2524189,
188 | "overrideTilesetUid": null,
189 | "gridTiles": [],
190 | "entityInstances": []
191 | },
192 | {
193 | "__identifier": "IntGridTest",
194 | "__type": "IntGrid",
195 | "__cWid": 16,
196 | "__cHei": 16,
197 | "__gridSize": 16,
198 | "__opacity": 0.62,
199 | "__pxTotalOffsetX": 0,
200 | "__pxTotalOffsetY": 0,
201 | "__tilesetDefUid": null,
202 | "__tilesetRelPath": null,
203 | "iid": "746c2ab6-c640-11ed-ad34-c9abfa814d11",
204 | "levelId": 121,
205 | "layerDefUid": 13,
206 | "pxOffsetX": 0,
207 | "pxOffsetY": 0,
208 | "visible": true,
209 | "optionalRules": [],
210 | "intGridCsv": [
211 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
212 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
213 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
214 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
215 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
216 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
217 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
218 | 0,0,0,0,0,0,0,0,0,0,0
219 | ],
220 | "autoLayerTiles": [],
221 | "seed": 9866733,
222 | "overrideTilesetUid": null,
223 | "gridTiles": [],
224 | "entityInstances": []
225 | },
226 | {
227 | "__identifier": "IntGrid8",
228 | "__type": "IntGrid",
229 | "__cWid": 32,
230 | "__cHei": 32,
231 | "__gridSize": 8,
232 | "__opacity": 1,
233 | "__pxTotalOffsetX": 4,
234 | "__pxTotalOffsetY": 4,
235 | "__tilesetDefUid": null,
236 | "__tilesetRelPath": null,
237 | "iid": "746c2ab7-c640-11ed-ad34-71cebfe841cc",
238 | "levelId": 121,
239 | "layerDefUid": 87,
240 | "pxOffsetX": 0,
241 | "pxOffsetY": 0,
242 | "visible": true,
243 | "optionalRules": [],
244 | "intGridCsv": [
245 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
246 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
247 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
248 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
249 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
250 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
251 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
252 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
253 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
254 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
255 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
256 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
257 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
258 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
259 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
260 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
261 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
262 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
263 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
264 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
265 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
266 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
267 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
268 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
269 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
270 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
271 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
272 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
273 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
274 | 0,0,0,0,0,0,0,0,0
275 | ],
276 | "autoLayerTiles": [],
277 | "seed": 1549651,
278 | "overrideTilesetUid": null,
279 | "gridTiles": [],
280 | "entityInstances": []
281 | }
282 | ],
283 | "__neighbours": []
284 | }
--------------------------------------------------------------------------------
/samples/_assets/unitTest/v1_4_0.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "1.5.3",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "v1_4_0",
12 | "iid": "fdf5dd10-3b70-11ee-a4c1-2d98aa7c2075",
13 | "uid": 122,
14 | "worldX": 0,
15 | "worldY": 1280,
16 | "worldDepth": 0,
17 | "pxWid": 256,
18 | "pxHei": 256,
19 | "__bgColor": "#7F8093",
20 | "bgColor": null,
21 | "useAutoIdentifier": false,
22 | "bgRelPath": null,
23 | "bgPos": null,
24 | "bgPivotX": 0.5,
25 | "bgPivotY": 0.5,
26 | "__smartColor": "#B9B9C4",
27 | "__bgPos": null,
28 | "externalRelPath": null,
29 | "fieldInstances": [
30 | { "__identifier": "level_int", "__type": "Int", "__value": 0, "__tile": null, "defUid": 93, "realEditorValues": [] },
31 | { "__identifier": "level_string", "__type": "String", "__value": "", "__tile": null, "defUid": 94, "realEditorValues": [] },
32 | { "__identifier": "level_reward", "__type": "ExternEnum.DroppedItemType", "__value": null, "__tile": null, "defUid": 95, "realEditorValues": [] },
33 | { "__identifier": "lowercase_enum", "__type": "Array", "__value": [], "__tile": null, "defUid": 106, "realEditorValues": [] }
34 | ],
35 | "layerInstances": [
36 | {
37 | "__identifier": "IntGrid_AutoLayer",
38 | "__type": "IntGrid",
39 | "__cWid": 32,
40 | "__cHei": 32,
41 | "__gridSize": 8,
42 | "__opacity": 1,
43 | "__pxTotalOffsetX": 0,
44 | "__pxTotalOffsetY": 0,
45 | "__tilesetDefUid": 46,
46 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
47 | "iid": "fdf5dd11-3b70-11ee-a4c1-6b9ec23ac76b",
48 | "levelId": 122,
49 | "layerDefUid": 41,
50 | "pxOffsetX": 0,
51 | "pxOffsetY": 0,
52 | "visible": true,
53 | "optionalRules": [],
54 | "intGridCsv": [
55 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
59 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
60 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
65 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
66 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
68 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
69 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
70 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
77 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
78 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
79 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
80 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
81 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
82 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
83 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 | 0,0,0,0,0,0,0,0,0
85 | ],
86 | "autoLayerTiles": [],
87 | "seed": 1878600,
88 | "overrideTilesetUid": null,
89 | "gridTiles": [],
90 | "entityInstances": []
91 | },
92 | {
93 | "__identifier": "Pure_AutoLayer",
94 | "__type": "AutoLayer",
95 | "__cWid": 32,
96 | "__cHei": 32,
97 | "__gridSize": 8,
98 | "__opacity": 1,
99 | "__pxTotalOffsetX": 0,
100 | "__pxTotalOffsetY": 0,
101 | "__tilesetDefUid": 46,
102 | "__tilesetRelPath": "Cavernas_by_Adam_Saltsman-Extended.png",
103 | "iid": "fdf5dd12-3b70-11ee-a4c1-2775e4f1138a",
104 | "levelId": 122,
105 | "layerDefUid": 82,
106 | "pxOffsetX": 0,
107 | "pxOffsetY": 0,
108 | "visible": true,
109 | "optionalRules": [],
110 | "intGridCsv": [],
111 | "autoLayerTiles": [],
112 | "seed": 9183880,
113 | "overrideTilesetUid": null,
114 | "gridTiles": [],
115 | "entityInstances": []
116 | },
117 | {
118 | "__identifier": "EntityWithTag",
119 | "__type": "Entities",
120 | "__cWid": 16,
121 | "__cHei": 16,
122 | "__gridSize": 16,
123 | "__opacity": 1,
124 | "__pxTotalOffsetX": 0,
125 | "__pxTotalOffsetY": 0,
126 | "__tilesetDefUid": null,
127 | "__tilesetRelPath": null,
128 | "iid": "fdf60420-3b70-11ee-a4c1-87adcca9456d",
129 | "levelId": 122,
130 | "layerDefUid": 118,
131 | "pxOffsetX": 0,
132 | "pxOffsetY": 0,
133 | "visible": true,
134 | "optionalRules": [],
135 | "intGridCsv": [],
136 | "autoLayerTiles": [],
137 | "seed": 7863463,
138 | "overrideTilesetUid": null,
139 | "gridTiles": [],
140 | "entityInstances": []
141 | },
142 | {
143 | "__identifier": "EntityTest",
144 | "__type": "Entities",
145 | "__cWid": 16,
146 | "__cHei": 16,
147 | "__gridSize": 16,
148 | "__opacity": 1,
149 | "__pxTotalOffsetX": 0,
150 | "__pxTotalOffsetY": 0,
151 | "__tilesetDefUid": null,
152 | "__tilesetRelPath": null,
153 | "iid": "fdf60421-3b70-11ee-a4c1-5bde7a085fb6",
154 | "levelId": 122,
155 | "layerDefUid": 4,
156 | "pxOffsetX": 0,
157 | "pxOffsetY": 0,
158 | "visible": true,
159 | "optionalRules": [],
160 | "intGridCsv": [],
161 | "autoLayerTiles": [],
162 | "seed": 5042540,
163 | "overrideTilesetUid": null,
164 | "gridTiles": [],
165 | "entityInstances": [
166 | {
167 | "__identifier": "Hero",
168 | "__grid": [2,5],
169 | "__pivot": [0.5,1],
170 | "__tags": [],
171 | "__tile": null,
172 | "__smartColor": "#BAF236",
173 | "iid": "0fa3ecf0-3b70-11ee-a4c1-b76253be54be",
174 | "width": 16,
175 | "height": 24,
176 | "defUid": 23,
177 | "px": [40,96],
178 | "fieldInstances": [{ "__identifier": "startWeapon", "__type": "LocalEnum.Weapons", "__value": "LongBow", "__tile": null, "defUid": 39, "realEditorValues": [{
179 | "id": "V_String",
180 | "params": ["LongBow"]
181 | }] }],
182 | "__worldX": 40,
183 | "__worldY": 1376
184 | }
185 | ]
186 | },
187 | {
188 | "__identifier": "TileTest",
189 | "__type": "Tiles",
190 | "__cWid": 8,
191 | "__cHei": 8,
192 | "__gridSize": 32,
193 | "__opacity": 1,
194 | "__pxTotalOffsetX": 0,
195 | "__pxTotalOffsetY": 0,
196 | "__tilesetDefUid": 14,
197 | "__tilesetRelPath": "Minecraft_texture_pack.gif",
198 | "iid": "fdf60422-3b70-11ee-a4c1-87ae3b51a044",
199 | "levelId": 122,
200 | "layerDefUid": 15,
201 | "pxOffsetX": 0,
202 | "pxOffsetY": 0,
203 | "visible": true,
204 | "optionalRules": [],
205 | "intGridCsv": [],
206 | "autoLayerTiles": [],
207 | "seed": 8933106,
208 | "overrideTilesetUid": null,
209 | "gridTiles": [],
210 | "entityInstances": []
211 | },
212 | {
213 | "__identifier": "IntGridTest",
214 | "__type": "IntGrid",
215 | "__cWid": 16,
216 | "__cHei": 16,
217 | "__gridSize": 16,
218 | "__opacity": 0.62,
219 | "__pxTotalOffsetX": 0,
220 | "__pxTotalOffsetY": 0,
221 | "__tilesetDefUid": null,
222 | "__tilesetRelPath": null,
223 | "iid": "fdf60423-3b70-11ee-a4c1-9538d0fb3cbb",
224 | "levelId": 122,
225 | "layerDefUid": 13,
226 | "pxOffsetX": 0,
227 | "pxOffsetY": 0,
228 | "visible": true,
229 | "optionalRules": [],
230 | "intGridCsv": [
231 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
232 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
233 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
234 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
235 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
236 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
237 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
238 | 0,0,0,0,0,0,0,0,0,0,0
239 | ],
240 | "autoLayerTiles": [],
241 | "seed": 6300247,
242 | "overrideTilesetUid": null,
243 | "gridTiles": [],
244 | "entityInstances": []
245 | },
246 | {
247 | "__identifier": "IntGrid8",
248 | "__type": "IntGrid",
249 | "__cWid": 32,
250 | "__cHei": 32,
251 | "__gridSize": 8,
252 | "__opacity": 1,
253 | "__pxTotalOffsetX": 4,
254 | "__pxTotalOffsetY": 4,
255 | "__tilesetDefUid": null,
256 | "__tilesetRelPath": null,
257 | "iid": "fdf60424-3b70-11ee-a4c1-492dd034147d",
258 | "levelId": 122,
259 | "layerDefUid": 87,
260 | "pxOffsetX": 0,
261 | "pxOffsetY": 0,
262 | "visible": true,
263 | "optionalRules": [],
264 | "intGridCsv": [
265 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
266 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
267 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
268 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
269 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
270 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
271 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
272 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
273 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
274 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
275 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
276 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
277 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
278 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
279 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
280 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
281 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
282 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
283 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
284 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
285 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
286 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
287 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
288 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
289 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
290 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
291 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
292 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
293 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
294 | 0,0,0,0,0,0,0,0,0
295 | ],
296 | "autoLayerTiles": [],
297 | "seed": 6555422,
298 | "overrideTilesetUid": null,
299 | "gridTiles": [],
300 | "entityInstances": []
301 | }
302 | ],
303 | "__neighbours": [{ "levelIid": "b32d7710-3b70-11ee-a4c1-ada3a8497e3b", "dir": "<" }]
304 | }
--------------------------------------------------------------------------------
/samples/_initSamples/README.md:
--------------------------------------------------------------------------------
1 | # NOTE
2 |
3 | This class is *not* a sample nor a demo: it only generates the HXML and HTML files of each sample.
4 |
--------------------------------------------------------------------------------
/samples/_initSamples/SamplesInitializer.hx:
--------------------------------------------------------------------------------
1 | /**
2 | NOTE: this class is not a sample nor a demo: it only generates the HXML and HTML files of each sample.
3 | **/
4 |
5 | class SamplesInitializer{
6 | public static function run() {
7 | var baseDir = ".."; // no trailing "/"
8 |
9 | Sys.println("");
10 | Sys.println('NOTE: please check the README for more infos.');
11 | Sys.println("");
12 |
13 |
14 | // List all sample HX files
15 | var hxFiles : Array = [];
16 | var allowedDirs = [ "Heaps -", "Generic -" ];
17 | var pendingDirs = [ baseDir ];
18 | while( pendingDirs.length>0 ) {
19 | var dir = pendingDirs.shift();
20 | for(f in sys.FileSystem.readDirectory(dir)) {
21 | if( sys.FileSystem.isDirectory(dir+"/"+f) ) {
22 | for( allow in allowedDirs )
23 | if( f.indexOf(allow)>=0 ) {
24 | pendingDirs.push(dir+"/"+f);
25 | break;
26 | }
27 | }
28 | else if( dir!=baseDir && f.indexOf(".hx")==f.length-3 )
29 | hxFiles.push( dn.FilePath.fromFile(dir+"/"+f) );
30 | }
31 | }
32 |
33 |
34 | var removeCmdRegEx = ~/--cmd (.*$)/gm;
35 | var allHxmls = [];
36 | var htmlToc = [];
37 | // var htmlToc = hxFiles.map( (fp)->{
38 | // var name = fp.fileName;
39 | // return ' $name ';
40 | // });
41 | for(fp in hxFiles) {
42 | var name = fp.fileName;
43 | var dir = fp.directory;
44 |
45 | // Build HXML
46 | Sys.println('Creating $dir/build.hxml...');
47 | var hxml = StringTools.replace(BASE_HXML, "%name%", name);
48 | hxml = StringTools.replace(hxml, "\t", "");
49 | sys.io.File.saveContent('$dir/build.hxml', hxml );
50 |
51 | // Build HTML
52 | Sys.println('Creating $dir/index.html...');
53 | var html = StringTools.replace( BASE_HTML, "%name%", name );
54 | html = StringTools.replace( html, "%toc%", htmlToc.join("") );
55 |
56 | sys.io.File.saveContent('$dir/index.html', html );
57 | allHxmls.push('$dir/build.hxml');
58 | }
59 |
60 | // Create buildAll.hxml
61 | var allHxml = allHxmls.map( path->{
62 | var fp = dn.FilePath.fromFile(path);
63 | fp.makeRelativeTo(baseDir);
64 | return '
65 | --cwd "${fp.directory}"
66 | "${fp.fileWithExt}"
67 | --next
68 | --cwd ..
69 | ';
70 | } ).join("--next\n");
71 | allHxml = StringTools.replace(allHxml, "\t", "");
72 | sys.io.File.saveContent('$baseDir/buildAll.hxml', allHxml);
73 |
74 | Sys.println('Generated ${allHxmls.length} sample build files successfully.');
75 | }
76 |
77 | public static function print(msg:String) { // Used in HXML macro calls
78 | Sys.println("");
79 | Sys.println(msg);
80 | }
81 |
82 |
83 |
84 |
85 | static var BASE_HXML = "
86 | # %name% (Javascript/WebGL)
87 | -cp .
88 | -cp ../_srcCommon
89 | -cp ../../src
90 | -lib heaps
91 | -lib deepnightLibs
92 | -D resourcesPath=../_assets
93 | --dce full
94 | -main %name%
95 | -js _javascript.js
96 |
97 | # %name% (Hashlink)
98 | --next
99 | -cp .
100 | -cp ../_srcCommon
101 | -cp ../../src
102 | -lib heaps
103 | -lib deepnightLibs
104 | -D resourcesPath=../_assets
105 | -lib hlsdl
106 | --dce full
107 | -main %name%
108 | -hl _hashlink.hl
109 | ";
110 |
111 |
112 | static var BASE_HTML = '
113 |
114 |
115 |
116 |
117 | %name%
118 |
161 |
162 |
163 |
164 |
165 | Failed to load JS script! Please build it using the HXML file (run: haxe build.hxml
).
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | ';
174 | }
175 |
--------------------------------------------------------------------------------
/samples/_initSamples/initSamples.hxml:
--------------------------------------------------------------------------------
1 | -lib deepnightLibs
2 | --macro SamplesInitializer.run()
3 | --macro SamplesInitializer.print("Compiling all samples...")
4 |
5 | --next
6 | --cmd haxe --cwd .. buildAll.hxml
7 |
8 | --next
9 | -lib deepnightLibs
10 | --macro SamplesInitializer.print("Done!")
--------------------------------------------------------------------------------
/samples/_srcCommon/ExternCastleDbTest.hx:
--------------------------------------------------------------------------------
1 | private typedef Init = haxe.macro.MacroType<[cdb.Module.build("sample.cdb")]>;
2 |
--------------------------------------------------------------------------------
/samples/_srcCommon/ExternEnumTest.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This enum file is imported in the LDtk project.
3 | It demonstrates the ability for LDtk to use external Enums as entity field values.
4 | **/
5 |
6 | enum DroppedItemType {
7 | Food;
8 | Gold;
9 | Ammo;
10 | Key;
11 | // SomeNewObject;
12 | }
13 |
14 | enum SomeEnum {
15 | Foo;
16 | Bar;
17 | Pouet;
18 | }
--------------------------------------------------------------------------------
/samples/_srcCommon/LdtkProject.hx:
--------------------------------------------------------------------------------
1 | /**
2 | This file will contain all the classes and types generated
3 | from the "sample.ldtk" project
4 | **/
5 |
6 | private typedef _Tmp = haxe.macro.MacroType<[
7 | ldtk.Project.build("../_assets/sample.ldtk")
8 | ]>;
--------------------------------------------------------------------------------
/samples/buildAll.hxml:
--------------------------------------------------------------------------------
1 |
2 | --cwd "Generic - Read project"
3 | "build.hxml"
4 | --next
5 | --cwd ..
6 | --next
7 |
8 | --cwd "Heaps - Object tiles"
9 | "build.hxml"
10 | --next
11 | --cwd ..
12 | --next
13 |
14 | --cwd "Heaps - Render full world"
15 | "build.hxml"
16 | --next
17 | --cwd ..
18 | --next
19 |
20 | --cwd "Heaps - Render IntGrid layer"
21 | "build.hxml"
22 | --next
23 | --cwd ..
24 | --next
25 |
26 | --cwd "Heaps - Render tile layers"
27 | "build.hxml"
28 | --next
29 | --cwd ..
30 |
--------------------------------------------------------------------------------
/src/ldtk/Entity.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | class Entity {
4 | var untypedProject : ldtk.Project;
5 |
6 | /** Original JSON object **/
7 | public var json(default,null) : ldtk.Json.EntityInstanceJson;
8 |
9 | /** Original entity definition JSON object **/
10 | public var defJson(default,null) : ldtk.Json.EntityDefJson;
11 |
12 | public var identifier : String;
13 |
14 | /** Unique instance identifier **/
15 | public var iid : String;
16 |
17 | /** Grid-based X coordinate **/
18 | public var cx : Int;
19 |
20 | /** Grid-based Y coordinate **/
21 | public var cy : Int;
22 |
23 | /** Pixel-based X coordinate **/
24 | public var pixelX : Int;
25 |
26 | /** Pixel-based Y coordinate **/
27 | public var pixelY : Int;
28 |
29 | /** Pivot X coord (0-1) **/
30 | public var pivotX : Float;
31 |
32 | /** Pivot Y coord (0-1) **/
33 | public var pivotY : Float;
34 |
35 | /** Pixel-based X world coordinate **/
36 | public var worldPixelX : Int;
37 |
38 | /** Pixel-based Y world coordinate **/
39 | public var worldPixelY : Int;
40 |
41 | /** Width in pixels **/
42 | public var width : Int;
43 |
44 | /** Height in pixels**/
45 | public var height : Int;
46 |
47 | /** Tile infos if the entity has one (it could have be overridden by a Field value, such as Enums) **/
48 | public var tileInfos : Null;
49 |
50 | var _fields : Map = new Map();
51 |
52 |
53 | public function new(p:ldtk.Project, json:ldtk.Json.EntityInstanceJson) {
54 | untypedProject = p;
55 | this.json = json;
56 | this.defJson = p.getEntityDefJson(json.defUid);
57 | identifier = json.__identifier;
58 | iid = json.iid;
59 | cx = json.__grid[0];
60 | cy = json.__grid[1];
61 | pixelX = json.px[0];
62 | pixelY = json.px[1];
63 | pivotX = json.__pivot==null ? 0 : json.__pivot[0];
64 | pivotY = json.__pivot==null ? 0 : json.__pivot[1];
65 | worldPixelX = json.__worldX;
66 | worldPixelY = json.__worldY;
67 | width = json.width;
68 | height = json.height;
69 |
70 | tileInfos = json.__tile;
71 |
72 | p._assignFieldInstanceValues(this, json.fieldInstances);
73 | }
74 |
75 |
76 | #if heaps
77 | public function getTile() : Null {
78 | if( tileInfos==null )
79 | return null;
80 |
81 | var tileset = untypedProject._untypedTilesets.get(tileInfos.tilesetUid);
82 | if( tileset==null )
83 | return null;
84 |
85 | return tileset.getFreeTile(tileInfos.x, tileInfos.y, tileInfos.w, tileInfos.h);
86 | }
87 | #end
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/ldtk/Layer.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | import ldtk.Json;
4 |
5 | class Layer {
6 | var untypedProject: ldtk.Project;
7 |
8 | /** Original JSON object **/
9 | public var json(default,null) : LayerInstanceJson;
10 |
11 | /** Original layer definition JSON object **/
12 | public var defJson(default,null) : LayerDefJson;
13 |
14 | public var identifier : String;
15 | public var type : LayerType;
16 |
17 | /** Unique instance identifier **/
18 | public var iid : String;
19 |
20 | /** Layer instance visibility **/
21 | public var visible : Bool;
22 |
23 | /** Grid size in pixels **/
24 | public var gridSize : Int;
25 |
26 | /** Grid-based layer width **/
27 | public var cWid : Int;
28 | /** Grid-based layer height **/
29 | public var cHei : Int;
30 |
31 | /** Pixel-based layer width **/
32 | public var pxWid : Int;
33 | /** Pixel-based layer height **/
34 | public var pxHei : Int;
35 |
36 | /**
37 | Pixel-based layer X offset (includes both instance and definition offsets)
38 | **/
39 | public var pxTotalOffsetX: Int;
40 |
41 | /**
42 | Pixel-based layer Y offset (includes both instance and definition offsets)
43 | **/
44 | public var pxTotalOffsetY : Int;
45 |
46 | /** Layer opacity (0-1) **/
47 | public var opacity : Float;
48 |
49 |
50 | public function new(p:ldtk.Project, json:ldtk.Json.LayerInstanceJson) {
51 | this.json = json;
52 | this.defJson = p.getLayerDefJson(json.layerDefUid);
53 | untypedProject = p;
54 | identifier = json.__identifier;
55 | type =
56 | try LayerType.createByName(json.__type)
57 | catch(e:Dynamic) throw 'Unknown layer type ${json.__type} in $identifier';
58 | iid = json.iid;
59 | gridSize = json.__gridSize;
60 | cWid = json.__cWid;
61 | cHei = json.__cHei;
62 | pxWid = cWid * json.__gridSize;
63 | pxHei = cHei * json.__gridSize;
64 | pxTotalOffsetX = json.__pxTotalOffsetX;
65 | pxTotalOffsetY = json.__pxTotalOffsetY;
66 | opacity = json.__opacity;
67 | visible = json.visible==true;
68 | }
69 |
70 | /** Print class debug info **/
71 | @:keep public function toString() {
72 | return 'ldtk.Layer[#$identifier, type=$type]';
73 | }
74 |
75 |
76 | /**
77 | Return TRUE if grid-based coordinates are within layer bounds.
78 | **/
79 | public inline function isCoordValid(cx,cy) {
80 | return cx>=0 && cx=0 && cy no flipping, 1=> X flip, 2=> Y flip, 3=> X and Y flips **/
15 | var flips: Int;
16 |
17 | /** Opacity (0-1)**/
18 | var alpha: Float;
19 |
20 | /** ID of the auto-rule that generated this tile **/
21 | var ruleId: Int;
22 |
23 | /** Coord ID of the auto-rule that generated this tile **/
24 | var coordId: Int;
25 | }
26 |
27 |
28 | class Layer_AutoLayer extends ldtk.Layer {
29 | /**
30 | A single array containing all AutoLayer tiles informations, in "render" order
31 | **/
32 | public var autoTiles : Array;
33 |
34 |
35 | /** Getter to layer untyped Tileset instance. The typed value is created in macro. **/
36 | var untypedTileset(get,never) : ldtk.Tileset;
37 | inline function get_untypedTileset() return untypedProject._untypedTilesets.get(tilesetUid);
38 |
39 | /** Tileset UID **/
40 | public var tilesetUid(default,null) : Int;
41 |
42 |
43 | public function new(p,json) {
44 | super(p,json);
45 |
46 | autoTiles = [];
47 | tilesetUid = json.__tilesetDefUid;
48 |
49 | for(jsonAutoTile in json.autoLayerTiles)
50 | autoTiles.push({
51 | tileId: jsonAutoTile.t,
52 | flips: jsonAutoTile.f,
53 | alpha: jsonAutoTile.a,
54 | renderX: jsonAutoTile.px[0],
55 | renderY: jsonAutoTile.px[1],
56 | ruleId: jsonAutoTile.d[0],
57 | coordId: jsonAutoTile.d[1],
58 | });
59 | }
60 |
61 |
62 |
63 | #if !macro
64 |
65 | #if heaps
66 | /**
67 | Render layer to a `h2d.TileGroup`. If `target` isn't provided, a new h2d.TileGroup is created. If `target` is provided, it **must** have the same tile source as the layer tileset!
68 | **/
69 | public inline function render(?target:h2d.TileGroup) : h2d.TileGroup {
70 | if( target==null )
71 | target = new h2d.TileGroup( untypedTileset.getAtlasTile() );
72 |
73 | for( autoTile in autoTiles )
74 | target.addAlpha(
75 | autoTile.renderX + pxTotalOffsetX,
76 | autoTile.renderY + pxTotalOffsetY,
77 | autoTile.alpha,
78 | untypedTileset.getAutoLayerTile(autoTile)
79 | );
80 |
81 | return target;
82 | }
83 | #end
84 |
85 |
86 | #if flixel
87 | /**
88 | Render layer to a `FlxGroup`. If `target` isn't provided, a new one is created.
89 | **/
90 | public function render(?target:flixel.group.FlxSpriteGroup) : flixel.group.FlxSpriteGroup {
91 | if( target==null ) {
92 | target = new flixel.group.FlxSpriteGroup();
93 | target.active = false;
94 | }
95 |
96 |
97 | for( autoTile in autoTiles ) {
98 | var s = new flixel.FlxSprite(autoTile.renderX, autoTile.renderY);
99 | s.flipX = autoTile.flips & 1 != 0;
100 | s.flipY = autoTile.flips & 2 != 0;
101 | s.frame = untypedTileset.getFrame(autoTile.tileId);
102 | target.add(s);
103 | }
104 |
105 | return target;
106 | }
107 | #end
108 |
109 | #end
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/src/ldtk/Layer_Entities.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | class Layer_Entities extends ldtk.Layer {
4 | var _entities : Array = [];
5 |
6 | public function new(p,json) {
7 | super(p,json);
8 |
9 | for(json in json.entityInstances) {
10 | var e = _instanciateEntity(json);
11 | _entities.push(e);
12 |
13 | if( Reflect.field(this, "all_"+e.identifier)==null )
14 | Reflect.setField(this, "all_"+e.identifier, []);
15 |
16 | var arr : Array = Reflect.field(this, "all_"+e.identifier);
17 | arr.push(e);
18 | }
19 | }
20 |
21 | function _instanciateEntity(json:ldtk.Json.EntityInstanceJson) : Entity {
22 | return null; // overriden by Macros.hx
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ldtk/Layer_IntGrid.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | class Layer_IntGrid extends ldtk.Layer {
4 | var valueInfos : Map, color:UInt }> = new Map();
5 |
6 | /**
7 | IntGrid integer values, map is based on coordIds
8 | **/
9 | public var intGrid : Map = new Map();
10 |
11 |
12 | public function new(p,json) {
13 | super(p,json);
14 |
15 | if( json.intGridCsv!=null ) {
16 | // Read new CSV format
17 | for(i in 0...json.intGridCsv.length)
18 | if( json.intGridCsv[i]>=0 )
19 | intGrid.set(i, json.intGridCsv[i]);
20 | }
21 | else {
22 | // Read old pre-CSV format
23 | for(ig in json.intGrid)
24 | intGrid.set(ig.coordId, ig.v+1);
25 | }
26 | }
27 |
28 | /**
29 | Get the Integer value at selected coordinates
30 |
31 | Return -1 if none.
32 | **/
33 | public inline function getInt(cx:Int, cy:Int) {
34 | return isCoordValid(cx,cy) ? intGrid.get( getCoordId(cx,cy) ) : 0;
35 | // return !isCoordValid(cx,cy) || !intGrid.exists( getCoordId(cx,cy) ) ? 0 : intGrid.get( getCoordId(cx,cy) );
36 | }
37 |
38 | /**
39 | Return TRUE if there is any value at selected coordinates.
40 |
41 | Optional parameter "val" allows to check for a specific integer value.
42 | **/
43 | public inline function hasValue(cx:Int, cy:Int, val=0) {
44 | return !isCoordValid(cx,cy)
45 | ? false
46 | : val==0
47 | ? intGrid.get( getCoordId(cx,cy) )>0
48 | : intGrid.get( getCoordId(cx,cy) )==val;
49 | }
50 |
51 |
52 | inline function getValueInfos(v:Int) {
53 | return valueInfos.get(v);
54 | }
55 |
56 | /**
57 | Get the value String identifier at selected coordinates.
58 |
59 | Return null if none.
60 | **/
61 | public inline function getName(cx:Int, cy:Int) : Null {
62 | return !hasValue(cx,cy) ? null : getValueInfos(getInt(cx,cy)).identifier;
63 | }
64 |
65 | /**
66 | Get the value color (0xrrggbb Unsigned-Int format) at selected coordinates.
67 |
68 | Return null if none.
69 | **/
70 | public inline function getColorInt(cx:Int, cy:Int) : Null {
71 | return !hasValue(cx,cy) ? null : getValueInfos(getInt(cx,cy)).color;
72 | }
73 |
74 | /**
75 | Get the value color ("#rrggbb" string format) at selected coordinates.
76 |
77 | Return null if none.
78 | **/
79 | public inline function getColorHex(cx:Int, cy:Int) : Null {
80 | return !hasValue(cx,cy) ? null : ldtk.Project.intToHex( getValueInfos(getInt(cx,cy)).color );
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/ldtk/Layer_IntGrid_AutoLayer.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | class Layer_IntGrid_AutoLayer extends ldtk.Layer_IntGrid {
4 | /**
5 | A single array containing all AutoLayer tiles informations, in "render" order (ie. 1st is behind, last is on top)
6 | **/
7 | public var autoTiles : Array;
8 |
9 |
10 | /** Getter to layer untyped Tileset instance. The typed value is created in macro. **/
11 | public var untypedTileset(get,never) : ldtk.Tileset;
12 | inline function get_untypedTileset() return untypedProject._untypedTilesets.get(tilesetUid);
13 |
14 | /** Tileset UID **/
15 | public var tilesetUid(default,null) : Int;
16 |
17 |
18 | public function new(p,json) {
19 | super(p,json);
20 |
21 | autoTiles = [];
22 | tilesetUid = json.__tilesetDefUid;
23 |
24 | for(jsonAutoTile in json.autoLayerTiles)
25 | autoTiles.push({
26 | tileId: jsonAutoTile.t,
27 | flips: jsonAutoTile.f,
28 | alpha: jsonAutoTile.a,
29 | renderX: jsonAutoTile.px[0],
30 | renderY: jsonAutoTile.px[1],
31 | ruleId: jsonAutoTile.d[0],
32 | coordId: jsonAutoTile.d[1],
33 | });
34 | }
35 |
36 |
37 |
38 | #if !macro
39 |
40 | #if heaps
41 | /**
42 | Render layer to a `h2d.TileGroup`. If `target` isn't provided, a new h2d.TileGroup is created. If `target` is provided, it **must** have the same tile source as the layer tileset!
43 | **/
44 | public inline function render(?target:h2d.TileGroup) : h2d.TileGroup {
45 | if( target==null )
46 | target = new h2d.TileGroup( untypedTileset.getAtlasTile() );
47 |
48 | for( autoTile in autoTiles )
49 | target.addAlpha(
50 | autoTile.renderX + pxTotalOffsetX,
51 | autoTile.renderY + pxTotalOffsetY,
52 | autoTile.alpha,
53 | untypedTileset.getAutoLayerTile(autoTile)
54 | );
55 |
56 | return target;
57 | }
58 | #end
59 |
60 |
61 | #if flixel
62 | /**
63 | Render layer to a `FlxGroup`. If `target` isn't provided, a new one is created.
64 | **/
65 | public function render(?target:flixel.group.FlxSpriteGroup) : flixel.group.FlxSpriteGroup {
66 | if( target==null ) {
67 | target = new flixel.group.FlxSpriteGroup();
68 | target.active = false;
69 | }
70 |
71 |
72 | for( autoTile in autoTiles ) {
73 | var s = new flixel.FlxSprite(autoTile.renderX, autoTile.renderY);
74 | s.flipX = autoTile.flips & 1 != 0;
75 | s.flipY = autoTile.flips & 2 != 0;
76 | s.frame = untypedTileset.getFrame(autoTile.tileId);
77 | target.add(s);
78 | }
79 |
80 | return target;
81 | }
82 | #end
83 |
84 | #end
85 | }
86 |
--------------------------------------------------------------------------------
/src/ldtk/Layer_Tiles.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | class Layer_Tiles extends ldtk.Layer {
4 | var tiles : Map>;
5 |
6 | /** Getter to layer untyped Tileset instance. The typed value is created in macro. **/
7 | var untypedTileset(get,never) : ldtk.Tileset;
8 | inline function get_untypedTileset() return untypedProject._untypedTilesets.get(tilesetUid);
9 |
10 | /** Tileset UID **/
11 | public var tilesetUid(default,null) : Int;
12 |
13 |
14 | public function new(p,json) {
15 | super(p,json);
16 |
17 | tilesetUid = json.__tilesetDefUid;
18 |
19 | tiles = new Map();
20 | for(t in json.gridTiles)
21 | if( !tiles.exists(t.d[0]) )
22 | tiles.set(t.d[0], [{ tileId:t.t, flipBits:t.f }]);
23 | else
24 | tiles.get(t.d[0]).push({ tileId:t.t, flipBits:t.f });
25 |
26 | }
27 |
28 | /**
29 | Return the stack of tiles at coords, or empty array if there is none. To avoid useless memory allocations, you should check `hasAnyTileAt` before using this method.
30 | **/
31 | public inline function getTileStackAt(cx:Int,cy:Int) : Array<{ tileId:Int, flipBits:Int }> {
32 | return isCoordValid(cx,cy) && tiles.exists(getCoordId(cx,cy))
33 | ? tiles.get( getCoordId(cx,cy) )
34 | : [];
35 | }
36 |
37 | /**
38 | Return TRUE if any tile exists at specified coords
39 | **/
40 | public inline function hasAnyTileAt(cx,cy) {
41 | return tiles.exists( getCoordId(cx,cy) );
42 | }
43 |
44 |
45 | #if !macro
46 |
47 | #if heaps
48 | /**
49 | Render layer to a `h2d.TileGroup`. If `target` isn't provided, a new h2d.TileGroup is created. If `target` is provided, it **must** have the same tile source as the layer tileset!
50 | **/
51 | public inline function render(?target:h2d.TileGroup) : h2d.TileGroup {
52 | if( target==null )
53 | target = new h2d.TileGroup( untypedTileset.getAtlasTile() );
54 |
55 | for( cy in 0...cHei )
56 | for( cx in 0...cWid )
57 | if( hasAnyTileAt(cx,cy) ) {
58 | for( tile in getTileStackAt(cx,cy) ) {
59 | target.add(
60 | cx*gridSize + pxTotalOffsetX,
61 | cy*gridSize + pxTotalOffsetY,
62 | untypedTileset.getTile(tile.tileId, tile.flipBits)
63 | );
64 | }
65 | }
66 |
67 | return target;
68 | }
69 | #end
70 |
71 |
72 | #if flixel
73 | /**
74 | Render layer to a `FlxGroup`. If `target` isn't provided, a new one is created.
75 | **/
76 | public function render(?target:flixel.group.FlxSpriteGroup) : flixel.group.FlxSpriteGroup {
77 | if( target==null ) {
78 | target = new flixel.group.FlxSpriteGroup();
79 | target.active = false;
80 | }
81 |
82 |
83 | for( cy in 0...cHei )
84 | for( cx in 0...cWid )
85 | if( hasAnyTileAt(cx,cy) )
86 | for( tile in getTileStackAt(cx,cy) ) {
87 | var s = new flixel.FlxSprite(cx*gridSize + pxTotalOffsetX, cy*gridSize + pxTotalOffsetY);
88 | s.flipX = tile.flipBits & 1 != 0;
89 | s.flipY = tile.flipBits & 2 != 0;
90 | s.frame = untypedTileset.getFrame(tile.tileId);
91 | s.width = gridSize;
92 | s.height = gridSize;
93 | target.add(s);
94 | }
95 |
96 | return target;
97 | }
98 | #end
99 | #end
100 |
101 | }
--------------------------------------------------------------------------------
/src/ldtk/Level.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | enum NeighbourDir {
4 | NorthEastCorner;
5 | NorthWestCorner;
6 | SouthEastCorner;
7 | SouthWestCorner;
8 | North;
9 | South;
10 | West;
11 | East;
12 | SameDepthOverlap;
13 | DepthBelow;
14 | DepthAbove;
15 | }
16 |
17 | typedef LevelBgImage = {
18 | var relFilePath: String;
19 |
20 | /** Top-left X coordinate of background image **/
21 | var topLeftX: Int;
22 |
23 | /** Top-left Y coordinate of background image **/
24 | var topLeftY: Int;
25 |
26 | /** X scale factor of background image **/
27 | var scaleX: Float;
28 |
29 | /** Y scale factor of background image **/
30 | var scaleY: Float;
31 |
32 | /** Cropped sub rectangle in background image **/
33 | var cropRect: {
34 | x: Float,
35 | y: Float,
36 | w: Float,
37 | h: Float,
38 | }
39 | }
40 |
41 | class Level {
42 | var untypedProject: ldtk.Project; // WARNING: the var type isn't the "complete" project type as generated by macros!
43 |
44 | /** Original parsed JSON object **/
45 | public var json(default,null) : ldtk.Json.LevelJson;
46 |
47 | public var iid(default,null) : String;
48 | public var uid(default,null) : Int;
49 | public var identifier(default,null) : String;
50 | public var pxWid(default,null) : Int;
51 | public var pxHei(default,null) : Int;
52 | public var worldX(default,null) : Int;
53 | public var worldY(default,null) : Int;
54 | public var worldDepth(default,null) : Int;
55 |
56 | /** Level background color (as Hex "#rrggbb") **/
57 | public var bgColor_hex(default,null): String;
58 |
59 | /** Level background color (as Int 0xrrggbb) **/
60 | public var bgColor_int(default,null): UInt;
61 |
62 | @:deprecated("Use bgColor_int instead") @:noCompletion
63 | public var bgColor(get,never) : UInt;
64 | @:noCompletion inline function get_bgColor() return bgColor_int;
65 |
66 | public var allUntypedLayers(default,null) : Array;
67 | public var neighbours : Array<{ levelIid:String, dir: NeighbourDir }>;
68 | public var bgImageInfos(default,null) : Null;
69 |
70 | /** Index in project `levels` array **/
71 | public var arrayIndex(default,null) : Int;
72 |
73 | /** Only exists if levels are stored in separate level files **/
74 | var externalRelPath(default,null) : Null;
75 |
76 |
77 | public function new(project:ldtk.Project, arrayIdx:Int, json:ldtk.Json.LevelJson) {
78 | this.untypedProject = project;
79 | this.arrayIndex = arrayIdx;
80 | fromJson(json);
81 | project._assignFieldInstanceValues(this, json.fieldInstances);
82 | }
83 |
84 | /** Print class debug info **/
85 | @:keep public function toString() {
86 | return 'ldtk.Level[#$identifier, ${pxWid}x$pxHei]';
87 | }
88 |
89 |
90 | /** Parse level JSON **/
91 | function fromJson(json:ldtk.Json.LevelJson) {
92 | this.json = json;
93 | neighbours = [];
94 | allUntypedLayers = [];
95 |
96 | iid = json.iid;
97 | uid = json.uid;
98 | identifier = json.identifier;
99 | pxWid = json.pxWid;
100 | pxHei = json.pxHei;
101 | worldX = json.worldX;
102 | worldY = json.worldY;
103 | worldDepth = json.worldDepth;
104 | bgColor_hex = json.__bgColor;
105 | bgColor_int = Project.hexToInt(json.__bgColor);
106 |
107 | bgImageInfos = json.bgRelPath==null || json.__bgPos==null ? null : {
108 | relFilePath: json.bgRelPath,
109 | topLeftX: json.__bgPos.topLeftPx[0],
110 | topLeftY: json.__bgPos.topLeftPx[1],
111 | scaleX: json.__bgPos.scale[0],
112 | scaleY: json.__bgPos.scale[1],
113 | cropRect: {
114 | x: json.__bgPos.cropRect[0],
115 | y: json.__bgPos.cropRect[1],
116 | w: json.__bgPos.cropRect[2],
117 | h: json.__bgPos.cropRect[3],
118 | },
119 | }
120 |
121 | externalRelPath = json.externalRelPath;
122 |
123 | if( json.layerInstances!=null )
124 | for(json in json.layerInstances)
125 | allUntypedLayers.push( _instanciateLayer(json) );
126 |
127 | if( json.__neighbours!=null )
128 | for(n in json.__neighbours)
129 | neighbours.push({
130 | levelIid: n.levelIid,
131 | dir: switch n.dir {
132 | case "nw": NorthWestCorner;
133 | case "ne": NorthEastCorner;
134 | case "sw": SouthWestCorner;
135 | case "se": SouthEastCorner;
136 |
137 | case "n": North;
138 | case "s": South;
139 | case "w": West;
140 | case "e": East;
141 |
142 | case "<": DepthBelow;
143 | case ">": DepthAbove;
144 | case "o": SameDepthOverlap;
145 |
146 | case _: trace("WARNING: unknown neighbour level dir: "+n.dir); North;
147 | },
148 | });
149 | }
150 |
151 |
152 | function _instanciateLayer(json:ldtk.Json.LayerInstanceJson) : ldtk.Layer {
153 | return null; // overriden by Macros.hx
154 | }
155 |
156 |
157 | /**
158 | Return TRUE if the level was previously loaded and is ready for usage (always TRUE if levels are embedded in the project file).
159 | **/
160 | public inline function isLoaded() return this.externalRelPath==null || allUntypedLayers!=null && allUntypedLayers.length>0;
161 |
162 | /**
163 | Load level if it's stored in an external file. **IMPORTANT**: this probably doesn't need to be used in most scenario, as `load()` is *automatically* called when trying to use a level variable in your project.
164 | **/
165 | public function load() {
166 | if( isLoaded() )
167 | return true;
168 |
169 |
170 | var bytes = untypedProject.getAsset(externalRelPath);
171 | try {
172 | var raw = bytes.toString();
173 | var json : ldtk.Json.LevelJson = haxe.Json.parse(raw);
174 | fromJson(json);
175 | return true;
176 | }
177 | catch(e:Dynamic) {
178 | Project.error('Failed to parse external level $identifier: $externalRelPath ($e)');
179 | return false;
180 | }
181 | }
182 |
183 |
184 | public inline function hasBgImage() {
185 | return bgImageInfos!=null;
186 | }
187 |
188 |
189 | #if !macro
190 |
191 | #if heaps
192 | var _cachedBgTile : Null;
193 |
194 | /**
195 | Get the full "raw" (ie. non-cropped, scaled or positioned) background Tile. Use `getBgBitmap()` instead to get the "ready for display" background image.
196 | **/
197 | public function getRawBgImageTile() : Null {
198 | if( bgImageInfos==null )
199 | return null;
200 |
201 | if( _cachedBgTile==null ) {
202 | var bytes = untypedProject.getAsset(bgImageInfos.relFilePath);
203 | _cachedBgTile = dn.ImageDecoder.decodeTile(bytes);
204 | if( _cachedBgTile==null )
205 | _cachedBgTile = h2d.Tile.fromColor(0xff0000, pxWid, pxHei);
206 | }
207 | return _cachedBgTile;
208 | }
209 |
210 | /**
211 | Return the level background image, ready for display. The bitmap coordinates and scaling also match level background settings.
212 | **/
213 | public function getBgBitmap(?parent:h2d.Object) : Null {
214 | var t = getRawBgImageTile();
215 | if( t==null )
216 | return null;
217 |
218 | t = t.sub(
219 | bgImageInfos.cropRect.x,
220 | bgImageInfos.cropRect.y,
221 | bgImageInfos.cropRect.w,
222 | bgImageInfos.cropRect.h
223 | );
224 | var bmp = new h2d.Bitmap(t, parent);
225 | bmp.x = bgImageInfos.topLeftX;
226 | bmp.y = bgImageInfos.topLeftY;
227 | bmp.scaleX = bgImageInfos.scaleX;
228 | bmp.scaleY = bgImageInfos.scaleY;
229 | return bmp;
230 | }
231 | #end
232 |
233 | #if flixel
234 | public function getBgSprite() : Null< flixel.FlxSprite > {
235 | if( bgImageInfos==null )
236 | return null;
237 |
238 | // Full image
239 | var graphic = untypedProject.getFlxGraphicAsset( bgImageInfos.relFilePath );
240 | if( graphic==null )
241 | return null;
242 |
243 | // Cropped sub section
244 | var f = flixel.graphics.frames.FlxImageFrame.fromGraphic(graphic, flixel.math.FlxRect.weak(
245 | bgImageInfos.cropRect.x,
246 | bgImageInfos.cropRect.y,
247 | bgImageInfos.cropRect.w,
248 | bgImageInfos.cropRect.h
249 | ));
250 |
251 | // FlxSprite
252 | var spr = new flixel.FlxSprite();
253 | spr.frame = f.frame;
254 | spr.x = bgImageInfos.topLeftX;
255 | spr.y = bgImageInfos.topLeftY;
256 | spr.origin.set(0,0);
257 | spr.scale.set(bgImageInfos.scaleX, bgImageInfos.scaleY);
258 | return spr;
259 | }
260 | #end
261 |
262 | #end // End of "if !macro"
263 | }
264 |
--------------------------------------------------------------------------------
/src/ldtk/Point.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | class Point {
4 | public var cx : Int;
5 | public var cy : Int;
6 |
7 | public function new(cx,cy) {
8 | this.cx = cx;
9 | this.cy = cy;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ldtk/Project.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | /**
4 | LDtk Project JSON importer for Haxe.
5 |
6 | USAGE:
7 |
8 | Create a HX file for each LDtk project JSON. The filename isn’t important, pick whatever you like.
9 | This HX will host all the the typed data extracted from the project file:
10 |
11 | ```
12 | private typedef _Tmp =
13 | haxe.macro.MacroType<[ ldtk.Project.build("path/to/myProject.ldtk") ]>;
14 | ```
15 |
16 | See full documentation here: https://ldtk.io/docs
17 | **/
18 |
19 |
20 | #if macro
21 |
22 |
23 | /* MACRO TYPE BUILDER *****************************************************/
24 |
25 | import haxe.macro.Context;
26 | import haxe.macro.Expr;
27 | using haxe.macro.Tools;
28 |
29 | class Project {
30 |
31 | /** Build project types based on Project JSON **/
32 | public static function build(projectFilePath:String) {
33 | #if !macro
34 | error("Should only be used in macros");
35 | #else
36 |
37 | return ldtk.macro.TypeBuilder.buildTypes(projectFilePath);
38 | #end
39 | }
40 | }
41 |
42 |
43 | #else
44 |
45 |
46 | /* ACTUAL PROJECT CLASS *****************************************************/
47 |
48 | import ldtk.Json;
49 |
50 | class Project {
51 | /** Contains the full path to the project JSON, as provided to the macro (using slashes) **/
52 | public var projectFilePath : String;
53 |
54 | /** Contains the directory of the project JSON (using slashes, no trailing slash) **/
55 | public var projectDir : Null;
56 |
57 | /** Project background color (as Int 0xrrggbb) **/
58 | public var bgColor_int: UInt;
59 |
60 | /** Project background color (as Hex "#rrggbb") **/
61 | public var bgColor_hex: String;
62 |
63 | var _untypedWorlds : Array;
64 |
65 | /** Full access to the JSON project definitions **/
66 | public var defs : ldtk.Json.DefinitionsJson;
67 |
68 | /** A map containing all untyped Tilesets, indexed using their JSON `uid` (integer unique ID). The typed tilesets will be added in a field called `all_tilesets` by macros. **/
69 | @:allow(ldtk.Layer_Tiles, ldtk.Layer_AutoLayer, ldtk.Layer_IntGrid_AutoLayer, ldtk.Entity)
70 | var _untypedTilesets : Map;
71 |
72 | /** Internal asset cache to avoid reloading of previously loaded data. **/
73 | var assetCache : Map; // TODO support hot reloading
74 |
75 | var _untypedToc : Map>;
76 |
77 | function new() {}
78 |
79 | /**
80 | Replace current project using another project-JSON data.
81 |
82 | WARNING: types and classes are generated at compilation-time, not at runtime.
83 | **/
84 | public function parseJson(jsonString:String) {
85 | // Init
86 | _untypedTilesets = new Map();
87 | _untypedToc = new Map();
88 | assetCache = new Map();
89 |
90 | // Parse json
91 | var untypedJson : Dynamic = haxe.Json.parse(jsonString);
92 | var json : ProjectJson = untypedJson;
93 |
94 | // Init misc fields
95 | defs = json.defs;
96 | bgColor_hex = json.bgColor;
97 | bgColor_int = ldtk.Project.hexToInt(json.bgColor);
98 |
99 | // Add dummy JSON world
100 | if( json.worlds==null || json.worlds.length==0 )
101 | json.worlds = [ World.createDummyJson(json) ];
102 |
103 | // Populate worlds
104 | _untypedWorlds = [];
105 | var idx = 0;
106 | for(json in json.worlds)
107 | _untypedWorlds.push( _instanciateWorld(this, idx++, json) );
108 |
109 |
110 | // Populate tilesets
111 | Reflect.setField(this, "all_tilesets", {});
112 | for(tsJson in json.defs.tilesets) {
113 | _untypedTilesets.set( tsJson.uid, _instanciateTileset(this, tsJson) );
114 | Reflect.setField( Reflect.field(this,"all_tilesets"), tsJson.identifier, _instanciateTileset(this, tsJson));
115 | }
116 |
117 | // Init toc
118 | var classToc : Dynamic = Reflect.field(this,"toc");
119 | for( k in Reflect.fields(classToc) )
120 | Reflect.setField(classToc, k, []);
121 |
122 | // Populate toc
123 | if( json.toc!=null ) {
124 | var jsonToc : Array = json.toc;
125 | for(te in jsonToc)
126 | if( Reflect.hasField(classToc, te.identifier) )
127 | Reflect.setField(classToc, te.identifier, te.instancesData.copy());
128 | }
129 | }
130 |
131 | /** Transform an identifier string by capitalizing its first letter **/
132 | @:noCompletion
133 | public function capitalize(id:String) {
134 | if( id==null )
135 | id = "";
136 |
137 | var reg = ~/^(_*)([a-z])([a-zA-Z0-9_]*)/g; // extract first letter, if it's lowercase
138 | if( reg.match(id) )
139 | id = reg.matched(1) + reg.matched(2).toUpperCase() + reg.matched(3);
140 |
141 | return id;
142 | }
143 |
144 |
145 | var _enumTypePrefix : String;
146 |
147 | function _resolveExternalEnumValue(name:String, enumValueId:String) : T {
148 | return null;
149 | }
150 |
151 |
152 | /** Used to populated field instances with actual values **/
153 | @:allow(ldtk.Entity, ldtk.Level)
154 | function _assignFieldInstanceValues(target:Dynamic, fieldInstances:Array) {
155 | var arrayReg = ~/Array<(.*)>/gi;
156 | for(f in fieldInstances) {
157 | if( f.__value==null )
158 | continue;
159 |
160 | var isArray = arrayReg.match(f.__type);
161 | var typeName = isArray ? arrayReg.matched(1) : f.__type;
162 |
163 | switch typeName {
164 | case "Int", "Float", "Bool", "String" :
165 | Reflect.setField(target, "f_"+f.__identifier, f.__value);
166 |
167 | case "FilePath" :
168 | Reflect.setField(target, "f_"+f.__identifier, f.__value);
169 |
170 | case "Color":
171 | Reflect.setField(target, "f_"+f.__identifier+"_hex", f.__value);
172 | if( !isArray )
173 | Reflect.setField(target, "f_"+f.__identifier+"_int", ldtk.Project.hexToInt(f.__value));
174 | else {
175 | var arr : Array = f.__value;
176 | Reflect.setField(target, "f_"+f.__identifier+"_int", arr.map( (c)->ldtk.Project.hexToInt(c) ) );
177 | }
178 |
179 | case "Point":
180 | if( !isArray )
181 | Reflect.setField(target, "f_"+f.__identifier, new ldtk.Point(f.__value.cx, f.__value.cy));
182 | else {
183 | var arr : Array<{ cx:Int, cy:Int }> = f.__value;
184 | Reflect.setField(target, "f_"+f.__identifier, arr.map( (pt)->new ldtk.Point(pt.cx, pt.cy) ) );
185 | }
186 |
187 | case "EntityRef":
188 | Reflect.setField(target, "f_"+f.__identifier, f.__value);
189 |
190 | case _.indexOf("LocalEnum.") => 0:
191 | var type = _enumTypePrefix + typeName.substr( typeName.indexOf(".")+1 );
192 | var e = Type.resolveEnum( type );
193 | if( !isArray )
194 | Reflect.setField(target, "f_"+f.__identifier, Type.createEnum(e, capitalize(f.__value)) );
195 | else {
196 | var arr : Array = f.__value;
197 | Reflect.setField(target, "f_"+f.__identifier, arr.map( (k)->Type.createEnum(e,capitalize(k)) ) );
198 | }
199 |
200 |
201 | case _.indexOf("ExternEnum.") => 0:
202 | var type = typeName.substr( typeName.indexOf(".")+1 );
203 | if( !isArray )
204 | Reflect.setField(target, "f_"+f.__identifier, _resolveExternalEnumValue(type, f.__value) );
205 | else {
206 | var arr : Array = f.__value;
207 | Reflect.setField(target, "f_"+f.__identifier, arr.map( (k)->_resolveExternalEnumValue(type, k) ) );
208 | }
209 |
210 | case "Tile":
211 | function _checkTile(tileRect : TilesetRect) {
212 | if( tileRect==null || !dn.M.isValidNumber(tileRect.x) )
213 | return null; // old format
214 | else
215 | return tileRect;
216 | }
217 | #if heaps
218 | function _heapsTileGetter(tileRect:TilesetRect) {
219 | if( tileRect==null || !dn.M.isValidNumber(tileRect.x) || !_untypedTilesets.exists(tileRect.tilesetUid))
220 | return null;
221 |
222 | var tileset = _untypedTilesets.get(tileRect.tilesetUid);
223 | var tile = tileset.getFreeTile( tileRect.x, tileRect.y, tileRect.w, tileRect.h );
224 | return tile;
225 | }
226 | #end
227 |
228 | if( isArray ) {
229 | var arr : Array = f.__value;
230 | Reflect.setField(target, "f_"+f.__identifier+"_infos", arr.map( tr->_checkTile(tr) ) );
231 | #if heaps
232 | Reflect.setField(target, "f_"+f.__identifier+"_getTile", arr.map( tr->_heapsTileGetter.bind(tr) ) );
233 | #end
234 |
235 | }
236 | else {
237 | Reflect.setField(target, "f_"+f.__identifier+"_infos", _checkTile(f.__value));
238 | #if heaps
239 | Reflect.setField(target, "f_"+f.__identifier+"_getTile", _heapsTileGetter.bind(f.__value));
240 | #end
241 | }
242 |
243 | case _ :
244 | Project.error('Unknown field type $typeName at runtime'); // TODO add some helpful context here
245 | }
246 | }
247 | }
248 |
249 |
250 | @:keep public function toString() {
251 | return 'ldtk.Project[${_untypedWorlds.length} worlds]';
252 | }
253 |
254 |
255 | /**
256 | Get an asset from current Asset management system. The path should be **relative to the project JSON file**.
257 | **/
258 | public function getAsset(projectRelativePath:String) : haxe.io.Bytes {
259 | if( assetCache.exists(projectRelativePath) )
260 | return assetCache.get(projectRelativePath);
261 | else {
262 | var bytes = loadAssetBytes(projectRelativePath);
263 | assetCache.set(projectRelativePath, bytes);
264 | return bytes;
265 | }
266 | }
267 |
268 |
269 | /**
270 | Try to resolve the Project file location in the current Asset management system
271 | **/
272 | function makeAssetRelativePath(projectRelativePath:String) {
273 | // Get project file name
274 | var p = StringTools.replace(projectFilePath, "\\", "/");
275 | var projectFileName = p.lastIndexOf("/")<0 ? p : p.substr( p.lastIndexOf("/")+1 );
276 |
277 | #if heaps
278 |
279 | // Browser all folders in Heaps res/ folder recursively to locate Project file
280 | var pendingDirs = [
281 | hxd.Res.loader.fs.getRoot()
282 | ];
283 | while( pendingDirs.length>0 ) {
284 | var curDir = pendingDirs.shift();
285 | for(f in curDir) {
286 | if( f.isDirectory ) {
287 | // Found another dir
288 | pendingDirs.push(f);
289 | }
290 | else if( f.name==projectFileName ) {
291 | // Found it
292 | return dn.FilePath.cleanUp( ( f.directory.length==0 ? "" : f.directory+"/" ) + projectRelativePath, true );
293 | }
294 | }
295 | }
296 | error('Project file is not in Heaps res/ folder!');
297 | return "";
298 |
299 | #elseif openfl
300 |
301 | // Browse openFL assets to locate project file
302 | for( e in openfl.Assets.list() )
303 | if( e.indexOf(projectFileName)>=0 ) {
304 | // Found it
305 | var baseDir = e.indexOf("/")<0 ? "" : e.substr( 0, e.lastIndexOf("/") );
306 | return dn.FilePath.cleanUp( baseDir + "/" + projectRelativePath, true );
307 | }
308 |
309 | error('Project file is not in OpenFL assets!');
310 | return "";
311 |
312 | #else
313 |
314 | // Generic Haxe Resource Loading for Unsupported Frameworks
315 | // Browse resources to locate project file
316 | for(key => value in haxe.Resource.listNames()) {
317 | if(value == projectFilePath) {
318 | // Found it
319 | var baseDir = value.indexOf("/")<0 ? "" : value.substr( 0, value.lastIndexOf("/") );
320 | return dn.FilePath.cleanUp( baseDir + "/" + projectRelativePath, true );
321 | }
322 | }
323 |
324 | error('Project file is not loaded properly.\nPlease add "-r " and "-r " to your project.hxml build file and try again.');
325 | return "";
326 |
327 | #end
328 | }
329 |
330 |
331 | /**
332 | Load an Asset as haxe.io.Bytes
333 | **/
334 | function loadAssetBytes(projectRelativePath:String) : haxe.io.Bytes {
335 | #if heaps
336 |
337 | var resPath = makeAssetRelativePath(projectRelativePath);
338 | if( !hxd.Res.loader.exists(resPath) )
339 | error('Asset not found in Heaps res/ folder: $resPath');
340 |
341 | var res = hxd.Res.load(resPath);
342 | return res.entry.getBytes();
343 |
344 | #elseif openfl
345 |
346 | var assetId = makeAssetRelativePath(projectRelativePath);
347 | var bytes : haxe.io.Bytes = try openfl.Assets.getBytes(assetId) catch(e:Dynamic) {
348 | error('OpenFL asset not found or could not be accessed synchronously: $assetId ; error=$e');
349 | null;
350 | }
351 | return bytes;
352 |
353 |
354 | #else
355 |
356 | // Generic Haxe Resource Loading for Unsupported Frameworks
357 | var assetId = makeAssetRelativePath(projectRelativePath);
358 | var bytes : haxe.io.Bytes = try haxe.Resource.getBytes(assetId) catch(e:Dynamic) {
359 | error('Asset not found or was not loaded properly at runtime: $assetId ; error=$e');
360 | null;
361 | }
362 | return bytes;
363 |
364 | #end
365 | }
366 |
367 |
368 | #if flixel
369 | /**
370 | Get an asset image as FlxGraphic
371 | **/
372 | public function getFlxGraphicAsset(projectRelativePath:String) : flixel.graphics.FlxGraphic {
373 | var assetId = makeAssetRelativePath(projectRelativePath);
374 | var g = try flixel.graphics.FlxGraphic.fromAssetKey(assetId)
375 | catch(e:Dynamic) {
376 | error('FlxGraphic not found in assets: $assetId ; error=$e');
377 | null;
378 | }
379 | return g;
380 | }
381 | #end
382 |
383 |
384 | /**
385 | Crash with an error message
386 | **/
387 | public static function error(str:String) {
388 | throw '[ldtk-api] $str';
389 | }
390 |
391 |
392 | function _instanciateWorld(project:ldtk.Project, arrayIndex:Int, json:ldtk.Json.WorldJson) {
393 | return null; // overriden by Macros.hx
394 | }
395 |
396 |
397 | function _instanciateTileset(project:ldtk.Project, json:ldtk.Json.TilesetDefJson) {
398 | return null;
399 | }
400 |
401 |
402 | function searchDef(arr:Array, ?uid:Int, ?identifier:String) {
403 | if( uid==null && identifier==null )
404 | return null;
405 |
406 | for(e in arr)
407 | if( uid!=null && e.uid==uid || identifier!=null && e.identifier==identifier )
408 | return e;
409 |
410 | return null;
411 | }
412 |
413 | /**
414 | Get a Layer definition using either its uid (Int) or identifier (String)
415 | **/
416 | public function getLayerDefJson(?uid:Int, ?identifier:String) : Null {
417 | return searchDef( defs.layers, uid, identifier );
418 | }
419 | @:noCompletion @:deprecated("Method was renamed to: getLayerDefJson")
420 | public function getLayerDef(?uid,?identifier) return getLayerDefJson(uid,identifier);
421 |
422 | /**
423 | Get an Entity definition using either its uid (Int) or identifier (String)
424 | **/
425 | public inline function getEntityDefJson(?uid:Int, ?identifier:String) : Null {
426 | return searchDef( defs.entities, uid, identifier );
427 | }
428 | @:noCompletion @:deprecated("Method was renamed to: getEntityDefJson")
429 | public function getEntityDef(?uid,?identifier) return getEntityDefJson(uid,identifier);
430 |
431 |
432 |
433 | /**
434 | Get a Tileset definition using either its uid (Int) or identifier (String)
435 | **/
436 | public inline function getTilesetDefJson(?uid:Int, ?identifier:String) : Null {
437 | return searchDef( defs.tilesets, uid, identifier );
438 | }
439 | @:noCompletion @:deprecated("Method was renamed to: getTilesetDefJson")
440 | public function getTilesetDef(?uid,?identifier) return getTilesetDefJson(uid,identifier);
441 |
442 |
443 | /**
444 | Get an Enum definition using either its uid (Int) or identifier (String)
445 | **/
446 | public inline function getEnumDefJson(?uid:Int, ?identifier:String) : Null {
447 | var e = searchDef( defs.enums, uid, identifier );
448 | if( e!=null )
449 | return e;
450 | else
451 | return searchDef( defs.externalEnums, uid, identifier );
452 | }
453 | @:noCompletion @:deprecated("Method was renamed to: getEnumDefJson")
454 | public function getEnumDef(?uid,?identifier) return getEnumDefJson(uid,identifier);
455 |
456 |
457 | /**
458 | Get an Enum definition using an Enum value
459 | **/
460 | public function getEnumDefFromValue(v:EnumValue) : Null {
461 | try {
462 | var name = Type.getEnum(v).getName();
463 | var defId = name.substr( name.indexOf("_")+1 ); // get rid of the Macro prefix
464 | defId = defId.substr( defId.lastIndexOf(".")+1 );
465 | return getEnumDefJson(defId);
466 | }
467 | catch(err:Dynamic) {
468 | return null;
469 | }
470 | }
471 |
472 | function getEnumTileInfosFromValue(v:EnumValue) : Null<{ x:Int, y:Int, w:Int, h:Int, tilesetUid:Int }> {
473 | var ed = getEnumDefFromValue(v);
474 | if( ed==null )
475 | return null;
476 |
477 | for(ev in ed.values)
478 | if( ev.id==v.getName() && ev.tileRect!=null )
479 | return {
480 | tilesetUid: ed.iconTilesetUid,
481 | x: ev.tileRect.x,
482 | y: ev.tileRect.y,
483 | w: ev.tileRect.w,
484 | h: ev.tileRect.h,
485 | };
486 |
487 | return null;
488 | }
489 |
490 | #if heaps
491 |
492 | public function getEnumTile(enumValue:EnumValue) : Null {
493 | var tileInfos = getEnumTileInfosFromValue(enumValue);
494 | if( tileInfos==null )
495 | return null;
496 |
497 | var tileset = _untypedTilesets.get(tileInfos.tilesetUid);
498 | if( tileset==null )
499 | return null;
500 |
501 | return tileset.getFreeTile(tileInfos.x, tileInfos.y, tileInfos.w, tileInfos.h);
502 | }
503 | #end
504 |
505 | public function getEnumColor(enumValue:EnumValue) : UInt {
506 | var ed = getEnumDefFromValue(enumValue);
507 | for(v in ed.values)
508 | if( v.id==enumValue.getName() )
509 | return v.color;
510 | return 0xff00ff;
511 | }
512 |
513 | @:noCompletion
514 | public static inline function hexToInt(hex:String) : Int {
515 | return hex==null ? 0x0 : Std.parseInt( "0x"+hex.substr(1) );
516 | }
517 |
518 | @:noCompletion
519 | public static inline function intToHex(c:Int, ?leadingZeros=6) : String {
520 | var h = StringTools.hex(c);
521 | while( h.length >;
36 |
37 |
38 | public function new(p:ldtk.Project, json:ldtk.Json.TilesetDefJson) {
39 | this.json = json;
40 | untypedProject = p;
41 | identifier = json.identifier;
42 | tileGridSize = json.tileGridSize;
43 | relPath = json.relPath;
44 | pxWid = json.pxWid;
45 | pxHei = json.pxHei;
46 | padding = json.padding;
47 | spacing = json.spacing;
48 |
49 | // Init untyped enum tags
50 | untypedTags = new Map();
51 | if( json.enumTags!=null ) {
52 | for(t in json.enumTags) {
53 | untypedTags.set( p.capitalize(t.enumValueId), [] );
54 | for(tid in t.tileIds)
55 | untypedTags.get( p.capitalize(t.enumValueId) ).set(tid,tid);
56 | }
57 | }
58 | }
59 |
60 | /** Print class debug info **/
61 | @:keep public function toString() {
62 | return 'ldtk.Tileset[#$identifier, path=$relPath]';
63 | }
64 |
65 |
66 | /**
67 | Get X pixel coordinate (in atlas image) from a specified tile ID
68 | **/
69 | public inline function getAtlasX(tileId:Int) {
70 | return ( tileId - Std.int( tileId / cWid ) * cWid ) * tileGridSize;
71 | }
72 |
73 | /**
74 | Get Y pixel coordinate (in atlas image) from a specified tile ID
75 | **/
76 | public inline function getAtlasY(tileId:Int) {
77 | return Std.int( tileId / cWid ) * tileGridSize;
78 | }
79 |
80 | /**
81 | Resolve an atlas coordinate to a tile ID. The result is only relevant if the coordinates are over a tile (ie. in atlas bounds, not in margins etc.).
82 | WARNING: tile spacing is not supported yet!
83 | **/
84 | public inline function getTileIdFromCoords(pixelX:Int, pixelY:Int) {
85 | return Std.int( (pixelX-padding) / tileGridSize ) + cWid * Std.int( pixelY / tileGridSize );
86 | }
87 |
88 |
89 | /***************************************************************************
90 | HEAPS API
91 | ***************************************************************************/
92 |
93 | #if( !macro && heaps )
94 | var _cachedAtlasTile : Null;
95 |
96 | /** Get the main tileset h2d.Tile **/
97 | public inline function getAtlasTile() : Null {
98 | if( _cachedAtlasTile!=null )
99 | return _cachedAtlasTile;
100 | else {
101 | var bytes = untypedProject.getAsset(relPath);
102 | _cachedAtlasTile = dn.ImageDecoder.decodeTile(bytes);
103 | if( _cachedAtlasTile==null )
104 | _cachedAtlasTile = h2d.Tile.fromColor(0xff0000, pxWid, pxHei);
105 | return _cachedAtlasTile;
106 | }
107 | }
108 |
109 | /**
110 | Get a h2d.Tile from a Tile ID.
111 |
112 | "flipBits" can be: 0=no flip, 1=flipX, 2=flipY, 3=bothXY
113 | **/
114 | public inline function getTile(tileId:Int, flipBits:Int=0) : Null {
115 | if( tileId<0 )
116 | return null;
117 | else {
118 | var atlas = getAtlasTile();
119 | var t = atlas.sub( getAtlasX(tileId), getAtlasY(tileId), tileGridSize, tileGridSize );
120 | return switch flipBits {
121 | case 0: t;
122 | case 1: t.flipX(); t.setCenterRatio(0,0); t;
123 | case 2: t.flipY(); t.setCenterRatio(0,0); t;
124 | case 3: t.flipX(); t.flipY(); t.setCenterRatio(0,0); t;
125 | case _: Project.error("Unsupported flipBits value"); null;
126 | }
127 | }
128 | }
129 |
130 | /**
131 | Get a h2d.Tile using given rectangle pixel coords.
132 | **/
133 | public inline function getFreeTile(x:Int, y:Int, wid:Int, hei:Int) : Null {
134 | var atlas = getAtlasTile();
135 | return atlas==null ? null : atlas.sub(x,y,wid,hei);
136 | }
137 |
138 | @:deprecated("Use getTile() instead") @:noCompletion
139 | public inline function getHeapsTile(oldAtlasTile:h2d.Tile, tileId:Int, flipBits:Int=0) {
140 | return getTile(tileId, flipBits);
141 | }
142 |
143 |
144 | /** Get a h2d.Tile from a Auto-Layer tile. **/
145 | public inline function getAutoLayerTile(autoLayerTile:ldtk.Layer_AutoLayer.AutoTile) : Null {
146 | if( autoLayerTile.tileId<0 )
147 | return null;
148 | else
149 | return getTile(autoLayerTile.tileId, autoLayerTile.flips);
150 | }
151 |
152 | @:deprecated("Use getAutoLayerTile() instead") @:noCompletion
153 | public inline function getAutoLayerHeapsTile(oldAtlasTile:h2d.Tile, autoLayerTile:ldtk.Layer_AutoLayer.AutoTile) {
154 | return getAutoLayerTile(autoLayerTile);
155 | }
156 |
157 | #end // End of Heaps API
158 |
159 |
160 |
161 |
162 | /***************************************************************************
163 | Flixel API
164 | ***************************************************************************/
165 |
166 | #if( !macro && flixel )
167 |
168 | var _tileFrames: Null< flixel.graphics.frames.FlxTileFrames >;
169 | var _atlas: Null< flixel.graphics.FlxGraphic >;
170 |
171 | /** Read Atlas and cache it locally **/
172 | function readAtlas() {
173 | if( _tileFrames==null ) {
174 | _atlas = untypedProject.getFlxGraphicAsset(relPath);
175 | _tileFrames = flixel.graphics.frames.FlxTileFrames.fromBitmapAddSpacesAndBorders(
176 | _atlas,
177 | flixel.math.FlxPoint.weak( tileGridSize, tileGridSize )
178 | );
179 | }
180 | }
181 |
182 | /** Get the main tileset FlxTileFrames **/
183 | public inline function getTileFrames() : flixel.graphics.frames.FlxTileFrames {
184 | readAtlas();
185 | return _tileFrames;
186 | }
187 |
188 | /** Get the main tileset FlxGraphic **/
189 | public inline function getAtlasGraphic() : flixel.graphics.FlxGraphic {
190 | readAtlas();
191 | return _atlas;
192 | }
193 |
194 | /** Get a FlxFrame using its ID **/
195 | public inline function getFrame(tileId:Int) : flixel.graphics.frames.FlxFrame {
196 | return getTileFrames().getByIndex(tileId);
197 | }
198 |
199 | #end // End of Flixel API
200 | }
201 |
--------------------------------------------------------------------------------
/src/ldtk/World.hx:
--------------------------------------------------------------------------------
1 | package ldtk;
2 |
3 | import ldtk.Json;
4 |
5 | class World {
6 | #if !macro
7 |
8 | var untypedProject: ldtk.Project; // WARNING: the var type isn't the "complete" project type as generated by macros!
9 | var json : ldtk.Json.WorldJson;
10 | var _untypedLevels : Array;
11 |
12 | /** Index in project `worlds` array **/
13 | public var arrayIndex(default,null) : Int;
14 | public var identifier(default,null) : String;
15 | public var iid(default,null) : String;
16 |
17 | public var layout: WorldLayout;
18 | public var gridWid : Int;
19 | public var gridHei : Int;
20 |
21 |
22 |
23 | public function new(project:Project, arrayIdx:Int, json:ldtk.Json.WorldJson) {
24 | this.untypedProject = project;
25 | this.arrayIndex = arrayIdx;
26 | if( json!=null )
27 | fromJson(json);
28 | }
29 |
30 | @:keep public function toString() {
31 | return 'ldtk.World[$identifier, $layout, ${_untypedLevels.length} levels]';
32 | }
33 |
34 | function fromJson(untypedJson:Dynamic) {
35 | this.json = untypedJson;
36 | iid = json.iid;
37 | identifier = json.identifier;
38 | layout = WorldLayout.createByName( Std.string(untypedJson.worldLayout) );
39 | gridWid = json.worldGridWidth;
40 | gridHei = json.worldGridHeight;
41 |
42 |
43 | // Populate levels
44 | _untypedLevels = [];
45 | var idx = 0;
46 | for(json in json.levels)
47 | _untypedLevels.push( _instanciateLevel(untypedProject, idx++, json) );
48 | }
49 |
50 |
51 | function _instanciateLevel(project:ldtk.Project, arrayIndex:Int, json:ldtk.Json.LevelJson) {
52 | return null; // overriden by Macros.hx
53 | }
54 |
55 | #end
56 |
57 |
58 | @:allow(ldtk.macro.TypeBuilder, ldtk.Project)
59 | static function createDummyJson(projectJson:ProjectJson) : WorldJson {
60 | var untypedJson : Dynamic = projectJson;
61 | return {
62 | iid: "Default_iid",
63 | identifier: "Default",
64 |
65 | worldLayout: WorldLayout.createByName( Std.string(untypedJson.worldLayout) ),
66 | worldGridWidth: projectJson.worldGridWidth,
67 | worldGridHeight: projectJson.worldGridHeight,
68 |
69 | defaultLevelWidth: projectJson.defaultLevelWidth,
70 | defaultLevelHeight: projectJson.defaultLevelHeight,
71 | levels: projectJson.levels,
72 |
73 | }
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/tests/ProjectNoPackage.hx:
--------------------------------------------------------------------------------
1 | private typedef _Tmp = haxe.macro.MacroType<[
2 | ldtk.Project.build("samples/_assets/unitTest.ldtk")
3 | ]>;
--------------------------------------------------------------------------------
/tests/Tests.hx:
--------------------------------------------------------------------------------
1 | import dn.CiAssert;
2 | import ExternEnumTest;
3 | import ExternCastleDbTest;
4 | import ProjectNoPackage;
5 |
6 | class Tests {
7 |
8 | static function exit(code=0) {
9 | #if hxnodejs
10 | js.node.Require.require("process").exit(code);
11 | #elseif js
12 | // unsupported
13 | #else
14 | Sys.exit(code);
15 | #end
16 | }
17 |
18 | static inline function section(v:String) {
19 | if( CiAssert.VERBOSE ) {
20 | print("");
21 | print(v);
22 | }
23 | }
24 |
25 | static function print(v:Dynamic) {
26 | #if js
27 | js.html.Console.log( Std.string(v) );
28 | #else
29 | Sys.println( Std.string(v) );
30 | #end
31 | }
32 |
33 |
34 | static function main() {
35 | // Init
36 | #if hl
37 | hxd.Res.initLocal();
38 | #else
39 | hxd.Res.initEmbed();
40 | #end
41 |
42 | // Load castle DB
43 | ExternCastleDbTest.load( hxd.Res.sample_cdb.entry.getText() );
44 |
45 | // Check args
46 | CiAssert.VERBOSE = false;
47 | for( a in Sys.args() )
48 | if( a=="-v" )
49 | CiAssert.VERBOSE = true;
50 |
51 | print("Running tests...");
52 |
53 | // Run tests
54 | var project = new ProjectNoPackage();
55 |
56 | try {
57 | section("PROJECT (NO PACKAGE)...");
58 |
59 | section("Project...");
60 | CiAssert.isNotNull( project );
61 |
62 | // Project asset loader
63 | CiAssert.isNotNull( project.getAsset("unitTest.ldtk") );
64 |
65 | // Project defs
66 | CiAssert.isNotNull( project.defs );
67 | CiAssert.isNotNull( project.defs.entities );
68 | CiAssert.isNotNull( project.defs.enums );
69 | CiAssert.isNotNull( project.defs.externalEnums );
70 | CiAssert.isNotNull( project.defs.layers );
71 | CiAssert.isNotNull( project.defs.tilesets );
72 |
73 | var defaultWorld = project.all_worlds.World1;
74 | CiAssert.equals( defaultWorld.layout, ldtk.Json.WorldLayout.GridVania );
75 | CiAssert.isTrue( project.defs.entities.length>0 );
76 | CiAssert.isTrue( project.defs.enums.length>0 );
77 | CiAssert.isTrue( project.defs.externalEnums.length>0 );
78 | CiAssert.isTrue( project.defs.layers.length>0 );
79 | CiAssert.isTrue( project.defs.tilesets.length>0 );
80 |
81 | CiAssert.isNotNull( project.getLayerDefJson("IntGrid_AutoLayer") );
82 | CiAssert.isNotNull( project.getEntityDefJson("Hero") );
83 | CiAssert.isNotNull( project.getEnumDefJson("Weapons") );
84 | CiAssert.isNotNull( project.getEnumDefJson("lowercase_enum") );
85 | CiAssert.isNotNull( project.getTilesetDefJson("Minecraft_texture_pack") );
86 |
87 | CiAssert.equals( project.getEnumDefFromValue(Trash).identifier, "Mobs" );
88 | CiAssert.equals( project.getEnumDefFromValue(LongBow).identifier, "Weapons" );
89 | CiAssert.equals( project.getEnumDefFromValue(Lc_a).identifier, "lowercase_enum" );
90 | CiAssert.equals( project.getEnumDefFromValue(Ammo).identifier, "DroppedItemType" ); // extern
91 | CiAssert.equals( project.getEnumDefFromValue(Foo).identifier, "SomeEnum" ); // extern
92 | CiAssert.equals( project.getEnumDefFromValue(null), null );
93 |
94 | // Original JSON fields
95 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.json );
96 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_IntGrid8.json );
97 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob[0].json );
98 | CiAssert.isNotNull( project.all_tilesets.Cavernas_by_Adam_Saltsman.json );
99 |
100 | // Types
101 | section("Types...");
102 | CiAssert.isNotNull( ProjectNoPackage.Enum_Mobs );
103 | CiAssert.isNotNull( ProjectNoPackage.ProjectNoPackage_EntityEnum );
104 | CiAssert.isNotNull( ProjectNoPackage.Tileset_Cavernas_by_Adam_Saltsman );
105 |
106 | // Levels
107 | section("Levels...");
108 | CiAssert.isNotNull( defaultWorld.all_levels );
109 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests );
110 | CiAssert.isNotNull( defaultWorld.all_levels.Offset_tests );
111 | CiAssert.isNotNull( defaultWorld.getLevel("Main_tests") );
112 | CiAssert.equals( defaultWorld.getLevel("Main_tests"), defaultWorld.all_levels.Main_tests );
113 | CiAssert.equals( defaultWorld.getLevel(0), defaultWorld.all_levels.Main_tests );
114 | CiAssert.isTrue( defaultWorld.levels.length>0 );
115 | CiAssert.isNotNull( defaultWorld.levels[0].l_IntGridTest );
116 | CiAssert.equals( defaultWorld.levels[1].worldX, 512 );
117 | CiAssert.equals( defaultWorld.levels[1].worldY, 256 );
118 | CiAssert.equals( defaultWorld.levels[0].bgColor_hex, "#271E27" );
119 | CiAssert.equals( defaultWorld.levels[0].bgColor_int, 0x271E27 );
120 | CiAssert.equals( defaultWorld.levels[0].neighbours.length, 2 );
121 | CiAssert.equals( defaultWorld.levels[0].neighbours[0].dir, ldtk.Level.NeighbourDir.East );
122 | CiAssert.equals( defaultWorld.getLevelAt(10,10), defaultWorld.all_levels.Main_tests );
123 | CiAssert.equals( defaultWorld.getLevelAt(600,400), defaultWorld.all_levels.Offset_tests );
124 |
125 | // Layer misc
126 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.visible, true );
127 |
128 | // Layer JSONs
129 | var layer = defaultWorld.all_levels.Main_tests.l_EntityTest;
130 | CiAssert.isNotNull(layer.json);
131 | CiAssert.isNotNull(layer.json.entityInstances);
132 | CiAssert.isNotNull(layer.defJson);
133 | CiAssert.equals(layer.json.layerDefUid, layer.defJson.uid);
134 | CiAssert.equals(layer.defJson.identifier, "EntityTest");
135 |
136 |
137 | // Layer offsets
138 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.l_IntGrid8.pxTotalOffsetX, 4 );
139 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.l_IntGrid8.pxTotalOffsetY, 4 );
140 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.l_IntGridTest.pxTotalOffsetX, 8 );
141 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.l_IntGridTest.pxTotalOffsetY, 8 );
142 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.l_EntityTest.all_OffsetTest[0].pixelX, 0 );
143 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.l_EntityTest.all_OffsetTest[0].pixelY, 0 );
144 |
145 |
146 | // IntGrid layer
147 | section("IntGrid...");
148 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_IntGridTest );
149 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.type, ldtk.Json.LayerType.IntGrid );
150 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.type==IntGrid );
151 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.getInt(0,0)==1 );
152 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.hasValue(0,0) );
153 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.getName(0,0)=="a" );
154 |
155 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.getInt(1,0)==2 );
156 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.getInt(2,0)==3 );
157 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGridTest.getInt(3,0)==4 );
158 |
159 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.hasValue(0,1), false );
160 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.hasValue(3,0, 4), true );
161 |
162 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.isCoordValid(0,0), true );
163 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.isCoordValid(-1,0), false );
164 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_IntGridTest.isCoordValid(999,0), false );
165 |
166 | // Entity layer
167 | section("Entity...");
168 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_EntityTest);
169 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_EntityTest.type, ldtk.Json.LayerType.Entities );
170 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_EntityTest.type==Entities );
171 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Hero.length!=0 );
172 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob.length!=0 );
173 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_EntityTest.all_AllFields.length!=0 );
174 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Unused.length, 0 );
175 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob[0].tileInfos );
176 |
177 | // Entity layer tags
178 | var level = defaultWorld.all_levels.Main_tests;
179 | CiAssert.isNotNull( level.l_EntityWithTag );
180 | CiAssert.isNotNull( level.l_EntityWithTag.all_Tagged );
181 | CiAssert.equals( level.l_EntityWithTag.all_Tagged.length, 3 );
182 | CiAssert.equals( level.l_EntityWithTag.getAllUntyped().length, 3 );
183 |
184 | // Entities
185 | var hero = defaultWorld.all_levels.Main_tests.l_EntityTest.all_Hero[0];
186 | var mob = defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob[0];
187 | var allFieldsTest = defaultWorld.all_levels.Main_tests.l_EntityTest.all_AllFields[0];
188 | var fileEnt = defaultWorld.all_levels.Main_tests.l_EntityTest.all_File[0];
189 | CiAssert.isNotNull( hero );
190 | CiAssert.isNotNull( mob );
191 | CiAssert.isNotNull( allFieldsTest );
192 | CiAssert.isNotNull( fileEnt );
193 | CiAssert.equals( mob.f_scale, 0.5 );
194 | CiAssert.equals( hero.width, 16 );
195 | CiAssert.equals( hero.height, 24 );
196 | CiAssert.equals( allFieldsTest.width, 32 );
197 | CiAssert.equals( allFieldsTest.height, 32 );
198 | CiAssert.equals( allFieldsTest.iid, "f2f3f740-66b0-11ec-91ab-910cd77ba401" );
199 | CiAssert.equals( allFieldsTest.f_entityRefs.length, 2 );
200 | CiAssert.equals( allFieldsTest.f_entityRefs[0].entityIid, "57c51ab0-66b0-11ec-8446-f3a61ee63449" );
201 | CiAssert.equals( allFieldsTest.f_entityRefs[1].entityIid, "58f66ec0-66b0-11ec-8446-9b40d7be219b" );
202 |
203 | // Entity JSONs
204 | CiAssert.isNotNull(hero.json);
205 | CiAssert.isNotNull(hero.json.fieldInstances);
206 | CiAssert.isNotNull(hero.defJson);
207 | CiAssert.isNotNull(hero.defJson.fieldDefs);
208 | CiAssert.equals(hero.json.defUid, hero.defJson.uid);
209 | CiAssert.equals(hero.defJson.identifier, "Hero");
210 |
211 | // Extern enums
212 | var extEnt = defaultWorld.all_levels.Main_tests.l_EntityTest.all_ExternEnums[0];
213 | CiAssert.isNotNull(extEnt);
214 | CiAssert.isNotNull(extEnt.f_cdb);
215 | CiAssert.isNotNull(extEnt.f_haxe);
216 | CiAssert.equals(extEnt.f_cdb, CdbA);
217 | CiAssert.equals(extEnt.f_haxe, SomeEnum.Pouet);
218 | CiAssert.isTrue(
219 | switch extEnt.f_cdb {
220 | case CdbA: true;
221 | case CdbB: false;
222 | case CdbC: false;
223 | }
224 | );
225 | CiAssert.isTrue(extEnt.f_cdb==ExternCastleDbTest.CdbEnumTestKind.CdbA);
226 |
227 | // Entity tiles
228 | var eTiles = defaultWorld.all_levels.Main_tests.l_EntityTest.all_EntityTiles;
229 | CiAssert.isNotNull( eTiles );
230 | CiAssert.isTrue( eTiles.length>=2 );
231 | CiAssert.isNotNull( eTiles[0].tileInfos );
232 | CiAssert.equals( eTiles[0].tileInfos.tilesetUid, 14 );
233 | CiAssert.equals( eTiles[0].tileInfos.x, 32 );
234 | CiAssert.equals( eTiles[0].tileInfos.y, 32 );
235 | CiAssert.equals( eTiles[1].tileInfos.x, 64 );
236 | CiAssert.equals( eTiles[1].tileInfos.y, 0 );
237 |
238 | // Sym ref 1
239 | var fromSymRef = defaultWorld.all_levels.Main_tests.l_EntityTest.all_SymRef[0];
240 | var toSymRef = defaultWorld.all_levels.Target_level_ref.l_EntityTest.all_SymRef[0];
241 | CiAssert.equals( fromSymRef.f_ref.entityIid, toSymRef.iid );
242 | CiAssert.equals( fromSymRef.f_ref.levelIid, defaultWorld.all_levels.Target_level_ref.iid );
243 | CiAssert.equals( toSymRef.f_ref.entityIid, fromSymRef.iid );
244 | CiAssert.equals( toSymRef.f_ref.levelIid, defaultWorld.all_levels.Main_tests.iid );
245 |
246 | // Sym ref 2
247 | var fromSymRef = defaultWorld.all_levels.Main_tests.l_EntityTest.all_SymRef[1];
248 | var toSymRef = defaultWorld.all_levels.Main_tests.l_EntityTest.all_SymRef[2];
249 | CiAssert.equals( fromSymRef.f_ref.entityIid, toSymRef.iid );
250 | CiAssert.equals( fromSymRef.f_ref.levelIid, defaultWorld.all_levels.Main_tests.iid );
251 | CiAssert.equals( toSymRef.f_ref.entityIid, fromSymRef.iid );
252 | CiAssert.equals( toSymRef.f_ref.levelIid, defaultWorld.all_levels.Main_tests.iid );
253 |
254 | // Regions
255 | var r = defaultWorld.all_levels.Main_tests.l_EntityTest.all_Region[0];
256 | CiAssert.isNotNull(r);
257 | CiAssert.equals(r.width, 64);
258 | CiAssert.equals(r.height, 48);
259 | CiAssert.equals(r.f_flag, true);
260 |
261 | // Enums
262 | section("Enums...");
263 | CiAssert.isNotNull( Enum_Weapons );
264 | CiAssert.isNotNull( Enum_lowercase_enum );
265 | CiAssert.equals( Enum_Weapons.getConstructors()[0], "LongBow" );
266 | CiAssert.equals( Enum_Weapons.getConstructors()[1], "Torch" );
267 | CiAssert.equals( hero.f_startWeapon, LongBow );
268 | CiAssert.equals( mob.f_type, Trash );
269 | CiAssert.equals( mob.entityType, Mob );
270 | CiAssert.equals( mob.f_lootDrops[0], ExternEnumTest.DroppedItemType.Ammo );
271 | CiAssert.equals( mob.f_lootDrops[1], ExternEnumTest.DroppedItemType.Food );
272 | CiAssert.equals( mob.f_lootDrops[2], ExternEnumTest.DroppedItemType.Gold );
273 | CiAssert.equals( mob.f_lootDrops[3], ExternEnumTest.DroppedItemType.Key );
274 |
275 | // Arrays
276 | CiAssert.isNotNull( allFieldsTest.f_ints );
277 | CiAssert.equals( allFieldsTest.f_ints.length, 3 );
278 | CiAssert.equals( allFieldsTest.f_ints[0], 0 );
279 | CiAssert.equals( allFieldsTest.f_ints[1], 1 );
280 | CiAssert.equals( allFieldsTest.f_ints[2], 2 );
281 | CiAssert.equals( allFieldsTest.f_strings[0], "a" );
282 | CiAssert.equals( allFieldsTest.f_floats[1], 0.5 );
283 | CiAssert.equals( allFieldsTest.f_bools[0], false );
284 | CiAssert.equals( allFieldsTest.f_bools[2], true );
285 | CiAssert.equals( allFieldsTest.f_colors_hex[0],"#FF0000" );
286 | CiAssert.equals( allFieldsTest.f_colors_int[0], 0xff0000 );
287 | CiAssert.isTrue( allFieldsTest.f_localEnums.length>0 );
288 | CiAssert.equals( allFieldsTest.f_localEnums[0], FireBall );
289 | CiAssert.isTrue( allFieldsTest.f_externEnums.length>0 );
290 | CiAssert.equals( allFieldsTest.f_externEnums[0], Gold );
291 | CiAssert.equals( allFieldsTest.f_externEnums[1], null );
292 | CiAssert.equals( allFieldsTest.f_lowercaseEnum[0], Lc_a );
293 | CiAssert.equals( allFieldsTest.f_lowercaseEnum[1], Lc_b );
294 | CiAssert.equals( allFieldsTest.f_lowercaseEnum[2], null );
295 |
296 | // FilePath entity field & loading
297 | CiAssert.isNotNull( fileEnt.f_filePath );
298 | CiAssert.isNotNull( project.getAsset(fileEnt.f_filePath) );
299 | CiAssert.isNotNull( fileEnt.f_filePath_bytes );
300 | CiAssert.isTrue( fileEnt.f_filePath_bytes.length>0 );
301 |
302 | // Points / paths
303 | section("Points/paths...");
304 | CiAssert.isTrue( allFieldsTest.f_point.cx==19 );
305 | CiAssert.isTrue( mob.f_path!=null );
306 | CiAssert.isTrue( mob.f_path.length>0 );
307 | CiAssert.isTrue( mob.f_path[0].cy == mob.cy );
308 |
309 | // Worlds untyped access
310 | for(w in project.worlds)
311 | CiAssert.isTrue( Reflect.hasField(project.all_worlds, w.identifier) );
312 | CiAssert.isNotNull( project.getWorld(project.all_worlds.World1.iid) );
313 | CiAssert.isNotNull( project.getWorld(project.all_worlds.World2.iid) );
314 | CiAssert.equals( project.getWorld(project.all_worlds.World1.iid), project.all_worlds.World1 );
315 | CiAssert.equals( project.getWorld(project.all_worlds.World2.iid), project.all_worlds.World2 );
316 | CiAssert.equals( project.worlds[0].layout, ldtk.Json.WorldLayout.GridVania );
317 | CiAssert.equals( project.worlds[1].layout, ldtk.Json.WorldLayout.Free );
318 |
319 | // Enum switch check
320 | section("Switch...");
321 | CiAssert.isTrue( switch defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob[0].f_lootDrops[0] {
322 | case null: false;
323 | case Ammo: true;
324 | case Food: false;
325 | case Gold: false;
326 | case Key: false;
327 | });
328 | switch defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob[0].f_type {
329 | case Trash:
330 | case Shooter:
331 | case Shielder:
332 | }
333 |
334 | // Level custom fields
335 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_level_int, 1 );
336 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_level_string, "my string value" );
337 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_level_reward, Ammo );
338 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.f_level_int, 2 );
339 | CiAssert.equals( defaultWorld.all_levels.Offset_tests.f_level_reward, Key );
340 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_lowercase_enum[0], Lc_a );
341 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_lowercase_enum[1], Lc_b );
342 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_lowercase_enum.length, 2 );
343 | CiAssert.equals( defaultWorld.all_levels.Main_tests.f_lowercase_enum[2], null );
344 |
345 | // Tile layer
346 | section("Tile layer...");
347 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_TileTest );
348 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_TileTest.type, ldtk.Json.LayerType.Tiles );
349 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.resolveLayer("TileTest") );
350 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.identifier=="TileTest" );
351 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.type==Tiles );
352 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.hasAnyTileAt(4,0) );
353 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_TileTest.getTileStackAt(4,0)[0].tileId, 0 );
354 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.hasAnyTileAt(5,0) );
355 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_TileTest.getTileStackAt(5,0)[0].tileId, 1 );
356 |
357 |
358 | // Tilesets
359 | section("Tilesets...");
360 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_TileTest.tileset );
361 | // CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.atlasBytes );
362 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.getTileStackAt(1,4)[0].tileId>=0 );
363 | var gridSize = defaultWorld.all_levels.Main_tests.l_TileTest.tileset.tileGridSize;
364 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.getAtlasX(1)==gridSize );
365 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.getAtlasY(1)==0 );
366 |
367 | // Tilesets enum tags
368 | CiAssert.isNotNull( project.all_tilesets.Minecraft_texture_pack );
369 | CiAssert.isNotNull( project.all_tilesets.Minecraft_texture_pack.hasTag );
370 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_TileTest.tileset );
371 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag );
372 | CiAssert.isTrue( project.all_tilesets.Minecraft_texture_pack.hasTag(0,Grass) );
373 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag(0,Grass) );
374 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag(1,Stone) );
375 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag(3,Grass) );
376 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag(3,Dirt) );
377 | CiAssert.isFalse( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag(1,Grass) );
378 | CiAssert.isFalse( defaultWorld.all_levels.Main_tests.l_TileTest.tileset.hasTag(4,Grass) );
379 |
380 | CiAssert.isNotNull( project.all_tilesets.Cavernas_by_Adam_Saltsman );
381 | CiAssert.isNotNull( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag );
382 | CiAssert.isTrue( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag(0,Lc_a) );
383 | CiAssert.isTrue( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag(1,Lc_b) );
384 | CiAssert.isTrue( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag(2,Lc_c) );
385 | CiAssert.isTrue( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag(3,Lc_d) );
386 | CiAssert.isFalse( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag(1,Lc_a) );
387 | CiAssert.isFalse( project.all_tilesets.Cavernas_by_Adam_Saltsman.hasTag(4,Lc_a) );
388 |
389 |
390 | // Auto-layer (IntGrid)
391 | section("Auto-Layer (IntGrid)...");
392 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_IntGrid_AutoLayer );
393 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_IntGrid_AutoLayer.tileset );
394 | // CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_IntGrid_AutoLayer.tileset.atlasBytes );
395 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGrid_AutoLayer.autoTiles.length>100 );
396 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_IntGrid_AutoLayer.autoTiles[0] );
397 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_IntGrid_AutoLayer.autoTiles[0].renderX!=0 );
398 |
399 | // Auto-layer (pure)
400 | section("Auto-Layer (pure)...");
401 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_Pure_AutoLayer);
402 | // CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_Pure_AutoLayer.tileset.atlasBytes );
403 | CiAssert.equals( defaultWorld.all_levels.Main_tests.l_Pure_AutoLayer.type, ldtk.Json.LayerType.AutoLayer );
404 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_Pure_AutoLayer.tileset );
405 |
406 | // Project references
407 | section("Project refs...");
408 | var level = defaultWorld.all_levels.Main_tests;
409 | @:privateAccess CiAssert.equals( level.untypedProject, project );
410 | @:privateAccess CiAssert.equals( level.l_EntityTest.untypedProject, project );
411 | @:privateAccess CiAssert.equals( level.l_IntGrid_AutoLayer.tileset.untypedProject, project );
412 |
413 |
414 | // Level background image
415 | CiAssert.isTrue( defaultWorld.all_levels.Offset_tests.bgImageInfos==null );
416 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.bgImageInfos );
417 | CiAssert.equals( defaultWorld.all_levels.Main_tests.bgImageInfos.topLeftX, 0 );
418 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.bgImageInfos.cropRect );
419 |
420 |
421 | // Project in a package
422 | section("PROJECT (WITH PACKAGE)...");
423 |
424 | var project = new packageTest.ProjectPackage();
425 | CiAssert.isNotNull( project );
426 | CiAssert.isNotNull( packageTest.ProjectPackage.Enum_Mobs );
427 | CiAssert.isNotNull( packageTest.ProjectPackage.ProjectPackage_EntityEnum );
428 | CiAssert.isNotNull( packageTest.ProjectPackage.Enum_Weapons );
429 | CiAssert.isNotNull( packageTest.ProjectPackage.Tileset_Cavernas_by_Adam_Saltsman );
430 | CiAssert.isNotNull( defaultWorld.all_levels );
431 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.load() );
432 | CiAssert.isTrue( defaultWorld.all_levels.Offset_tests.load() );
433 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests );
434 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob.length>0 );
435 | CiAssert.isNotNull( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Mob[0].f_lootDrops );
436 | CiAssert.isTrue( defaultWorld.all_levels.Main_tests.l_EntityTest.all_Hero[0].f_startWeapon == Enum_Weapons.LongBow );
437 |
438 | // Table of content
439 | CiAssert.isNotNull( project.toc );
440 | CiAssert.isNotNull( project.toc.Hero );
441 | CiAssert.isTrue( project.toc.Hero.length>0 );
442 | CiAssert.equals( project.toc.Hero[0].iids.entityIid, "f2f3d032-66b0-11ec-91ab-159ce9d99f47" );
443 | CiAssert.isNotNull( project.toc.Hero[0].fields );
444 | CiAssert.isNotNull( project.toc.Hero[0].fields.startWeapon );
445 | CiAssert.equals( project.toc.Hero[0].fields.startWeapon, "LongBow" );
446 | CiAssert.isNotNull( project.toc.Mob );
447 | CiAssert.isTrue( project.toc.Mob.length>0 );
448 |
449 |
450 | var world = project.all_worlds.World1;
451 |
452 | // 1.4.0
453 | var l = world.all_levels.v1_4_0;
454 | CiAssert.isNotNull(l);
455 | var e = l.l_EntityTest.all_Hero[0];
456 | CiAssert.isNotNull(e);
457 | CiAssert.equals(e.pixelX, 40);
458 | CiAssert.equals(e.pixelY, 96);
459 | CiAssert.equals(e.worldPixelX, l.worldX+e.pixelX);
460 | CiAssert.equals(e.worldPixelY, l.worldY+e.pixelY);
461 | CiAssert.equals(l.neighbours.length, 1);
462 | CiAssert.equals(l.neighbours[0].dir, ldtk.Level.NeighbourDir.DepthBelow);
463 | }
464 | catch( e:Dynamic ) {
465 | // Unknown errors
466 | print("Exception: "+e);
467 | print("");
468 | exit(1);
469 | return;
470 | }
471 |
472 | if( CiAssert.VERBOSE )
473 | print("");
474 | print("Success.");
475 | exit(0);
476 | }
477 | }
478 |
479 |
--------------------------------------------------------------------------------
/tests/_base.hxml:
--------------------------------------------------------------------------------
1 | -cp tests
2 | -cp samples/_srcCommon
3 | -cp src
4 |
5 | -lib castle
6 | -D ldtkCastle=ExternCastleDbTest
7 |
8 | -lib deepnightLibs
9 | -lib heaps
10 | -D resourcesPath=samples/_assets
11 |
12 | # -D ldtk_times
13 | # -D dump=pretty
14 | --dce full
15 | -debug
16 |
17 | -main Tests
18 |
--------------------------------------------------------------------------------
/tests/hl.hxml:
--------------------------------------------------------------------------------
1 | tests/_base.hxml
2 | -hl tests/bin/test.hl
3 | --cmd hl tests/bin/test.hl -v
--------------------------------------------------------------------------------
/tests/js.hxml:
--------------------------------------------------------------------------------
1 | tests/_base.hxml
2 | -js tests/bin/test.js
3 | -lib hxnodejs
4 | --cmd node tests/bin/test.js -v
--------------------------------------------------------------------------------
/tests/lab/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/settings.json
--------------------------------------------------------------------------------
/tests/lab/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "HL debug",
9 | "request": "launch",
10 | "type": "hl",
11 | "hxml": "hl.hxml",
12 | "cwd": "${workspaceRoot}",
13 | "preLaunchTask": "HL debug"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/tests/lab/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "HL debug",
8 | "type": "hxml",
9 | "file": "hl.hxml",
10 | "presentation": {
11 | "reveal": "never",
12 | "panel": "dedicated",
13 | "clear": true
14 | },
15 | "problemMatcher": ["$haxe"],
16 | "group": {
17 | "kind": "build",
18 | "isDefault": true
19 | }
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/tests/lab/README.md:
--------------------------------------------------------------------------------
1 | # About
2 |
3 | This project is meant to test latest LDtk features in a minimal Heaps environment.
--------------------------------------------------------------------------------
/tests/lab/hl.hxml:
--------------------------------------------------------------------------------
1 | -cp src
2 | -main Boot
3 | -dce full
4 | -debug
5 |
6 | -lib heaps
7 | -lib hldx
8 | -lib deepnightLibs
9 | -lib ldtk-haxe-api
10 |
11 | -D windowSize=1024x768
12 | -hl bin/client.hl
--------------------------------------------------------------------------------
/tests/lab/res/Cavernas_by_Adam_Saltsman-Extended.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deepnight/ldtk-haxe-api/22d7ee209b7a9f5775d53407253ec9432fc588db/tests/lab/res/Cavernas_by_Adam_Saltsman-Extended.png
--------------------------------------------------------------------------------
/tests/lab/src/Boot.hx:
--------------------------------------------------------------------------------
1 | class Boot extends hxd.App {
2 | public static var ME : Boot;
3 |
4 | // Boot
5 | static function main() new Boot();
6 |
7 | // Engine ready
8 | override function init() {
9 | ME = this;
10 |
11 | hxd.Res.initEmbed();
12 |
13 | #if deepnightLibs
14 | new Main();
15 | #end
16 | }
17 |
18 | override function onResize() {
19 | super.onResize();
20 |
21 | #if deepnightLibs
22 | dn.Process.resizeAll();
23 | #end
24 | }
25 |
26 | override function update(deltaTime:Float) {
27 | super.update(deltaTime);
28 | #if deepnightLibs
29 | dn.Process.updateAll(hxd.Timer.tmod);
30 | #end
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/tests/lab/src/LdtkProject.hx:
--------------------------------------------------------------------------------
1 | private typedef _Tmp =
2 | haxe.macro.MacroType<[ ldtk.Project.build("res/apiLab.ldtk") ]>;
--------------------------------------------------------------------------------
/tests/lab/src/Main.hx:
--------------------------------------------------------------------------------
1 | import dn.*;
2 | import LdtkProject;
3 |
4 | class Main extends dn.Process {
5 | var bmp : h2d.Bitmap;
6 | var p : LdtkProject;
7 | var level : LdtkProject_Level;
8 |
9 | public function new() {
10 | super();
11 |
12 | createRoot(Boot.ME.s2d);
13 |
14 | p = new LdtkProject();
15 | level = p.all_levels.World_Level_0;
16 |
17 | // Render
18 | root.addChild( level.l_Collisions.render() );
19 |
20 | // Level tile field
21 | var t = level.f_levelTile_getTile();
22 | if( t!=null )
23 | new h2d.Bitmap(t, root);
24 |
25 | // Entity tiles
26 | for(e in level.l_Entities.all_TilesTest) {
27 | var bmp = new h2d.Bitmap(e.getTile(), root);
28 | bmp.setPosition( e.pixelX, e.pixelY );
29 | }
30 |
31 | // Refs
32 | for(e in level.l_Entities.all_RefSource)
33 | trace(e.f_name+" => "+(e.f_target!=null ? e.f_target.entityIid : null));
34 |
35 | Process.resizeAll();
36 | }
37 |
38 | override function onResize() {
39 | super.onResize();
40 |
41 | root.setScale( dn.heaps.Scaler.bestFit_i(level.pxWid, level.pxHei) );
42 | }
43 |
44 | override function update() {
45 | super.update();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/packageTest/ProjectPackage.hx:
--------------------------------------------------------------------------------
1 | package packageTest;
2 |
3 | private typedef _Tmp = haxe.macro.MacroType<[
4 | ldtk.Project.build("samples/_assets/unitTest.ldtk")
5 | ]>;
--------------------------------------------------------------------------------
/tidy.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | echo Samples...
4 | del samples\index.html /s 2>nul
5 | del samples\build.hxml /s 2>nul
6 | del samples\*.hl /s 2>nul
7 | del samples\*.js /s 2>nul
8 | del samples\buildAll.hxml 2>nul
9 |
10 | echo Dump...
11 | rmdir /Q/S dump 2>nul
12 |
13 | echo Done.
14 | echo.
15 | pause
--------------------------------------------------------------------------------