├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs ├── assets │ ├── css │ │ └── main.css │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ ├── main.js │ │ └── search.js ├── classes │ ├── background.html │ ├── entity.html │ ├── enum.html │ ├── layer.html │ ├── level.html │ ├── tileset.html │ └── world.html ├── enums │ ├── fieldtype.html │ ├── layertype.html │ ├── ldtk.bgpos.html │ ├── ldtk.editordisplaymode.html │ ├── ldtk.editordisplaypos.html │ ├── ldtk.limitbehavior.html │ ├── ldtk.rendermode.html │ ├── ldtk.tilerendermode.html │ ├── ldtk.type.html │ └── ldtk.worldlayout.html ├── index.html ├── interfaces │ ├── boolarrayfield.html │ ├── boolfield.html │ ├── colorarrayfield.html │ ├── colorfield.html │ ├── enumarrayfield.html │ ├── enumfield.html │ ├── enumvalue.html │ ├── filepatharrayfield.html │ ├── filepathfield.html │ ├── floatarrayfield.html │ ├── floatfield.html │ ├── intarrayfield.html │ ├── intfield.html │ ├── intgridvaluedef.html │ ├── ldtk.definitions.html │ ├── ldtk.entitydefinition.html │ ├── ldtk.entityinstance.html │ ├── ldtk.entityinstancetile.html │ ├── ldtk.enumdefinition.html │ ├── ldtk.enumvaluedefinition.html │ ├── ldtk.fielddefinition.html │ ├── ldtk.fieldinstance.html │ ├── ldtk.intgridvaluedefinition.html │ ├── ldtk.intgridvalueinstance.html │ ├── ldtk.layerdefinition.html │ ├── ldtk.layerinstance.html │ ├── ldtk.level.html │ ├── ldtk.levelbackgroundposition.html │ ├── ldtk.neighbourlevel.html │ ├── ldtk.tileinstance.html │ ├── ldtk.tilesetdefinition.html │ ├── ldtk.world.html │ ├── neighbour.html │ ├── point.html │ ├── pointarrayfield.html │ ├── pointfield.html │ ├── size.html │ ├── stringarrayfield.html │ ├── stringfield.html │ └── tile.html └── modules │ └── ldtk.html ├── jest.config.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── index.test.ts ├── index.ts ├── typedef.ts └── util.ts ├── test ├── atlas │ ├── Cavernas_by_Adam_Saltsman.png │ ├── Inca_back2_by_Kronbits.png │ ├── Inca_front_by_Kronbits-extended.png │ ├── Monsters_and_Minions_by_Beowulf.png │ ├── RPG Graphics Icons by 7Soul's.png │ ├── SunnyLand_by_Ansimuz-extended.png │ └── TopDown_by_deepnight.png ├── test.ldtk ├── test_free.ldtk ├── test_gridvania.ldtk ├── test_gridvania_opt.ldtk ├── test_separate.ldtk └── test_separate │ ├── 0000-Level1.ldtkl │ ├── 0001-Level2.ldtkl │ ├── 0002-Level3.ldtkl │ ├── 0003-Level4.ldtkl │ └── backups │ └── test_separate___2021-01-24__17-06-54__crash.backup.ldtk └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | coverage 4 | 5 | webpack.*.js 6 | jest.config.js 7 | rollup.config.js 8 | .eslintrc.js -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: "@typescript-eslint/parser", 4 | plugins: ["@typescript-eslint"], 5 | extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 6 | rules: { 7 | "@typescript-eslint/no-empty-function": "off", 8 | "@typescript-eslint/no-explicit-any": "off", 9 | "@typescript-eslint/no-non-null-assertion": "off", 10 | "@typescript-eslint/ban-ts-comment": "off", 11 | "@typescript-eslint/no-namespace": "off", 12 | "@typescript-eslint/explicit-module-boundary-types": "off", 13 | "@typescript-eslint/no-var-requires": "off", 14 | "@typescript-eslint/no-inferrable-types": "off", 15 | "no-debugger": "off", 16 | "no-fallthrough": "off", 17 | "no-constant-condition": "off", 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: CI 4 | 5 | jobs: 6 | # runs typescript build + test 7 | ts: 8 | name: TypeScript 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | node_version: 13 | - 14 14 | - 15 15 | steps: 16 | # get code + setup node toolchain 17 | - name: Checkout code 18 | uses: actions/checkout@v2 19 | - name: Get Node toolchain 20 | uses: actions/setup-node@v2 21 | with: 22 | node-version: ${{ matrix.node_version }} 23 | 24 | - name: Cache node modules 25 | uses: actions/cache@v2 26 | env: 27 | cache-name: cache-node-modules 28 | with: 29 | # npm cache files are stored in `~/.npm` on Linux/macOS 30 | path: ~/.npm 31 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} 32 | restore-keys: | 33 | ${{ runner.os }}-build-${{ env.cache-name }}- 34 | ${{ runner.os }}-build- 35 | ${{ runner.os }}- 36 | 37 | # install, build, test 38 | - name: Install dependencies 39 | run: npm ci 40 | - name: Build package 41 | run: npm run build 42 | - name: Run tests 43 | run: npm run test 44 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [created] 4 | 5 | name: Node.js Package 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | # Setup .npmrc file to publish to npm 13 | - uses: actions/setup-node@v1 14 | with: 15 | node-version: '14.x' 16 | registry-url: 'https://registry.npmjs.org' 17 | 18 | - name: Cache node modules 19 | uses: actions/cache@v2 20 | env: 21 | cache-name: cache-node-modules 22 | with: 23 | # npm cache files are stored in `~/.npm` on Linux/macOS 24 | path: ~/.npm 25 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} 26 | restore-keys: | 27 | ${{ runner.os }}-build-${{ env.cache-name }}- 28 | ${{ runner.os }}-build- 29 | ${{ runner.os }}- 30 | 31 | - name: Install dependencies 32 | run: npm ci 33 | - name: Publish package to NPM 34 | run: npm publish 35 | env: 36 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store 3 | node_modules 4 | coverage 5 | dist 6 | yarn.lock -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Jan Procházka 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ldtk-ts 2 | 3 | [LDtk](https://ldtk.io/) file format type definitions and import wrapper. 4 | 5 | This library provides an API without all the noise of LDtk "editor-only" values, 6 | definitions, etc., combined with many utilities to make usage easier. 7 | 8 | If you just want the type definitions, they're fully compliant with the [schema](https://ldtk.io/files/JSON_SCHEMA.json). 9 | 10 | Documentation is available [here](https://www.jan-prochazka.eu/ldtk-ts). 11 | 12 | ```s 13 | $ npm install ldtk 14 | ``` 15 | 16 | ### Usage 17 | 18 | **Basic usage** 19 | 20 | ```ts 21 | import { World } from "ldtk"; 22 | 23 | World.loadRaw("assets/world.ldtk").then(async world => { 24 | // You have access to the raw `LDtk` JSON file here 25 | let currentLevel = world.levels[0]; 26 | for (const layer of currentLevel.layerInstances) { 27 | console.log(layer); 28 | // the world is your oyster 29 | } 30 | }) 31 | ``` 32 | 33 | **Using the importer** 34 | 35 | ```ts 36 | import { World, LDtk } from "ldtk"; 37 | 38 | World.fromURL("assets/world.ldtk").then(async world => { 39 | let currentLevel = world.levelMap["Level1"]; 40 | function loop(time) { 41 | render(currentLevel); 42 | 43 | window.requestAnimationFrame(loop); 44 | } 45 | window.requestAnimationFrame(loop) 46 | }); 47 | ``` 48 | 49 | ### Versioning table 50 | 51 | LDtk | ldtk-ts 52 | :-----:|:-------: 53 | 0.7.2 | 0.8.6 54 | 0.7.1 | 0.8.5 55 | <0.7.0 | not supported -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /docs/enums/ldtk.tilerendermode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TileRenderMode | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 64 |

Enumeration TileRenderMode

65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |

Possible values: "Crop", "Stretch"

75 |
76 |
77 |
78 |
79 |

Index

80 |
81 |
82 |
83 |

Enumeration members

84 | 88 |
89 |
90 |
91 |
92 |
93 |

Enumeration members

94 |
95 | 96 |

Crop

97 |
Crop: = "Crop"
98 | 103 |
104 |
105 | 106 |

Stretch

107 |
Stretch: = "Stretch"
108 | 113 |
114 |
115 |
116 | 222 |
223 |
224 | 246 |
247 |

Generated using TypeDoc

248 |
249 |
250 | 251 | 252 | -------------------------------------------------------------------------------- /docs/interfaces/boolarrayfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BoolArrayField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface BoolArrayField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | BoolArrayField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: BoolArray
107 | 112 |
113 |
114 | 115 |

value

116 |
value: boolean[]
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/boolfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BoolField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface BoolField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | BoolField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: Bool
107 | 112 |
113 |
114 | 115 |

value

116 |
value: null | boolean
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/colorarrayfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ColorArrayField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface ColorArrayField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | ColorArrayField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 | 107 | 112 |
113 |
114 | 115 |

value

116 |
value: string[]
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/colorfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ColorField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface ColorField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | ColorField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: Color
107 | 112 |
113 |
114 | 115 |

value

116 |
value: null | string
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/floatarrayfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | FloatArrayField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface FloatArrayField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | FloatArrayField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 | 107 | 112 |
113 |
114 | 115 |

value

116 |
value: number[]
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/floatfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | FloatField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface FloatField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | FloatField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: Float
107 | 112 |
113 |
114 | 115 |

value

116 |
value: null | number
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/intarrayfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IntArrayField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface IntArrayField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | IntArrayField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: IntArray
107 | 112 |
113 |
114 | 115 |

value

116 |
value: number[]
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/intfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IntField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface IntField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | IntField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: Int
107 | 112 |
113 |
114 | 115 |

value

116 |
value: null | number
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/intgridvaluedef.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IntGridValueDef | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface IntGridValueDef

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | IntGridValueDef 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 86 |
87 |
88 |
89 |
90 |
91 |

Properties

92 |
93 | 94 |

color

95 |
color: string
96 | 101 |
102 |
103 |

Color (RGB hex string)

104 |
105 |
106 |
107 |
108 | 109 |

id

110 |
id: null | string
111 | 116 |
117 |
118 |

Unique string identifier

119 |
120 |
121 |
122 |
123 |
124 | 245 |
246 |
247 | 269 |
270 |

Generated using TypeDoc

271 |
272 |
273 | 274 | 275 | -------------------------------------------------------------------------------- /docs/interfaces/neighbour.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Neighbour | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface Neighbour

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |

Contains the neighbour's direction relative to this level 72 | and a reference to the neighbour.

73 |
74 |
75 |
76 |
77 |

Hierarchy

78 |
    79 |
  • 80 | Neighbour 81 |
  • 82 |
83 |
84 |
85 |

Index

86 |
87 |
88 |
89 |

Properties

90 | 94 |
95 |
96 |
97 |
98 |
99 |

Properties

100 |
101 | 102 |

dir

103 |
dir: "n" | "s" | "w" | "e"
104 | 109 |
110 |
111 | 112 |

level

113 |
level: Level
114 | 119 |
120 |
121 |
122 | 243 |
244 |
245 | 267 |
268 |

Generated using TypeDoc

269 |
270 |
271 | 272 | 273 | -------------------------------------------------------------------------------- /docs/interfaces/point.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Point | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 |
    54 |
  • 55 | ldtk 56 |
  • 57 |
  • 58 | Point 59 |
  • 60 |
61 |

Interface Point

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |

Represents a point in 2D space (X, Y)

72 |
73 |
74 |
75 |
76 |

Hierarchy

77 |
    78 |
  • 79 | Point 80 |
  • 81 |
82 |
83 |
84 |

Index

85 |
86 |
87 |
88 |

Properties

89 |
    90 |
  • x
  • 91 |
  • y
  • 92 |
93 |
94 |
95 |
96 |
97 |
98 |

Properties

99 |
100 | 101 |

x

102 |
x: number
103 | 108 |
109 |
110 | 111 |

y

112 |
y: number
113 | 118 |
119 |
120 |
121 | 242 |
243 |
244 | 266 |
267 |

Generated using TypeDoc

268 |
269 |
270 | 271 | 272 | -------------------------------------------------------------------------------- /docs/interfaces/pointfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PointField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface PointField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | PointField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: Point
107 | 112 |
113 |
114 | 115 |

value

116 |
value: null | Point
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/interfaces/size.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Size | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 |
    54 |
  • 55 | ldtk 56 |
  • 57 |
  • 58 | Size 59 |
  • 60 |
61 |

Interface Size

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |

Represents a 2D size (width, height)

72 |
73 |
74 |
75 |
76 |

Hierarchy

77 |
    78 |
  • 79 | Size 80 |
  • 81 |
82 |
83 |
84 |

Index

85 |
86 |
87 |
88 |

Properties

89 | 93 |
94 |
95 |
96 |
97 |
98 |

Properties

99 |
100 | 101 |

height

102 |
height: number
103 | 108 |
109 |
110 | 111 |

width

112 |
width: number
113 | 118 |
119 |
120 |
121 | 242 |
243 |
244 | 266 |
267 |

Generated using TypeDoc

268 |
269 |
270 | 271 | 272 | -------------------------------------------------------------------------------- /docs/interfaces/stringfield.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | StringField | ldtk 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | 28 |
29 |
30 | Options 31 |
32 |
33 | All 34 |
    35 |
  • Public
  • 36 |
  • Public/Protected
  • 37 |
  • All
  • 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 | Menu 47 |
48 |
49 |
50 |
51 |
52 |
53 | 61 |

Interface StringField

62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |

Hierarchy

70 |
    71 |
  • 72 | StringField 73 |
  • 74 |
75 |
76 |
77 |

Index

78 |
79 |
80 |
81 |

Properties

82 | 87 |
88 |
89 |
90 |
91 |
92 |

Properties

93 |
94 | 95 |

id

96 |
id: string
97 | 102 |
103 |
104 | 105 |

type

106 |
type: String
107 | 112 |
113 |
114 | 115 |

value

116 |
value: null | string
117 | 122 |
123 |
124 |
125 | 249 |
250 |
251 | 273 |
274 |

Generated using TypeDoc

275 |
276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: ["/src"], 3 | transform: { 4 | "^.+\\.ts?$": "ts-jest", 5 | }, 6 | testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.ts?$", 7 | testEnvironment: "node", 8 | moduleFileExtensions: ["ts", "js"], 9 | moduleDirectories: ["node_modules", "src"], 10 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ldtk", 3 | "version": "0.8.7", 4 | "description": "Importer for the LDtk project file format", 5 | "author": "Jan Procházka", 6 | "license": "MIT", 7 | "homepage": "https://github.com/jprochazk/ldtk-ts", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/jprochazk/ldtk-ts.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/jprochazk/ldtk-ts/issues" 14 | }, 15 | "keywords": [ 16 | "ldtk", 17 | "parse", 18 | "parser" 19 | ], 20 | "main": "dist/index.cjs.js", 21 | "module": "dist/index.esm.js", 22 | "browser": "dist/index.umd.js", 23 | "types": "dist/index.d.ts", 24 | "files": [ 25 | "/dist", 26 | "LICENSE" 27 | ], 28 | "scripts": { 29 | "test": "jest", 30 | "build": "rollup -c", 31 | "prepare": "npm run build", 32 | "build-docs": "typedoc src/index.ts --readme none" 33 | }, 34 | "devDependencies": { 35 | "@rollup/plugin-commonjs": "^15.1.0", 36 | "@rollup/plugin-json": "^4.1.0", 37 | "@rollup/plugin-node-resolve": "^9.0.0", 38 | "@types/jest": "^26.0.20", 39 | "@typescript-eslint/eslint-plugin": "^4.14.1", 40 | "@typescript-eslint/parser": "^4.14.1", 41 | "eslint": "^7.18.0", 42 | "jest": "^26.6.3", 43 | "node-fetch": "^2.6.1", 44 | "rollup": "^2.38.0", 45 | "rollup-plugin-terser": "^7.0.2", 46 | "rollup-plugin-typescript2": "^0.27.3", 47 | "ts-jest": "^26.4.4", 48 | "tslib": "^2.1.0", 49 | "typedoc": "^0.20.19", 50 | "typescript": "^4.1.3" 51 | }, 52 | "dependencies": {} 53 | } 54 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from "rollup-plugin-typescript2"; 2 | import json from "@rollup/plugin-json"; 3 | import { terser } from "rollup-plugin-terser"; 4 | import pkg from "./package.json"; 5 | 6 | export default [ 7 | // UMD, CJS, ESM 8 | { 9 | input: "src/index.ts", 10 | plugins: [ 11 | json(), 12 | typescript({ 13 | typescript: require("typescript"), 14 | }), 15 | terser({ 16 | output: { 17 | comments: false, 18 | }, 19 | }), 20 | ], 21 | output: [ 22 | { exports: "named", file: pkg.main, format: "cjs" }, 23 | { file: pkg.module, format: "es" }, 24 | { name: "packet", file: pkg.browser, format: "umd" }, 25 | ], 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /src/index.test.ts: -------------------------------------------------------------------------------- 1 | import { World, LDtk, EnumField, Field } from "./index"; 2 | import * as fs from "fs"; 3 | 4 | const fetch = (path: string): T => JSON.parse(fs.readFileSync(path, { encoding: "utf-8" })); 5 | 6 | // we want to be inside the `test` directory so that 7 | // loading relative-path assets works correctly 8 | process.chdir("test"); 9 | 10 | /** 11 | * Joins two arrays into an array of tuples. 12 | * If the two array lengths don't match, the extra 13 | * values from the longer one are paired with `null` values. 14 | * 15 | * ``` 16 | * zip([0, 1, 2], ['a', 'b', 'c']) // [[0, 'a'], [1, 'b'], [2, 'c']] 17 | * zip([0, 1], ['a', 'b', 'c']) // [[0, 'a'], [1, 'b'], [null, 'c']] 18 | * ``` 19 | */ 20 | function zip(a: A[], b: B[]) { 21 | const zipped: [A | null, B | null][] = []; 22 | for (let i = 0, len = a.length > b.length ? a.length : b.length; i < len; ++i) { 23 | zipped.push([a[i] ?? null, b[i] ?? null]); 24 | } 25 | return zipped; 26 | } 27 | 28 | function compareFields(o: LDtk.FieldInstance, p: Field) { 29 | // type check abbreviation 30 | const T = (name: string) => o.__type.includes(name); 31 | // TODO: separate test for type transformation 32 | // just check values here 33 | const o_val = o.__value as any; 34 | const p_val = p.value as any; 35 | switch (true) { 36 | // simple comparison - most can be compared 37 | // with just expect.toEqual 38 | case T("Int"): /* @fallthrough */ 39 | case T("Float"): /* @fallthrough */ 40 | case T("String"): /* @fallthrough */ 41 | case T("Bool"): /* @fallthrough */ 42 | case T("Color"): /* @fallthrough */ 43 | case T("FilePath"): 44 | expect(o_val).toEqual(p_val); 45 | break; 46 | // array special-cases 47 | case T("Array"): 48 | switch (true) { 49 | case T("Point"): 50 | zip(o_val, p_val).forEach(([o, p]) => 51 | o == null 52 | // if o is null, p should be too 53 | ? expect(p).toBeNull() 54 | // otherwise their fields should match 55 | : (expect(o.cx).toEqual(p.x), expect(o.cy).toEqual(p.y))); 56 | break; 57 | case T("Enum"): 58 | expect(T((p as EnumField).ref.id)).toEqual(true); 59 | break; 60 | } 61 | break; 62 | // non-array special cases 63 | case !T("Array"): 64 | switch (true) { 65 | case T("Point"): 66 | o_val == null 67 | ? expect(p_val).toBeNull() 68 | : (expect(o_val.cx).toEqual(p_val.x), expect(o_val.cy).toEqual(p_val.y)) 69 | break; 70 | case T("Enum"): 71 | expect(T((p as EnumField).ref.id)).toEqual(true); 72 | } 73 | break; 74 | } 75 | } 76 | 77 | describe("importer", () => { 78 | it("full API", () => { // Compares official Full API sample data with the processed data. 79 | const data = fetch("test.ldtk"); 80 | const world = World.fromJSON(data); 81 | 82 | expect(world.bgColor).toEqual(data.bgColor); 83 | expect(world.layout).toEqual(data.worldLayout); 84 | expect(world.externalLevels).toEqual(data.externalLevels); 85 | // enums 86 | expect(data.defs!.enums.length).toEqual(world.enums.length); 87 | for (let enumIdx = 0; enumIdx < data.defs!.enums.length; ++enumIdx) { 88 | const o_enum = data.defs!.enums[enumIdx]; 89 | const p_enum = world.enums[enumIdx]; 90 | expect(p_enum.id).toEqual(o_enum.identifier); 91 | expect(p_enum.uid).toEqual(o_enum.uid); 92 | zip(o_enum.values, p_enum.values).forEach(([o, p]) => ( 93 | expect(o?.id).toEqual(p?.id), 94 | expect(o?.__tileSrcRect[0]).toEqual(p?.tileSrcRect.x), 95 | expect(o?.__tileSrcRect[1]).toEqual(p?.tileSrcRect.y), 96 | expect(o?.__tileSrcRect[2]).toEqual(p?.tileSrcRect.width), 97 | expect(o?.__tileSrcRect[3]).toEqual(p?.tileSrcRect.height))); 98 | expect(o_enum.iconTilesetUid).toEqual(p_enum.tileset?.uid); 99 | } 100 | // tilesets 101 | expect(data.defs!.tilesets.length).toEqual(world.tilesets.length); 102 | for (let tilesetIdx = 0; tilesetIdx < data.defs!.tilesets.length; ++tilesetIdx) { 103 | const o_tileset = data.defs!.tilesets[tilesetIdx]; 104 | const p_tileset = world.tilesets[tilesetIdx]; 105 | expect(p_tileset.id).toEqual(o_tileset.identifier) 106 | expect(p_tileset.uid).toEqual(o_tileset.uid) 107 | expect(p_tileset.size.width).toEqual(o_tileset.pxWid); 108 | expect(p_tileset.size.height).toEqual(o_tileset.pxHei); 109 | expect(p_tileset.gridSize).toEqual(o_tileset.tileGridSize); 110 | expect(p_tileset.spacing).toEqual(o_tileset.spacing); 111 | expect(p_tileset.padding).toEqual(o_tileset.padding); 112 | expect(p_tileset.path).toEqual(o_tileset.relPath); 113 | } 114 | // levels 115 | expect(data.levels.length).toEqual(world.levels.length); 116 | for (let levelIdx = 0; levelIdx < data.levels.length; ++levelIdx) { 117 | // prefix 'o_' = original data 118 | // prefix 'p_' = processed data 119 | const o_level = data.levels[levelIdx]; 120 | const p_level = world.levels[levelIdx]; 121 | expect(p_level.id).toEqual(o_level.identifier); 122 | expect(p_level.uid).toEqual(o_level.uid); 123 | expect(p_level.background.color).toEqual(o_level.__bgColor); 124 | expect(p_level.background.path).toEqual(o_level.bgRelPath); 125 | expect(p_level.background.pivot.x).toEqual(o_level.bgPivotX); 126 | expect(p_level.background.pivot.y).toEqual(o_level.bgPivotY); 127 | expect(p_level.background.pos).toEqual(o_level.__bgPos); 128 | expect(p_level.size.width).toEqual(o_level.pxWid); 129 | expect(p_level.size.height).toEqual(o_level.pxHei); 130 | zip(o_level.__neighbours, p_level.neighbours).forEach(([o, p]) => ( 131 | expect(o?.dir).toEqual(p?.dir), 132 | expect(o?.levelUid).toEqual(p?.level.uid))); 133 | if (o_level.layerInstances != null) { 134 | expect(o_level.layerInstances.length).toEqual(p_level.layers.length); 135 | for (let layerIdx = 0; layerIdx < o_level.layerInstances.length; ++layerIdx) { 136 | const o_layer = o_level.layerInstances[layerIdx]; 137 | const p_layer = p_level.layers[layerIdx]; 138 | expect(p_layer.gridSize).toEqual(o_layer.__gridSize); 139 | expect(p_layer.opacity).toEqual(o_layer.__opacity); 140 | expect(p_layer.pxTotalOffset.x).toEqual(o_layer.__pxTotalOffsetX); 141 | expect(p_layer.pxTotalOffset.y).toEqual(o_layer.__pxTotalOffsetY); 142 | expect(p_layer.uid).toEqual(o_layer.layerDefUid); 143 | expect(p_layer.size.width).toEqual(o_layer.__cWid); 144 | expect(p_layer.size.height).toEqual(o_layer.__cHei); 145 | expect(p_layer.type).toEqual(o_layer.__type); 146 | expect(p_layer.tileset?.uid ?? null).toEqual(o_layer.__tilesetDefUid); 147 | if (o_layer.__type === "AutoLayer") { 148 | // auto layer tiles aren't preprocessed 149 | expect(p_layer.autoLayerTiles).not.toBeNull(); 150 | expect(o_layer.autoLayerTiles).toEqual(p_layer.autoLayerTiles); 151 | } 152 | else if (o_layer.__type === "Entities") { 153 | expect(p_layer.entities).not.toBeNull(); 154 | expect(o_layer.entityInstances.length).toEqual(p_layer.entities!.length); 155 | for (let entityIdx = 0; entityIdx < o_layer.entityInstances.length; ++entityIdx) { 156 | const o_entity = o_layer.entityInstances[entityIdx]; 157 | const p_entity = p_layer.entities![entityIdx]; 158 | expect(o_entity.fieldInstances.length).toEqual(Object.keys(p_entity.fields).length); 159 | for (const o_field of o_entity.fieldInstances) { 160 | const p_field = p_entity.fields[o_field.__identifier]; 161 | // field must exist 162 | expect(p_field != null).toEqual(true); 163 | compareFields(o_field, p_field); 164 | } 165 | 166 | } 167 | } 168 | else if (o_layer.__type === "Tiles") { 169 | // grid tiles aren't preprocessed 170 | expect(p_layer.gridTiles).not.toBeNull(); 171 | expect(o_layer.gridTiles).toEqual(p_layer.gridTiles); 172 | } 173 | else if (o_layer.__type === "IntGrid") { 174 | // TODO 175 | expect(p_layer.intGrid).not.toBeNull(); 176 | for (let intGridIdx = 0; intGridIdx < o_layer.intGrid.length; ++intGridIdx) { 177 | const o_igValue = o_layer.intGrid[intGridIdx]; 178 | const y = Math.floor(o_igValue.coordId / o_layer.__cWid); 179 | const x = o_igValue.coordId - y * o_layer.__cWid; 180 | const p_igValue = p_layer.intGrid![x][y]; 181 | expect(o_igValue.v).toEqual(p_igValue); 182 | } 183 | } 184 | } 185 | } 186 | } 187 | }); 188 | it("gridvania", () => { 189 | const data = fetch("test_gridvania.ldtk"); 190 | World.fromJSON(data); 191 | }); 192 | it("free layout", () => { 193 | const data = fetch("test_free.ldtk"); 194 | World.fromJSON(data); 195 | }); 196 | it("separate files", async () => { 197 | const data = fetch("test_separate.ldtk"); 198 | const world = World.fromJSON(data); 199 | // separate files start with 0 levels 200 | expect(world.levels.length).toEqual(0); 201 | // load one 202 | await world.loadLevel("Level1"); 203 | expect(world.levels.length).toEqual(1); 204 | // no duplicates 205 | await world.loadLevel("Level1"); 206 | expect(world.levels.length).toEqual(1); 207 | // load the rest 208 | await world.loadLevels(); 209 | expect(world.levels.length).toEqual(data.levels.length); 210 | }); 211 | }); -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'; 2 | 3 | const loadJSON = (() => { 4 | if (isBrowser) { 5 | return async function loadJSON(path: string): Promise { 6 | const data = await fetch(path); 7 | return await data.json(); 8 | } 9 | } else { 10 | const fs = require("fs"); 11 | return async function loadJSON(path: string): Promise { 12 | return new Promise((resolve, reject) => { 13 | fs.readFile(path, { encoding: "utf-8" }, (err: NodeJS.ErrnoException, data: string) => { 14 | if (err != null) reject(err) 15 | resolve(JSON.parse(data)); 16 | }) 17 | }); 18 | } 19 | } 20 | })(); 21 | 22 | export { 23 | isBrowser, 24 | loadJSON 25 | }; 26 | -------------------------------------------------------------------------------- /test/atlas/Cavernas_by_Adam_Saltsman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Cavernas_by_Adam_Saltsman.png -------------------------------------------------------------------------------- /test/atlas/Inca_back2_by_Kronbits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Inca_back2_by_Kronbits.png -------------------------------------------------------------------------------- /test/atlas/Inca_front_by_Kronbits-extended.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Inca_front_by_Kronbits-extended.png -------------------------------------------------------------------------------- /test/atlas/Monsters_and_Minions_by_Beowulf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Monsters_and_Minions_by_Beowulf.png -------------------------------------------------------------------------------- /test/atlas/RPG Graphics Icons by 7Soul's.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/RPG Graphics Icons by 7Soul's.png -------------------------------------------------------------------------------- /test/atlas/SunnyLand_by_Ansimuz-extended.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/SunnyLand_by_Ansimuz-extended.png -------------------------------------------------------------------------------- /test/atlas/TopDown_by_deepnight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/TopDown_by_deepnight.png -------------------------------------------------------------------------------- /test/test_separate/0002-Level3.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": "0.7.2", 9 | "url": "https://ldtk.io" 10 | }, 11 | "identifier": "Level3", 12 | "uid": 33, 13 | "worldX": 0, 14 | "worldY": 768, 15 | "pxWid": 256, 16 | "pxHei": 160, 17 | "__bgColor": "#373852", 18 | "bgColor": null, 19 | "bgRelPath": null, 20 | "bgPos": null, 21 | "bgPivotX": 0.5, 22 | "bgPivotY": 0.5, 23 | "__bgPos": null, 24 | "externalRelPath": null, 25 | "layerInstances": [ 26 | { 27 | "__identifier": "IntGrid_8px_grid", 28 | "__type": "IntGrid", 29 | "__cWid": 32, 30 | "__cHei": 20, 31 | "__gridSize": 8, 32 | "__opacity": 1, 33 | "__pxTotalOffsetX": 0, 34 | "__pxTotalOffsetY": 0, 35 | "__tilesetDefUid": null, 36 | "__tilesetRelPath": null, 37 | "levelId": 33, 38 | "layerDefUid": 34, 39 | "pxOffsetX": 0, 40 | "pxOffsetY": 0, 41 | "intGrid": [], 42 | "autoLayerTiles": [], 43 | "seed": 9843615, 44 | "gridTiles": [], 45 | "entityInstances": [] 46 | }, 47 | { 48 | "__identifier": "Entities", 49 | "__type": "Entities", 50 | "__cWid": 16, 51 | "__cHei": 10, 52 | "__gridSize": 16, 53 | "__opacity": 1, 54 | "__pxTotalOffsetX": 0, 55 | "__pxTotalOffsetY": 0, 56 | "__tilesetDefUid": null, 57 | "__tilesetRelPath": null, 58 | "levelId": 33, 59 | "layerDefUid": 13, 60 | "pxOffsetX": 0, 61 | "pxOffsetY": 0, 62 | "intGrid": [], 63 | "autoLayerTiles": [], 64 | "seed": 8894473, 65 | "gridTiles": [], 66 | "entityInstances": [] 67 | }, 68 | { 69 | "__identifier": "PureAutoLayer", 70 | "__type": "AutoLayer", 71 | "__cWid": 16, 72 | "__cHei": 10, 73 | "__gridSize": 16, 74 | "__opacity": 1, 75 | "__pxTotalOffsetX": 0, 76 | "__pxTotalOffsetY": 0, 77 | "__tilesetDefUid": 2, 78 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png", 79 | "levelId": 33, 80 | "layerDefUid": 26, 81 | "pxOffsetX": 0, 82 | "pxOffsetY": 0, 83 | "intGrid": [], 84 | "autoLayerTiles": [], 85 | "seed": 106526, 86 | "gridTiles": [], 87 | "entityInstances": [] 88 | }, 89 | { 90 | "__identifier": "IntGrid_classic", 91 | "__type": "IntGrid", 92 | "__cWid": 16, 93 | "__cHei": 10, 94 | "__gridSize": 16, 95 | "__opacity": 1, 96 | "__pxTotalOffsetX": 0, 97 | "__pxTotalOffsetY": 0, 98 | "__tilesetDefUid": null, 99 | "__tilesetRelPath": null, 100 | "levelId": 33, 101 | "layerDefUid": 1, 102 | "pxOffsetX": 0, 103 | "pxOffsetY": 0, 104 | "intGrid": [ 105 | { "coordId": 20, "v": 0 }, 106 | { "coordId": 21, "v": 0 }, 107 | { "coordId": 22, "v": 0 }, 108 | { "coordId": 23, "v": 0 }, 109 | { "coordId": 24, "v": 0 }, 110 | { "coordId": 25, "v": 0 }, 111 | { "coordId": 26, "v": 0 }, 112 | { "coordId": 27, "v": 0 }, 113 | { "coordId": 65, "v": 1 }, 114 | { "coordId": 78, "v": 1 }, 115 | { "coordId": 81, "v": 1 }, 116 | { "coordId": 94, "v": 1 }, 117 | { "coordId": 132, "v": 0 }, 118 | { "coordId": 133, "v": 0 }, 119 | { "coordId": 134, "v": 0 }, 120 | { "coordId": 135, "v": 0 }, 121 | { "coordId": 136, "v": 0 }, 122 | { "coordId": 137, "v": 0 }, 123 | { "coordId": 138, "v": 0 }, 124 | { "coordId": 139, "v": 0 } 125 | ], 126 | "autoLayerTiles": [], 127 | "seed": 3262174, 128 | "gridTiles": [], 129 | "entityInstances": [] 130 | }, 131 | { 132 | "__identifier": "IntGrid_with_rules", 133 | "__type": "IntGrid", 134 | "__cWid": 16, 135 | "__cHei": 10, 136 | "__gridSize": 16, 137 | "__opacity": 1, 138 | "__pxTotalOffsetX": 0, 139 | "__pxTotalOffsetY": 0, 140 | "__tilesetDefUid": 2, 141 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png", 142 | "levelId": 33, 143 | "layerDefUid": 3, 144 | "pxOffsetX": 0, 145 | "pxOffsetY": 0, 146 | "intGrid": [ 147 | { "coordId": 52, "v": 0 }, 148 | { "coordId": 53, "v": 0 }, 149 | { "coordId": 54, "v": 0 }, 150 | { "coordId": 55, "v": 0 }, 151 | { "coordId": 56, "v": 0 }, 152 | { "coordId": 57, "v": 0 }, 153 | { "coordId": 58, "v": 0 }, 154 | { "coordId": 59, "v": 0 }, 155 | { "coordId": 68, "v": 0 }, 156 | { "coordId": 69, "v": 0 }, 157 | { "coordId": 70, "v": 0 }, 158 | { "coordId": 71, "v": 0 }, 159 | { "coordId": 72, "v": 0 }, 160 | { "coordId": 73, "v": 0 }, 161 | { "coordId": 74, "v": 0 }, 162 | { "coordId": 75, "v": 0 }, 163 | { "coordId": 84, "v": 0 }, 164 | { "coordId": 85, "v": 0 }, 165 | { "coordId": 86, "v": 0 }, 166 | { "coordId": 87, "v": 0 }, 167 | { "coordId": 88, "v": 0 }, 168 | { "coordId": 89, "v": 0 }, 169 | { "coordId": 90, "v": 0 }, 170 | { "coordId": 91, "v": 0 }, 171 | { "coordId": 100, "v": 0 }, 172 | { "coordId": 101, "v": 0 }, 173 | { "coordId": 102, "v": 0 }, 174 | { "coordId": 103, "v": 0 }, 175 | { "coordId": 104, "v": 0 }, 176 | { "coordId": 105, "v": 0 }, 177 | { "coordId": 106, "v": 0 }, 178 | { "coordId": 107, "v": 0 } 179 | ], 180 | "autoLayerTiles": [ 181 | { "px": [80,48], "src": [0,112], "f": 0, "t": 140, "d": [5,53] }, 182 | { "px": [112,48], "src": [0,112], "f": 0, "t": 140, "d": [5,55] }, 183 | { "px": [144,48], "src": [0,112], "f": 0, "t": 140, "d": [5,57] }, 184 | { "px": [80,64], "src": [0,112], "f": 0, "t": 140, "d": [5,69] }, 185 | { "px": [112,64], "src": [0,112], "f": 0, "t": 140, "d": [5,71] }, 186 | { "px": [144,64], "src": [0,112], "f": 0, "t": 140, "d": [5,73] }, 187 | { "px": [176,64], "src": [0,112], "f": 0, "t": 140, "d": [5,75] }, 188 | { "px": [64,80], "src": [0,112], "f": 0, "t": 140, "d": [5,84] }, 189 | { "px": [80,80], "src": [0,112], "f": 0, "t": 140, "d": [5,85] }, 190 | { "px": [96,80], "src": [0,112], "f": 0, "t": 140, "d": [5,86] }, 191 | { "px": [112,80], "src": [0,112], "f": 0, "t": 140, "d": [5,87] }, 192 | { "px": [128,80], "src": [0,112], "f": 0, "t": 140, "d": [5,88] }, 193 | { "px": [144,80], "src": [0,112], "f": 0, "t": 140, "d": [5,89] }, 194 | { "px": [160,80], "src": [0,112], "f": 0, "t": 140, "d": [5,90] }, 195 | { "px": [176,80], "src": [0,112], "f": 0, "t": 140, "d": [5,91] }, 196 | { "px": [80,96], "src": [0,112], "f": 0, "t": 140, "d": [5,101] }, 197 | { "px": [112,96], "src": [0,112], "f": 0, "t": 140, "d": [5,103] }, 198 | { "px": [144,96], "src": [0,112], "f": 0, "t": 140, "d": [5,105] }, 199 | { "px": [176,48], "src": [64,128], "f": 1, "t": 164, "d": [7,59] }, 200 | { "px": [176,96], "src": [64,128], "f": 3, "t": 164, "d": [7,107] }, 201 | { "px": [64,64], "src": [128,0], "f": 0, "t": 8, "d": [6,68] }, 202 | { "px": [64,80], "src": [128,16], "f": 0, "t": 28, "d": [6,68] }, 203 | { "px": [80,64], "src": [144,0], "f": 0, "t": 9, "d": [6,68] }, 204 | { "px": [80,80], "src": [144,16], "f": 0, "t": 29, "d": [6,68] }, 205 | { "px": [96,64], "src": [128,0], "f": 0, "t": 8, "d": [6,70] }, 206 | { "px": [96,80], "src": [128,16], "f": 0, "t": 28, "d": [6,70] }, 207 | { "px": [112,64], "src": [144,0], "f": 0, "t": 9, "d": [6,70] }, 208 | { "px": [112,80], "src": [144,16], "f": 0, "t": 29, "d": [6,70] }, 209 | { "px": [128,64], "src": [128,0], "f": 0, "t": 8, "d": [6,72] }, 210 | { "px": [128,80], "src": [128,16], "f": 0, "t": 28, "d": [6,72] }, 211 | { "px": [144,64], "src": [144,0], "f": 0, "t": 9, "d": [6,72] }, 212 | { "px": [144,80], "src": [144,16], "f": 0, "t": 29, "d": [6,72] }, 213 | { "px": [160,64], "src": [128,0], "f": 0, "t": 8, "d": [6,74] }, 214 | { "px": [160,80], "src": [128,16], "f": 0, "t": 28, "d": [6,74] }, 215 | { "px": [176,64], "src": [144,0], "f": 0, "t": 9, "d": [6,74] }, 216 | { "px": [176,80], "src": [144,16], "f": 0, "t": 29, "d": [6,74] }, 217 | { "px": [64,48], "src": [64,80], "f": 0, "t": 104, "d": [9,52] }, 218 | { "px": [80,48], "src": [80,80], "f": 0, "t": 105, "d": [9,52] }, 219 | { "px": [96,48], "src": [64,80], "f": 0, "t": 104, "d": [9,54] }, 220 | { "px": [112,48], "src": [80,80], "f": 0, "t": 105, "d": [9,54] }, 221 | { "px": [128,48], "src": [64,80], "f": 0, "t": 104, "d": [9,56] }, 222 | { "px": [144,48], "src": [80,80], "f": 0, "t": 105, "d": [9,56] }, 223 | { "px": [160,48], "src": [64,80], "f": 0, "t": 104, "d": [9,58] }, 224 | { "px": [176,48], "src": [80,80], "f": 0, "t": 105, "d": [9,58] }, 225 | { "px": [64,96], "src": [64,80], "f": 0, "t": 104, "d": [8,100] }, 226 | { "px": [80,96], "src": [80,80], "f": 0, "t": 105, "d": [8,100] }, 227 | { "px": [96,96], "src": [64,80], "f": 0, "t": 104, "d": [8,102] }, 228 | { "px": [112,96], "src": [80,80], "f": 0, "t": 105, "d": [8,102] }, 229 | { "px": [128,96], "src": [64,80], "f": 0, "t": 104, "d": [8,104] }, 230 | { "px": [144,96], "src": [80,80], "f": 0, "t": 105, "d": [8,104] }, 231 | { "px": [160,96], "src": [64,80], "f": 0, "t": 104, "d": [8,106] }, 232 | { "px": [176,96], "src": [80,80], "f": 0, "t": 105, "d": [8,106] } 233 | ], 234 | "seed": 5440332, 235 | "gridTiles": [], 236 | "entityInstances": [] 237 | }, 238 | { 239 | "__identifier": "Tiles", 240 | "__type": "Tiles", 241 | "__cWid": 16, 242 | "__cHei": 10, 243 | "__gridSize": 16, 244 | "__opacity": 1, 245 | "__pxTotalOffsetX": 0, 246 | "__pxTotalOffsetY": 0, 247 | "__tilesetDefUid": 2, 248 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png", 249 | "levelId": 33, 250 | "layerDefUid": 14, 251 | "pxOffsetX": 0, 252 | "pxOffsetY": 0, 253 | "intGrid": [], 254 | "autoLayerTiles": [], 255 | "seed": 5395320, 256 | "gridTiles": [ 257 | { "px": [16,16], "src": [32,0], "f": 0, "t": 2, "d": [17] }, 258 | { "px": [32,16], "src": [48,0], "f": 0, "t": 3, "d": [18] }, 259 | { "px": [208,16], "src": [32,32], "f": 0, "t": 42, "d": [29] }, 260 | { "px": [224,16], "src": [48,32], "f": 0, "t": 43, "d": [30] }, 261 | { "px": [16,32], "src": [32,16], "f": 0, "t": 22, "d": [33] }, 262 | { "px": [32,32], "src": [48,16], "f": 0, "t": 23, "d": [34] }, 263 | { "px": [208,32], "src": [32,48], "f": 0, "t": 62, "d": [45] }, 264 | { "px": [224,32], "src": [48,48], "f": 0, "t": 63, "d": [46] }, 265 | { "px": [16,112], "src": [64,32], "f": 0, "t": 44, "d": [113] }, 266 | { "px": [32,112], "src": [80,32], "f": 0, "t": 45, "d": [114] }, 267 | { "px": [208,112], "src": [96,0], "f": 0, "t": 6, "d": [125] }, 268 | { "px": [224,112], "src": [112,0], "f": 0, "t": 7, "d": [126] }, 269 | { "px": [16,128], "src": [64,48], "f": 0, "t": 64, "d": [129] }, 270 | { "px": [32,128], "src": [80,48], "f": 0, "t": 65, "d": [130] }, 271 | { "px": [208,128], "src": [96,16], "f": 0, "t": 26, "d": [141] }, 272 | { "px": [224,128], "src": [112,16], "f": 0, "t": 27, "d": [142] } 273 | ], 274 | "entityInstances": [] 275 | } 276 | ], 277 | "__neighbours": [ { "levelUid": 36, "dir": "s" }, { "levelUid": 32, "dir": "n" } ] 278 | } -------------------------------------------------------------------------------- /test/test_separate/0003-Level4.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": "0.7.2", 9 | "url": "https://ldtk.io" 10 | }, 11 | "identifier": "Level4", 12 | "uid": 36, 13 | "worldX": 0, 14 | "worldY": 960, 15 | "pxWid": 256, 16 | "pxHei": 256, 17 | "__bgColor": "#373852", 18 | "bgColor": null, 19 | "bgRelPath": "Inca_back2_by_Kronbits.png", 20 | "bgPos": "Contain", 21 | "bgPivotX": 0.5, 22 | "bgPivotY": 0.5, 23 | "__bgPos": null, 24 | "externalRelPath": null, 25 | "layerInstances": [ 26 | { 27 | "__identifier": "IntGrid_8px_grid", 28 | "__type": "IntGrid", 29 | "__cWid": 32, 30 | "__cHei": 32, 31 | "__gridSize": 8, 32 | "__opacity": 1, 33 | "__pxTotalOffsetX": 0, 34 | "__pxTotalOffsetY": 0, 35 | "__tilesetDefUid": null, 36 | "__tilesetRelPath": null, 37 | "levelId": 36, 38 | "layerDefUid": 34, 39 | "pxOffsetX": 0, 40 | "pxOffsetY": 0, 41 | "intGrid": [], 42 | "autoLayerTiles": [], 43 | "seed": 3866698, 44 | "gridTiles": [], 45 | "entityInstances": [] 46 | }, 47 | { 48 | "__identifier": "Entities", 49 | "__type": "Entities", 50 | "__cWid": 16, 51 | "__cHei": 16, 52 | "__gridSize": 16, 53 | "__opacity": 1, 54 | "__pxTotalOffsetX": 0, 55 | "__pxTotalOffsetY": 0, 56 | "__tilesetDefUid": null, 57 | "__tilesetRelPath": null, 58 | "levelId": 36, 59 | "layerDefUid": 13, 60 | "pxOffsetX": 0, 61 | "pxOffsetY": 0, 62 | "intGrid": [], 63 | "autoLayerTiles": [], 64 | "seed": 3655473, 65 | "gridTiles": [], 66 | "entityInstances": [{ "__identifier": "Labels", "__grid": [8,1], "__pivot": [0.5,0.5], "__tile": null, "defUid": 10, "px": [129,24], "fieldInstances": [ 67 | { 68 | "__identifier": "text", 69 | "__value": "Level background image", 70 | "__type": "String", 71 | "defUid": 11, 72 | "realEditorValues": [{ 73 | "id": "V_String", 74 | "params": ["Level background image"] 75 | }] 76 | }, 77 | { "__identifier": "color", "__value": "#7F95AB", "__type": "Color", "defUid": 12, "realEditorValues": [] } 78 | ] }] 79 | }, 80 | { 81 | "__identifier": "PureAutoLayer", 82 | "__type": "AutoLayer", 83 | "__cWid": 16, 84 | "__cHei": 16, 85 | "__gridSize": 16, 86 | "__opacity": 1, 87 | "__pxTotalOffsetX": 0, 88 | "__pxTotalOffsetY": 0, 89 | "__tilesetDefUid": 2, 90 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png", 91 | "levelId": 36, 92 | "layerDefUid": 26, 93 | "pxOffsetX": 0, 94 | "pxOffsetY": 0, 95 | "intGrid": [], 96 | "autoLayerTiles": [], 97 | "seed": 5193927, 98 | "gridTiles": [], 99 | "entityInstances": [] 100 | }, 101 | { 102 | "__identifier": "IntGrid_classic", 103 | "__type": "IntGrid", 104 | "__cWid": 16, 105 | "__cHei": 16, 106 | "__gridSize": 16, 107 | "__opacity": 1, 108 | "__pxTotalOffsetX": 0, 109 | "__pxTotalOffsetY": 0, 110 | "__tilesetDefUid": null, 111 | "__tilesetRelPath": null, 112 | "levelId": 36, 113 | "layerDefUid": 1, 114 | "pxOffsetX": 0, 115 | "pxOffsetY": 0, 116 | "intGrid": [], 117 | "autoLayerTiles": [], 118 | "seed": 6618746, 119 | "gridTiles": [], 120 | "entityInstances": [] 121 | }, 122 | { 123 | "__identifier": "IntGrid_with_rules", 124 | "__type": "IntGrid", 125 | "__cWid": 16, 126 | "__cHei": 16, 127 | "__gridSize": 16, 128 | "__opacity": 1, 129 | "__pxTotalOffsetX": 0, 130 | "__pxTotalOffsetY": 0, 131 | "__tilesetDefUid": 2, 132 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png", 133 | "levelId": 36, 134 | "layerDefUid": 3, 135 | "pxOffsetX": 0, 136 | "pxOffsetY": 0, 137 | "intGrid": [], 138 | "autoLayerTiles": [], 139 | "seed": 7313278, 140 | "gridTiles": [], 141 | "entityInstances": [] 142 | }, 143 | { 144 | "__identifier": "Tiles", 145 | "__type": "Tiles", 146 | "__cWid": 16, 147 | "__cHei": 16, 148 | "__gridSize": 16, 149 | "__opacity": 1, 150 | "__pxTotalOffsetX": 0, 151 | "__pxTotalOffsetY": 0, 152 | "__tilesetDefUid": 2, 153 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png", 154 | "levelId": 36, 155 | "layerDefUid": 14, 156 | "pxOffsetX": 0, 157 | "pxOffsetY": 0, 158 | "intGrid": [], 159 | "autoLayerTiles": [], 160 | "seed": 4655507, 161 | "gridTiles": [], 162 | "entityInstances": [] 163 | } 164 | ], 165 | "__neighbours": [{ "levelUid": 33, "dir": "n" }] 166 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 4 | "module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 5 | "lib": ["ES2017", "ES7", "ES6", "DOM"], 6 | "declaration": true, 7 | "declarationDir": "./dist", 8 | "outDir": "./dist" /* Redirect output structure to the directory. */, 9 | "strict": true /* Enable all strict type-checking options. */, 10 | "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, 11 | "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, 12 | "baseUrl": "./src" /* Base directory to resolve non-absolute module names. */, 13 | //"types": [], 14 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 15 | "moduleResolution": "node", 16 | "downlevelIteration": true, 17 | }, 18 | "include": ["src"], 19 | "exclude": ["node_modules"] 20 | } 21 | --------------------------------------------------------------------------------