├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── detiled.js
├── detiled
├── detiled.lua
└── detiled_init_image.script
├── detiled_exporter
├── constants.json
├── helper.js
├── icons
│ └── entity.png
├── libs
│ └── xml_parser.js
├── scripts
│ ├── export_tiled.js
│ ├── generate_tilesets.js
│ ├── process_maps.js
│ ├── process_tilesets.js
│ └── templates
│ │ ├── collection.template
│ │ ├── collection_factory_node.template
│ │ ├── collection_go.template
│ │ ├── factory_node.template
│ │ ├── tileset_xml.template
│ │ ├── tileset_xml_item.template
│ │ ├── tileset_xml_item_property.template
│ │ ├── tileset_xml_tileitem.template
│ │ └── tileset_xml_tilesource.template
└── settings.json
├── example
├── assets
│ └── dungeon
│ │ ├── dungeon_atlas.atlas
│ │ ├── objects
│ │ ├── fire
│ │ │ ├── fire.go
│ │ │ └── images
│ │ │ │ └── fire.png
│ │ ├── player
│ │ │ ├── images
│ │ │ │ ├── new_icon.png
│ │ │ │ ├── tile_0096.png
│ │ │ │ ├── tile_0097.png
│ │ │ │ ├── tile_0098.png
│ │ │ │ ├── tile_0099.png
│ │ │ │ └── tile_0100.png
│ │ │ ├── player.collection
│ │ │ └── player.script
│ │ ├── water
│ │ │ └── water.go
│ │ └── weapon
│ │ │ ├── images
│ │ │ ├── tile_0103.png
│ │ │ ├── tile_0104.png
│ │ │ ├── tile_0105.png
│ │ │ ├── tile_0106.png
│ │ │ ├── tile_0107.png
│ │ │ ├── tile_0117.png
│ │ │ ├── tile_0118.png
│ │ │ ├── tile_0119.png
│ │ │ ├── tile_0125.png
│ │ │ ├── tile_0126.png
│ │ │ ├── tile_0127.png
│ │ │ ├── tile_0128.png
│ │ │ ├── tile_0129.png
│ │ │ ├── tile_0130.png
│ │ │ └── tile_0131.png
│ │ │ ├── weapon.go
│ │ │ └── weapon.script
│ │ └── tileset
│ │ └── dungeon
│ │ ├── dungeon.tilesource
│ │ └── dungeon_tilemap.png
├── example.collection
└── generated
│ ├── json_maps
│ └── dungeon_01.json
│ ├── mapping.json
│ ├── maps
│ └── dungeon_01
│ │ ├── dungeon_01-Group 1-dungeon.tilemap
│ │ ├── dungeon_01-dungeon.tilemap
│ │ ├── dungeon_01.collection
│ │ ├── dungeon_01_object_layer_1.collection
│ │ └── spawner_dungeon_01.collection
│ └── spawners
│ └── spawner_assets-dungeon-objects.go
├── example_tiled_export
├── images
│ ├── assets-dungeon-objects
│ │ ├── assets-dungeon-objects-fire-fire.png
│ │ ├── assets-dungeon-objects-player-new_icon.png
│ │ ├── assets-dungeon-objects-player-tile_0096.png
│ │ ├── assets-dungeon-objects-player-tile_0097.png
│ │ ├── assets-dungeon-objects-player-tile_0098.png
│ │ ├── assets-dungeon-objects-player-tile_0099.png
│ │ ├── assets-dungeon-objects-player-tile_0100.png
│ │ ├── assets-dungeon-objects-water-water.png
│ │ ├── assets-dungeon-objects-weapon-tile_0103.png
│ │ ├── assets-dungeon-objects-weapon-tile_0104.png
│ │ ├── assets-dungeon-objects-weapon-tile_0105.png
│ │ ├── assets-dungeon-objects-weapon-tile_0106.png
│ │ ├── assets-dungeon-objects-weapon-tile_0107.png
│ │ ├── assets-dungeon-objects-weapon-tile_0117.png
│ │ ├── assets-dungeon-objects-weapon-tile_0118.png
│ │ ├── assets-dungeon-objects-weapon-tile_0119.png
│ │ ├── assets-dungeon-objects-weapon-tile_0125.png
│ │ ├── assets-dungeon-objects-weapon-tile_0126.png
│ │ ├── assets-dungeon-objects-weapon-tile_0127.png
│ │ ├── assets-dungeon-objects-weapon-tile_0128.png
│ │ ├── assets-dungeon-objects-weapon-tile_0129.png
│ │ ├── assets-dungeon-objects-weapon-tile_0130.png
│ │ └── assets-dungeon-objects-weapon-tile_0131.png
│ └── assets-dungeon-tileset
│ │ └── dungeon_tilemap.png
└── tilesets
│ ├── assets-dungeon-objects.tsx
│ └── assets-dungeon-tileset-dungeon.tsx
├── export_from_tiled.sh
├── export_to_tiled.sh
├── game.project
├── input
└── game.input_binding
├── media
├── detiled_logo.png
└── detiled_thumb.png
├── notes.md
├── package-lock.json
├── package.json
└── tiled_example_maps
├── dungeon_01.tiled-project
└── dungeon_01.tmx
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Defold Protocol Buffer Text Files (https://github.com/github/linguist/issues/5091)
2 | *.animationset linguist-language=JSON5
3 | *.atlas linguist-language=JSON5
4 | *.camera linguist-language=JSON5
5 | *.collection linguist-language=JSON5
6 | *.collectionfactory linguist-language=JSON5
7 | *.collectionproxy linguist-language=JSON5
8 | *.collisionobject linguist-language=JSON5
9 | *.cubemap linguist-language=JSON5
10 | *.display_profiles linguist-language=JSON5
11 | *.factory linguist-language=JSON5
12 | *.font linguist-language=JSON5
13 | *.gamepads linguist-language=JSON5
14 | *.go linguist-language=JSON5
15 | *.gui linguist-language=JSON5
16 | *.input_binding linguist-language=JSON5
17 | *.label linguist-language=JSON5
18 | *.material linguist-language=JSON5
19 | *.mesh linguist-language=JSON5
20 | *.model linguist-language=JSON5
21 | *.particlefx linguist-language=JSON5
22 | *.render linguist-language=JSON5
23 | *.sound linguist-language=JSON5
24 | *.sprite linguist-language=JSON5
25 | *.spinemodel linguist-language=JSON5
26 | *.spinescene linguist-language=JSON5
27 | *.texture_profiles linguist-language=JSON5
28 | *.tilemap linguist-language=JSON5
29 | *.tilesource linguist-language=JSON5
30 |
31 | # Defold JSON Files
32 | *.buffer linguist-language=JSON
33 |
34 | # Defold GLSL Shaders
35 | *.fp linguist-language=GLSL
36 | *.vp linguist-language=GLSL
37 |
38 | # Defold Lua Files
39 | *.editor_script linguist-language=Lua
40 | *.render_script linguist-language=Lua
41 | *.script linguist-language=Lua
42 | *.gui_script linguist-language=Lua
43 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: insality # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: insality # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 | /.internal
63 | /build
64 | deployer_version_settings.txt
65 |
66 | .deployer_cache
67 | *.code-workspace
68 | *.tiled-session
69 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 | /.internal
63 | /build
64 | deployer_version_settings.txt
65 |
66 | .deployer_cache
67 | *.code-workspace
68 | *.tiled-session
69 |
70 | example/*
71 | example_tiled_export/*
72 | detiled/*
73 | export_from_tiled.sh
74 | export_to_tiled.sh
75 | game.project
76 | tiled_example_maps/*
77 | input/*
78 | media/*
79 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Maxim Tuprikov
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 |
2 | [](https://insality.github.io/detiled/)
3 | [](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
4 |
5 | [](https://www.npmjs.com/package/detiled)
6 |
7 | **Detiled** - the set of tools to make work with [**Defold**](https://defold.com/) and [**Tiled**](https://www.mapeditor.org/) easier. **Detiled** have designed workflow how to generate **Tiled** tilemaps and tools for generate **Defold** assets from **Tiled** maps.
8 |
9 |
10 | ## Features
11 |
12 | - Generate standalone **Tiled** tilesets from **Defold** assets folder
13 | - Generate collection files with gameobjects, collections and tilemaps from created **Tiled** maps
14 | - Generate **Defold** factory and collectionfactory for all tilesets used in generation. This is allow you create DLC folder assets for liveupdate for example
15 | - Generate *mapping file* - list of all usable entities with a lot of additional info (size, properties, urls and other)
16 | - **Defold** script properties is supported - you can adjust it in **Tiled** for each object
17 | - Generate objects into **Defold** collections directly, without any code to spawn it *(can be disabled via layer property)*
18 | - **Tiled** layer groups are supported
19 | - Several images for single asset to generate different **Tiled** tileset objects for easier game objects customization
20 |
21 |
22 | ## Setup
23 |
24 | ### Node Module
25 |
26 | To install **[detiled](https://www.npmjs.com/package/detiled)** use [`npm`](https://docs.npmjs.com/).
27 |
28 | ```bash
29 | npm install -g detiled
30 | ```
31 |
32 | For update **detiled** you can use
33 |
34 | ```bash
35 | npm update -g detiled
36 | ```
37 |
38 | ### Defold Dependency
39 |
40 | *Currently in development. For basic workflow it's not required*
41 |
42 |
43 | ## Usage
44 |
45 | ### Tiled path
46 |
47 | You should point the Tiled location in `TILED` environment field. By default it uses `/Applications/Tiled.app/Contents/MacOS/Tiled` location
48 |
49 | ### Generate Tiled tilesets *(tsx files)*
50 |
51 | Export assets from Defold asset folder to Tiled's tilesets
52 | ```
53 | detiled generate_tilesets [defold_assets_folder_path] [output_folder_path]
54 | ```
55 |
56 | - `defold_assets_folder_path` - is a root folder of your game assets. What is asset in **Detiled** described below
57 | - `output_folder_path` - the output folder for your generated tilesets. It should contains tilesets from previous generation, since **Detiled** can parse it to keep already generated asset indexes. Output folder will contain `.tsx` files and images for this tilesets. This tilesets can be shared with any member of your team to create game maps for example
58 |
59 | ### Generate Defold stuff
60 |
61 | Generate Defold collections and other assets from Tiled's maps and tilesets
62 | ```
63 | detiled export [tilesets_folder_path] [maps_folder_path] [output_folder_path]
64 | ```
65 | - `tilesets_folder_path` - is a folder with created tilesets in `generate tiled tilesets` step. This folder should contains `tilesets` folder with generated tileset files
66 | - `maps_folder_path`- is a folder with created `.tmx` maps files from Tiled. For each map will be generated `collection` file with all required stuff. For each map will be included factories with all tilesets that this map using
67 | - `output_folder_path` - is folder with all generated Defold stuff. This map is should be not edited due it can be cleaned at export step
68 |
69 | ### Mapping
70 |
71 | At export step with `detiled export` will generate the `mapping.json` at `output_folder_path`. This file contains all info from all tilesets, included properties, asset info and all other useful stuff you can use in the game.
72 | Example of mapping of single asset:
73 | ```js
74 | "some_tileset_name": { // Records for every processed tileset
75 | "20": { // Id of object from Tiled map inside tileset
76 | "object_name": "weapon", // The go name
77 | "is_collection": false, // Flag if this is collection or not
78 | "image_name": "tile_0131", // The image assigned to this object
79 | "image_url": "#sprite", // The anchor image url from go/collection
80 | "anchor": {
81 | "x": 0,
82 | "y": 8
83 | }, // Offset from object position to center of anchor image
84 | "width": 16, // Anchor image width
85 | "height": 16, // Anchor image height
86 | "go_path": "/example/assets/dungeon/objects/weapon/weapon.go", // File path in game assets
87 | "properties": {
88 | "__default_image_name": "tile_0126", // The default image in Defold assets of anchor image
89 | "weapon:detiled_init_image:detiled_image_url": "#sprite", // Autofill property for script property of generated asset. The same as image_url
90 | "weapon:detiled_init_image:detiled_init_image": "tile_0131", // Autofill property for script property of generated asset. The same as image_name
91 | "weapon:weapon_script:power": 20 // Default script property value
92 | }
93 | }
94 | }
95 | ```
96 |
97 |
98 | ## Generate Tiled tilesets flow
99 |
100 | To generate tilesets you should pass the assets folder. The assets folder is a folder with your game assets.
101 |
102 | The every object should be placed inside folder with the same name as this folder.
103 | Assets can be **(in priority order)**:
104 | - the `{name}.collection` object inside `{name}` folder
105 | - the `{name}.go` object inside `{name}` folder
106 | - the `{name}.tilesource` object inside `{name}` folder
107 |
108 | if asset is not found inside folder, the script goes recursive inside other folders
109 | The tileset name is generated with names of all folders before. For example if your assets placed in `assets->dungeon->objects` the tileset will have the name `assets-dungeon-objects.tsx`
110 |
111 | Every asset can have images for **Tiled** items. This images should be placed inside `images` folder in asset folder. For every image in this folder will be generated object for Tiled tileset. If no images was found, will be used the placeholder image.
112 |
113 | To place correctly the objects from **Tiled** to **Defold**, the exported will inspect the `*.collection` or `*.go` file to find the anchor image and his position.
114 |
115 | Anchor image will be used to gather offset for game object position generation, also this anchor image can be adjusted with relative image of Tiled object for every object inside `images` folder. See `autofill properties` and `anchor image` to get more info.
116 |
117 | If you remove or rename asset, it will be removed from tilesets on next tilesets generation. The tileset item ID of removed asset will be never use again (if you generate over existing tilesets).
118 |
119 | You can change the images and add new objects (or images for existing object) without any risks.
120 |
121 | Due the override issues, keep the `tsx` and `tmx` files under version control.
122 |
123 | All properties inside asset will be proposed to Tiled object properties. So you able to override it inside Tiled object properties on map editing. It's very useful to custom the properties of single object *(health of enemy, amount of gold or unique ID to get different data from you game database)*.
124 |
125 | You can scale objects and rotate them, this is supported by **Detiled**.
126 |
127 |
128 | ## Generate Defold assets flow
129 |
130 | To generate **Defold** assets, you should point the previous generated tilesets folder, the folder with created `tmx` **Tiled** maps and folder, where generated assets should be placed. The generated folder will be erased before generate, so don't modify it or don't place any handmade assets.
131 |
132 | To use generated map (it will be collection name with name of the map), include this collection inside your game collection.
133 |
134 | For every tilesets will be generated `spawners` - the game object with all required factories or collectionfactories for this tileset.
135 |
136 | Every generated map will include all required spawners to able spawn all entities inside *(if you want to spawn in manually)*.
137 |
138 | Since **Tiled** tilemap export is not perfect, I recommend you to re-save project in **Defold** after the export step to remove all unintended changes inside your VSC
139 |
140 | ### Properties
141 | - `no_export` - set to true to skip export of this object layer. Useful if you want create objects of this layer by yourself.
142 | - `z` - set value to adjust the z position of generated object layer
143 |
144 |
145 | ## Glossary
146 | - `Anchor image` - the image from asset, which exported thinks as main image. It find it as game object with sprite component. If sprite component or game object inside collection have the asset name, it will have more priority, than others. Otherwise the sprite with name `#sprite` have more priority than other sprite components
147 | - `Autofill properties` - the `detiled` properties, that can be set automatically on export. It have name `detiled_*`. For example `detiled_init_image` will be setup for all scripts of assets if will be found. You can use `detiled_init_image.script` to setup the image of asset on creating *(since **Defold** is not allow to override go or collection sprite properties directly)*
148 | - `Image anchor` - offset from anchor image to center of game object (or collection). It used to place perfectly objects from **Tiled** to **Defold** on export
149 |
150 |
151 | ## License
152 |
153 | - Developed and supported by [Insality](https://github.com/Insality)
154 |
155 |
156 | ## Issues and suggestions
157 |
158 | If you have any issues, questions or suggestions please [create an issue](https://github.com/Insality/defold-parser/issues) or contact me: [insality@gmail.com](mailto:insality@gmail.com)
159 |
160 |
161 | ## ❤️ Support project ❤️
162 |
163 | Please support me if you like this project! It will help me keep engaged to update **Detiled** and make it even better!
164 |
165 | [](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
166 |
167 |
--------------------------------------------------------------------------------
/detiled.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | //
3 | // ___ ___ ___ ___ ___ ___
4 | // /\ \ /\ \ /\ \ ___ /\__\ /\ \ /\ \
5 | // /::\ \ /::\ \ \:\ \ /\ \ /:/ / /::\ \ /::\ \
6 | // /:/\:\ \ /:/\:\ \ \:\ \ \:\ \ /:/ / /:/\:\ \ /:/\:\ \
7 | // /:/ \:\__\ /::\~\:\ \ /::\ \ /::\__\ /:/ / /::\~\:\ \ /:/ \:\__\
8 | // /:/__/ \:|__| /:/\:\ \:\__\ /:/\:\__\ __/:/\/__/ /:/__/ /:/\:\ \:\__\ /:/__/ \:|__|
9 | // \:\ \ /:/ / \:\~\:\ \/__/ /:/ \/__/ /\/:/ / \:\ \ \:\~\:\ \/__/ \:\ \ /:/ /
10 | // \:\ /:/ / \:\ \:\__\ /:/ / \::/__/ \:\ \ \:\ \:\__\ \:\ /:/ /
11 | // \:\/:/ / \:\ \/__/ \/__/ \:\__\ \:\ \ \:\ \/__/ \:\/:/ /
12 | // \::/__/ \:\__\ \/__/ \:\__\ \:\__\ \::/__/
13 | // ~~ \/__/ \/__/ \/__/ ~~
14 | //
15 |
16 | const fs = require("fs");
17 | const path = require("path");
18 | const tilesets_generator = require("./detiled_exporter/scripts/generate_tilesets");
19 | const export_tiled = require("./detiled_exporter/scripts/export_tiled");
20 |
21 | let COMMANDS = {
22 | "help": help,
23 | "generate_tilesets": tilesets_generator.start,
24 | "export": export_tiled.start,
25 | }
26 |
27 |
28 | function help() {
29 | console.log(`
30 | _|_|_| _|_|_|_|_| _| _| _|
31 | _| _| _|_| _| _| _|_| _|_|_|
32 | _| _| _|_|_|_| _|_|_|_|_| _| _| _| _|_|_|_| _| _|
33 | _| _| _| _| _| _| _| _| _|
34 | _|_|_| _|_|_| _| _| _| _|_|_| _|_|_|
35 |
36 |
37 | Hi! The Detiled exporter available commands:
38 |
39 |
40 | detiled generate_tilesets [defold_assets_folder_path] [output_folder_path]
41 | -- Export assets from Defold asset folder to Tiled's tilesets
42 |
43 |
44 | detiled export [tilesets_folder_path] [maps_folder_path] [output_folder_path]
45 | -- Generate Defold collections and other assets from Tiled's maps and tilesets
46 | `);
47 | };
48 |
49 |
50 | function start() {
51 | if (!fs.existsSync(path.join(process.cwd(), "game.project"))) {
52 | console.log("Error: you should run Detiled inside the root of game.project");
53 | console.log("Current folder is:", process.cwd());
54 | return;
55 | }
56 |
57 | let args = process.argv;
58 | let command = args[2];
59 | if (command && COMMANDS[command]) {
60 | COMMANDS[command](args[3], args[4], args[5], args[6]);
61 | } else {
62 | help();
63 | }
64 | }
65 |
66 | start()
67 |
--------------------------------------------------------------------------------
/detiled/detiled.lua:
--------------------------------------------------------------------------------
1 | local Detiled = {}
2 |
3 | return Detiled
--------------------------------------------------------------------------------
/detiled/detiled_init_image.script:
--------------------------------------------------------------------------------
1 | go.property("detiled_init_image", hash(""))
2 | go.property("detiled_image_url", msg.url())
3 |
4 | function init(self)
5 | if self.detiled_init_image ~= hash("") then
6 | sprite.play_flipbook(self.detiled_image_url, self.detiled_init_image)
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/detiled_exporter/constants.json:
--------------------------------------------------------------------------------
1 | {
2 | "TILESETS_FOLDER_NAME": "tilesets",
3 | "ASSETS_FOLDER_NAME": "assets",
4 | "ASSETS_IMAGES_FOLDER": "images",
5 | "DEFAULT_IMAGE": "./detiled_exporter/icons/entity.png",
6 | "DEFAULT_IMAGE_SIZE": {"width": 32, "height": 32}
7 | }
8 |
--------------------------------------------------------------------------------
/detiled_exporter/helper.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 |
4 | const M = {}
5 |
6 | const PROPERTY_TYPE_NUMBER = "PROPERTY_TYPE_NUMBER"
7 | const PROPERTY_TYPE_VECTOR3 = "PROPERTY_TYPE_VECTOR3"
8 | const PROPERTY_TYPE_VECTOR4 = "PROPERTY_TYPE_VECTOR4"
9 | const PROPERTY_TYPE_QUAT = "PROPERTY_TYPE_QUAT"
10 | const PROPERTY_TYPE_URL = "PROPERTY_TYPE_URL"
11 | const PROPERTY_TYPE_HASH = "PROPERTY_TYPE_HASH"
12 | const PROPERTY_TYPE_BOOLEAN = "PROPERTY_TYPE_BOOLEAN"
13 |
14 | const MAP_PROPERTY_TYPE = {
15 | PROPERTY_TYPE_BOOLEAN: 'type="bool"',
16 | PROPERTY_TYPE_NUMBER: 'type="float"',
17 | }
18 |
19 |
20 | M.log = function() {
21 | var args = Array.prototype.slice.call(arguments);
22 | args.unshift("[Detiled]: ");
23 | console.log.apply(console, args);
24 | };
25 |
26 |
27 | M.contains_count = function(string, substring) {
28 | return string.split(substring).length - 1;
29 | };
30 |
31 |
32 | function parse_vector(vector) {
33 | let values = []
34 | vector.split(",").forEach(function(value) {
35 | let new_value = value.trim()
36 | if (new_value.length == 0) {
37 | new_value = "0"
38 | }
39 | if (!new_value.includes(".")) {
40 | new_value = new_value + ".0"
41 | }
42 | values.push(new_value)
43 | })
44 |
45 | return values.join(", ")
46 | }
47 |
48 |
49 | function get_content_in_bracers(line) {
50 | let regex = /\((.*?)\)/g
51 | while ((m = regex.exec(line)) !== null) {
52 | // This is necessary to avoid infinite loops with zero-width matches
53 | if (m.index === regex.lastIndex) {
54 | regex.lastIndex++;
55 | }
56 |
57 | let value = m[1].trim()
58 |
59 | if ((value.charAt(0) === '"' && value.charAt(value.length -1) === '"') ||
60 | (value.charAt(0) === "'" && value.charAt(value.length -1) === "'")) {
61 | value = value.substr(1, value.length -2);
62 | }
63 |
64 | return value
65 | }
66 | return ""
67 | }
68 |
69 |
70 | M.script_to_defold_property = function(key, value) {
71 | key = key.trim()
72 | value = value.trim()
73 |
74 | let type = PROPERTY_TYPE_NUMBER
75 | if (value.startsWith("hash")) {
76 | value = get_content_in_bracers(value)
77 | type = PROPERTY_TYPE_HASH
78 | }
79 | if (value.startsWith("msg.url")) {
80 | value = get_content_in_bracers(value)
81 | type = PROPERTY_TYPE_URL
82 | }
83 | if (value.startsWith("vmath.vector3")) {
84 | value = get_content_in_bracers(value)
85 | value = parse_vector(value)
86 | type = PROPERTY_TYPE_VECTOR3
87 | }
88 | if (value.startsWith("vmath.vector4")) {
89 | value = get_content_in_bracers(value)
90 | value = parse_vector(value)
91 | type = PROPERTY_TYPE_VECTOR4
92 | }
93 | if (value.startsWith("vmath.quat")) {
94 | value = get_content_in_bracers(value)
95 | value = "quat " + parse_vector(value)
96 | type = PROPERTY_TYPE_QUAT
97 | }
98 | if (value.startsWith("resource.")) {
99 | value = get_content_in_bracers(value)
100 | type = PROPERTY_TYPE_HASH
101 | }
102 | if (value == "true" || value == "false") {
103 | value = (value == "true") && true || false
104 | type = PROPERTY_TYPE_BOOLEAN
105 | }
106 |
107 | return {
108 | key: key,
109 | value: value,
110 | type: type
111 | }
112 | }
113 |
114 | M.defold_to_tiled_property_value = function(key, value, type) {
115 | if (type == PROPERTY_TYPE_NUMBER) {
116 | value = parseFloat(value)
117 | }
118 | if (type == PROPERTY_TYPE_BOOLEAN) {
119 | value = (value == "true") && true || false
120 | }
121 | if (type == PROPERTY_TYPE_QUAT) {
122 | value = "quat " + value
123 | }
124 |
125 | return {
126 | key: key,
127 | value: value,
128 | type: type
129 | }
130 | }
131 |
132 |
133 | M.defold_to_tiled_property_xml_type = function(type) {
134 | return MAP_PROPERTY_TYPE[type] || ""
135 | }
136 |
137 |
138 | M.tiled_to_defold_property = function(key, value, type) {
139 | let defold_type = PROPERTY_TYPE_NUMBER
140 |
141 | if (type == "string") {
142 | defold_type = PROPERTY_TYPE_HASH
143 | let sep_count = M.contains_count(value, ", ")
144 | if (value.startsWith("quat ")) {
145 | value = value.replace("quat ", "")
146 | defold_type = PROPERTY_TYPE_QUAT
147 | } else {
148 | if (sep_count == 2) {
149 | defold_type = PROPERTY_TYPE_VECTOR3
150 | }
151 | if (sep_count == 3) {
152 | defold_type = PROPERTY_TYPE_VECTOR4
153 | }
154 | }
155 | }
156 |
157 | if (type == "bool") {
158 | value = value && "true" || "false"
159 | defold_type = PROPERTY_TYPE_BOOLEAN
160 | }
161 |
162 | if (type == "float") {
163 | defold_type = PROPERTY_TYPE_NUMBER
164 | value = "" + value
165 | }
166 |
167 | return {
168 | key: key,
169 | value: value,
170 | type: defold_type
171 | }
172 | }
173 |
174 |
175 | // @param target_path string
176 | // @param extname string|nil
177 | M.get_files_from = function(target_path, extname) {
178 | if (!fs.existsSync(target_path)) {
179 | return [];
180 | }
181 |
182 | let files_name = fs.readdirSync(target_path);
183 | if (extname) {
184 | files_name = files_name.filter(name => name.endsWith("." + extname));
185 | }
186 | files_name = files_name.map(name => path.join(target_path, name))
187 |
188 | return files_name;
189 | };
190 |
191 |
192 | M.get_assets_item_data = function(image_path, asset_name, properties, size, anchor, go_path, default_image, image_url, is_collection) {
193 | return {
194 | image_path: image_path,
195 | image_name: image_path && path.basename(image_path, ".png"),
196 | item: asset_name,
197 | is_collection: is_collection,
198 | properties: JSON.parse(JSON.stringify(properties)),
199 | width: size.width,
200 | height: size.height,
201 | anchor_x: anchor.x + size.width/2,
202 | anchor_y: anchor.y + size.height/2,
203 | go_path: "/" + path.relative(process.cwd(), go_path),
204 | default_image: default_image,
205 | image_url: image_url,
206 | }
207 | }
208 |
209 |
210 | M.is_export_collection = function(map_data) {
211 | return !M.get_property(map_data.properties, "no_export", false)
212 | }
213 |
214 |
215 | M.get_property = function(properties, key, default_value) {
216 | properties = properties || [];
217 | for (let i in properties) {
218 | if (properties[i].name === key) {
219 | return properties[i].value
220 | }
221 | }
222 |
223 | return default_value
224 | }
225 |
226 |
227 | module.exports = M
228 |
--------------------------------------------------------------------------------
/detiled_exporter/icons/entity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/detiled_exporter/icons/entity.png
--------------------------------------------------------------------------------
/detiled_exporter/libs/xml_parser.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const { XMLParser } = require("fast-xml-parser");
3 |
4 | const xml_parse_options = {
5 | ignoreAttributes: false,
6 | attributeNamePrefix : "@_",
7 | allowBooleanAttributes: true
8 | };
9 |
10 | const M = {}
11 |
12 | M.parse = function(xml_path) {
13 | let tileset_data = fs.readFileSync(xml_path).toString('utf8');
14 | let parser = new XMLParser(xml_parse_options);
15 | return parser.parse(tileset_data);
16 | };
17 |
18 |
19 | M.get_tile_by_id = function(xml_path, id) {
20 | let parsed = this.parse(xml_path);
21 | for (let i in parsed.tileset.tile) {
22 | let tile = parsed.tileset.tile[i];
23 | if (tile["@_id"] == id) {
24 | return tile;
25 | }
26 | }
27 | return null;
28 | };
29 |
30 | module.exports = M
31 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/export_tiled.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const os = require("os");
3 | const path = require("path");
4 | const rimraf = require("rimraf");
5 | const process = require("process");
6 | const helper = require("../helper");
7 | const Quaternion = require('quaternion');
8 | const constants = require("../constants");
9 | const { execSync } = require('child_process');
10 | const defold_parser = require("defold-parser");
11 |
12 | const tilesets = require("./process_tilesets")
13 | const maps = require("./process_maps")
14 |
15 | const COLLECTION_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/collection.template")).toString('utf8')
16 |
17 | let TILED_PATH = process.env.TILED || "/Applications/Tiled.app/Contents/MacOS/Tiled"
18 |
19 |
20 | function process_tileset(data, output_path, mapping) {
21 | tilesets.generate_factories(data, output_path, mapping)
22 | }
23 |
24 |
25 | function get_object_info(map_data, object) {
26 | let tilesets = map_data.tilesets
27 |
28 | let info = {
29 | name: "",
30 | object_id: "0",
31 | }
32 | for (let i in tilesets) {
33 | if (object.gid >= tilesets[i].firstgid) {
34 | info.name = tilesets[i].name
35 | info.object_id = (object.gid - tilesets[i].firstgid)
36 | }
37 | }
38 |
39 | return info
40 | }
41 |
42 |
43 | function autofill_detiled_properties(object, mapping_info) {
44 | if (!mapping_info.properties) {
45 | return
46 | }
47 |
48 | for (key in mapping_info.properties) {
49 | let property_path = key.split(":")
50 | if (property_path[2] == "detiled_init_image") {
51 | object.properties = object.properties || []
52 | object.properties.push({
53 | name: key,
54 | type: "string",
55 | value: mapping_info.image_name
56 | })
57 | }
58 | if (property_path[2] == "detiled_image_url") {
59 | object.properties = object.properties || []
60 | object.properties.push({
61 | name: key,
62 | type: "string",
63 | value: mapping_info.image_url
64 | })
65 | }
66 | }
67 | }
68 |
69 |
70 | function get_properties_for_collection(object, mapping_info) {
71 | let properties_by_go = {}
72 | let result = []
73 |
74 | autofill_detiled_properties(object, mapping_info)
75 |
76 | if (object.properties) {
77 | for (let index in object.properties) {
78 | let property = object.properties[index]
79 | let property_info = helper.tiled_to_defold_property(property.name, property.value, property.type)
80 | let property_path = property_info.key.split(":")
81 | properties_by_go[property_path[0]] = properties_by_go[property_path[0]] || []
82 | properties_by_go[property_path[0]].push({
83 | id: [ property_path[1] ],
84 | properties: [{
85 | id: [ property_path[2] ],
86 | value: [ property_info.value ],
87 | type: [ property_info.type ]
88 | }]
89 | })
90 | }
91 | }
92 |
93 | for (let key in properties_by_go) {
94 | result.push({
95 | id: [ key ],
96 | properties: properties_by_go[key]
97 | })
98 | }
99 |
100 | return result
101 | }
102 |
103 |
104 | function get_properties_for_object(object, mapping_info) {
105 | let result = []
106 |
107 | autofill_detiled_properties(object, mapping_info)
108 |
109 | if (object.properties) {
110 | for (let index in object.properties) {
111 | let property = object.properties[index]
112 | let property_info = helper.tiled_to_defold_property(property.name, property.value, property.type)
113 | let property_path = property_info.key.split(":")
114 | result.push({
115 | id: [ property_path[1] ],
116 | properties: [{
117 | id: [ property_path[2] ],
118 | value: [ property_info.value ],
119 | type: [ property_info.type ]
120 | }]
121 | })
122 | }
123 | }
124 |
125 | return result
126 | }
127 |
128 |
129 | function process_map(map_path, data, output_path, mapping) {
130 | let name = path.basename(map_path, ".json")
131 | console.log("Process map", name)
132 | maps.generate_spawners(name, data, output_path)
133 |
134 | // Add tilesource name to the map
135 | for (let i in data.tilesets) {
136 | let d = data.tilesets[i]
137 | d.name = path.basename(d.source, ".tsx")
138 | }
139 |
140 | let map_name_collection = name + ".collection"
141 | let map_folder = path.join(output_path, "maps", name)
142 | let map_collection_path = path.join(map_folder, map_name_collection)
143 |
144 | let is_export_collection = helper.is_export_collection(data)
145 | if (is_export_collection) {
146 | let collection_path = path.join(map_collection_path)
147 | let collection_parsed = defold_parser.load_from_file(collection_path)
148 |
149 | // Add objects
150 | let tilelayer_counter = 0
151 | for (let index in data.layers) {
152 | let layer = data.layers[index]
153 | if (layer.type == "tilelayer") {
154 | tilelayer_counter += 1
155 | }
156 | if (layer.type == "objectgroup") {
157 | let is_no_export = helper.get_property(layer.properties, "no_export", false)
158 | if (is_no_export) {
159 | helper.log("Skip export of layer " + layer.name + " due property no_export")
160 | continue;
161 | }
162 |
163 | // Create collection with this layer
164 | let layer_name = layer.name.replaceAll(" ", "_").toLowerCase()
165 | let collection_layer_name = name + "_" + layer_name
166 | let collection_layer = COLLECTION_TEMPLATE.replace("{1}", collection_layer_name)
167 | let collection_layer_data = defold_parser.decode_object(collection_layer)
168 |
169 | for (o_key in layer.objects) {
170 | let object = layer.objects[o_key]
171 | let object_info = get_object_info(data, object)
172 | let mapping_info = mapping[object_info.name]["" + object_info.object_id]
173 | if (!mapping_info) {
174 | console.log("Error wrong object on layer", object_info, layer.name)
175 | continue
176 | }
177 |
178 | let height = data.height * data.tileheight
179 | let object_name = object.name.length > 0 && object.name || mapping_info.object_name
180 | let object_id = object_name + "_" + object.id
181 |
182 | let rotation = object.rotation * Math.PI/180
183 | let scale_x = object.width / mapping_info.width
184 | let scale_y = object.height / mapping_info.height
185 |
186 | // TODO: This should be in module Grid. Need to Fill hexgrid and isogrid also
187 |
188 | // Get offset from object point in Tiled to Defold assets object
189 | // Tiled point in left bottom, Defold - in object center
190 | // And add sprite anchor.x for visual correct posing from tiled (In Tiled we pos the image)
191 | let offset = {
192 | x: (mapping_info.width/2 + mapping_info.anchor.x) * scale_x,
193 | y: (mapping_info.height/2 - mapping_info.anchor.y) * scale_y,
194 | }
195 | // Rotate offset in case of rotated object
196 | let rotated_offset = {
197 | x: offset.x * Math.cos(rotation) + offset.y * Math.sin(rotation),
198 | y: offset.x * Math.sin(rotation) - offset.y * Math.cos(rotation),
199 | }
200 |
201 | let object_x = object.x + rotated_offset.x
202 | // Height - {} is only if Y coords are inverted (In Tiled it's true)
203 | let object_y = (height - (object.y + rotated_offset.y))
204 |
205 | // Parse radians to Quaternion. In Defold collections GO have vector4 with quat value
206 | let quat_rotation = Quaternion.fromEuler(-rotation, 0, 0).normalize()
207 | if (mapping_info.is_collection) {
208 | let properties = get_properties_for_collection(object, mapping_info)
209 | collection_layer_data.collection_instances = collection_layer_data.collection_instances || []
210 | collection_layer_data.collection_instances.push({
211 | id: [ object_id ],
212 | instance_properties: properties,
213 | collection: [ mapping_info.go_path ],
214 | position: [{ x: [ object_x ], y: [ object_y ], z: [ 0 ] }],
215 | rotation: [{ x: [ quat_rotation.x ], y: [ quat_rotation.y ], z: [ quat_rotation.z ], w: [ quat_rotation.w ] }],
216 | scale3: [{ x: [ scale_x ], y: [ scale_y ], z: [ 1 ] }]
217 | })
218 | } else {
219 | collection_layer_data.instances = collection_layer_data.instances || []
220 | let properties = get_properties_for_object(object, mapping_info)
221 | collection_layer_data.instances.push({
222 | id: [ object_id ],
223 | component_properties: properties,
224 | prototype: [ mapping_info.go_path ],
225 | position: [{ x: [ object_x ], y: [ object_y ], z: [ 0 ] }],
226 | rotation: [{ x: [ quat_rotation.x ], y: [ quat_rotation.y ], z: [ quat_rotation.z ], w: [ quat_rotation.w ] }],
227 | scale3: [{ x: [ scale_x ], y: [ scale_y ], z: [ 1 ] }]
228 | })
229 | }
230 | }
231 |
232 | let layer_collection_path = path.join(map_folder, collection_layer_name + ".collection")
233 | defold_parser.save_to_file(layer_collection_path, collection_layer_data)
234 |
235 | let object_layer_z = helper.get_property(layer.properties, "z", 0.0001 * tilelayer_counter)
236 | // Add layer collection
237 | let layer_object_instance = {
238 | id: [ layer_name ],
239 | collection: [ "/" + path.relative(process.cwd(), layer_collection_path) ],
240 | position: [ { x: [ 0 ], y: [ 0 ], z: [ object_layer_z ] } ],
241 | rotation: [ { x: [ 0 ], y: [ 0 ], z: [ 0 ], w: [ 0 ] } ],
242 | scale3: [ { x: [ 0 ], y: [ 0 ], z: [ 0 ] } ],
243 | }
244 | collection_parsed.collection_instances = collection_parsed.collection_instances || []
245 | collection_parsed.collection_instances.push(layer_object_instance)
246 | }
247 | }
248 |
249 | collection_parsed.name = [ name ]
250 | defold_parser.save_to_file(collection_path, collection_parsed)
251 | }
252 |
253 | fs.mkdirSync(map_folder, { recursive: true })
254 | let map_output_path = path.join(output_path, "json_maps")
255 | fs.mkdirSync(map_output_path, { recursive: true })
256 | fs.writeFileSync(path.join(map_output_path, path.basename(map_path)), JSON.stringify(data))
257 | }
258 |
259 |
260 | function process_json(json_path, output_path, mapping) {
261 | let json_content = JSON.parse(fs.readFileSync(json_path))
262 | let json_type = json_content.type
263 |
264 | if (json_type == "tileset") {
265 | process_tileset(json_content, output_path, mapping)
266 | }
267 | if (json_type == "map") {
268 | process_map(json_path, json_content, output_path, mapping)
269 | }
270 | console.log("")
271 | }
272 |
273 |
274 | function convert_tilesets_to_json(tiled_tilesets_path, temp_tilesets_folder) {
275 | let tilesets = fs.readdirSync(tiled_tilesets_path)
276 | .filter(name => name.endsWith(".tsx"))
277 |
278 | for (let i in tilesets) {
279 | let tileset_name = tilesets[i]
280 | let tileset_path = path.join(tiled_tilesets_path, tileset_name)
281 | let tileset_name_json = path.basename(tileset_name, ".tsx") + ".json"
282 |
283 | let temp_tileset_path = path.join(temp_tilesets_folder, tileset_name_json)
284 | execSync(`${TILED_PATH} --export-tileset "${tileset_path}" "${temp_tileset_path}"`)
285 | }
286 | }
287 |
288 |
289 | function convert_maps_to_json(tiled_maps_path, temp_maps_folder, output_collection_path) {
290 | let maps = fs.readdirSync(tiled_maps_path)
291 | .filter(name => name.endsWith(".tmx"))
292 |
293 | for (let i in maps) {
294 | let map_name = maps[i]
295 | let map_basename = path.basename(map_name, ".tmx")
296 | let map_path = path.join(tiled_maps_path, map_name)
297 | let map_name_json = map_basename + ".json"
298 | let map_name_collection = map_basename + ".collection"
299 |
300 | let temp_map_json_path = path.join(temp_maps_folder, map_name_json)
301 | execSync(`${TILED_PATH} --export-map "${map_path}" "${temp_map_json_path}"`, {stdio: 'inherit'})
302 |
303 | let json_content = JSON.parse(fs.readFileSync(temp_map_json_path))
304 | let is_export_collection = helper.is_export_collection(json_content)
305 |
306 | if (is_export_collection) {
307 | let map_folder = path.join(output_collection_path, map_basename)
308 | let map_collection_path = path.join(map_folder, map_name_collection)
309 | fs.mkdirSync(map_folder, { recursive: true })
310 | execSync(`${TILED_PATH} --export-map "${map_path}" "${map_collection_path}"`, {stdio: 'inherit'})
311 | }
312 | }
313 | }
314 |
315 |
316 | function start_process_dir(tilesets_path, maps_path, output_path) {
317 | rimraf.sync(output_path)
318 | fs.mkdirSync(output_path, { recursive: true })
319 |
320 | let jsons = []
321 |
322 | let temp_tilesets_folder = fs.mkdtempSync(os.tmpdir())
323 | convert_tilesets_to_json(tilesets_path, temp_tilesets_folder)
324 | let tilesets = fs.readdirSync(temp_tilesets_folder)
325 | .filter(name => name.endsWith(".json"))
326 | .map(name => path.join(temp_tilesets_folder, name))
327 |
328 | let temp_maps_folder = fs.mkdtempSync(os.tmpdir())
329 | let map_output_folder = path.join(output_path, "maps")
330 | convert_maps_to_json(maps_path, temp_maps_folder, map_output_folder)
331 | let maps = fs.readdirSync(temp_maps_folder)
332 | .filter(name => name.endsWith(".json"))
333 | .map(name => path.join(temp_maps_folder, name))
334 |
335 | jsons = tilesets.concat(maps)
336 |
337 | console.log("Process next files:", jsons)
338 |
339 | let mapping = {}
340 | for (let i in jsons) {
341 | process_json(jsons[i], output_path, mapping)
342 | }
343 |
344 | let mapping_path = path.join(output_path, "mapping.json")
345 | fs.writeFileSync(mapping_path, JSON.stringify(mapping, null, 4))
346 | console.log("Write", mapping_path)
347 |
348 | fs.rmSync(temp_tilesets_folder, { recursive: true });
349 | fs.rmSync(temp_maps_folder, { recursive: true });
350 | }
351 |
352 |
353 | function start(tilesets_folder_path, maps_folder_path, output_folder_path) {
354 | console.log("Start tiled generator")
355 |
356 | let tilesets_path = path.join(path.resolve(tilesets_folder_path), constants.TILESETS_FOLDER_NAME)
357 | let maps_path = path.resolve(maps_folder_path)
358 | let output_path = path.resolve(output_folder_path)
359 | start_process_dir(tilesets_path, maps_path, output_path)
360 | }
361 |
362 | module.exports.start = start
363 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/generate_tilesets.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const path = require("path")
3 | const rimraf = require("rimraf")
4 | const image_size = require("image-size")
5 | const defold_parser = require("defold-parser")
6 |
7 | const helper = require("../helper")
8 | const constants = require("../constants")
9 | const xml_parser = require("../libs/xml_parser")
10 |
11 | const TILESET_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/tileset_xml.template")).toString('utf8')
12 | const TILESET_ITEM_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/tileset_xml_item.template")).toString('utf8')
13 | const TILESET_ITEM_PROPERTY_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/tileset_xml_item_property.template")).toString('utf8')
14 | const TILESET_ITEM_TILESOURCE = fs.readFileSync(path.join(__dirname, "templates/tileset_xml_tilesource.template")).toString('utf8')
15 | const TILESET_ITEM_TILEITEM = fs.readFileSync(path.join(__dirname, "templates/tileset_xml_tileitem.template")).toString('utf8')
16 |
17 | let items = {}
18 | let tilesources = {}
19 | let tilesets_db = {}
20 |
21 |
22 | // Get the data of current tilesets to prevent override of existing entities
23 | // @param output_path string @The folder with .tsx tilesets to override
24 | function parse_tilesets_db_from_tsx(output_path) {
25 | let tilesets_folder = path.join(output_path, constants.TILESETS_FOLDER_NAME)
26 | let tilesets = helper.get_files_from(tilesets_folder, "tsx")
27 |
28 | for (let i in tilesets) {
29 | let tileset = tilesets[i]
30 | let tileset_name = path.basename(tileset, ".tsx")
31 | let parsed_tsx = xml_parser.parse(tileset)
32 |
33 | let tileset_info = {}
34 | for (let j in parsed_tsx.tileset.tile) {
35 | let tile = parsed_tsx.tileset.tile[j]
36 | tileset_info[tile["@_class"]] = parseInt(tile["@_id"])
37 | }
38 | if (Object.keys(tileset_info).length > 0) {
39 | tilesets_db[tileset_name] = tileset_info
40 | }
41 | }
42 | }
43 |
44 |
45 | function is_folder_contains_named_file(target_path, file_extension) {
46 | let folder_name = path.basename(target_path)
47 | let asset_go_path = path.join(target_path, folder_name + file_extension)
48 | return fs.existsSync(asset_go_path)
49 | }
50 |
51 |
52 | function check_number(original) {
53 | let val = original
54 | if (!isNaN(parseFloat(val))) {
55 | val = val.trim()
56 | if (val.indexOf(".") !== -1) {
57 | val = val.replace(/0+$/, '')
58 | }
59 | if (val == String(parseFloat(val))) {
60 | return parseFloat(val)
61 | }
62 | }
63 |
64 | return original
65 | }
66 |
67 |
68 | function get_properties_from_script(component, component_name, go_id) {
69 | let script_data = fs.readFileSync(path.join(process.cwd(), component)).toString('utf8')
70 | let regex = /go.property\(\s*[\"\'](.*)[\"\']\s*,\s*(.*)\s*\)/g
71 | let properties = {}
72 |
73 | script_data.split("\n").forEach(function(line, index, arr) {
74 | if (line.startsWith("go.property")) {
75 | while ((m = regex.exec(line)) !== null) {
76 | // This is necessary to avoid infinite loops with zero-width matches
77 | if (m.index === regex.lastIndex) {
78 | regex.lastIndex++;
79 | }
80 | if (m[1] && m[2]) {
81 | let property_info = helper.script_to_defold_property(m[1], m[2])
82 | properties[go_id + ":" + component_name + ":" + property_info.key] = {
83 | value: check_number(property_info.value),
84 | type: property_info.type,
85 | }
86 | }
87 | }
88 | }
89 | });
90 |
91 | return properties
92 | }
93 |
94 |
95 | function parse_properties_from_go(go_parsed, go_properties, go_id) {
96 | for (let i in go_parsed.components) {
97 | let elem = go_parsed.components[i]
98 | let component = elem.component[0]
99 | if (component && component.endsWith(".script")) {
100 | let properties = get_properties_from_script(component, elem.id[0], go_id)
101 | for (let prop in properties) {
102 | if (go_properties[prop]) {
103 | helper.log("Error: go property duplicate", go_path, prop)
104 | }
105 | go_properties[prop] = properties[prop]
106 | }
107 | }
108 |
109 | if (elem.properties) {
110 | for (let prop_key in elem.properties) {
111 | let prop = elem.properties[prop_key]
112 | let property_info = helper.defold_to_tiled_property_value(prop.id[0], prop.value[0], prop.type[0])
113 |
114 | go_properties[go_id + ":" + elem.id[0] + ":" + property_info.key] = {
115 | value: property_info.value,
116 | type: property_info.type
117 | }
118 | }
119 | }
120 | }
121 | }
122 |
123 |
124 | function get_parent_go(collection_data, go_id) {
125 | for (i in collection_data.embedded_instances) {
126 | let go_info = collection_data.embedded_instances[i]
127 | if (go_info.children && go_info.children.indexOf(go_id) >= 0) {
128 | return go_info
129 | }
130 | }
131 |
132 | return null
133 | }
134 |
135 |
136 | function get_go_anchor_from_collection(collection_data, go_id) {
137 | let anchors = { x: 0, y: 0 }
138 | // Iterate over included go's
139 | for (i in collection_data.embedded_instances) {
140 | let go_info = collection_data.embedded_instances[i]
141 | if (go_info.id[0] == go_id) {
142 | anchors.x = anchors.x + go_info.position[0].x[0]
143 | anchors.y = anchors.y + go_info.position[0].y[0]
144 |
145 | let parent_go = get_parent_go(collection_data, go_id)
146 | while (parent_go) {
147 | anchors.x = anchors.x + parent_go.position[0].x[0]
148 | anchors.y = anchors.y + parent_go.position[0].y[0]
149 | parent_go = get_parent_go(collection_data, parent_go.id[0])
150 | }
151 | }
152 | }
153 |
154 | return anchors
155 | }
156 |
157 |
158 | function process_collection_asset(asset_path, tileset_path) {
159 | let tileset_name = tileset_path.join("-")
160 | items[tileset_name] = items[tileset_name] || []
161 |
162 | helper.log("Process collection asset", path.relative(process.cwd(), asset_path), tileset_path.join("-"))
163 |
164 | let asset_name = path.basename(asset_path)
165 | let image_folder_path = path.join(asset_path, constants.ASSETS_IMAGES_FOLDER)
166 | let images = []
167 | if (fs.existsSync(image_folder_path)) {
168 | images = fs.readdirSync(image_folder_path)
169 | .filter(name => name.endsWith(".png"))
170 | }
171 |
172 | let anchors = [] // with different priorities
173 | let default_image = null
174 | let image_url = null
175 | let go_path = path.join(asset_path, asset_name + ".collection")
176 | let go_parsed = defold_parser.load_from_file(go_path)
177 | let go_properties = {}
178 |
179 | for (i in go_parsed.embedded_instances) {
180 | let go_info = go_parsed.embedded_instances[i]
181 | let go_data = go_info.data[0]
182 | parse_properties_from_go(go_data, go_properties, go_info.id[0])
183 |
184 | // TODO: Image priority: asset_name.go#asset_name, asset_name.go#sprite, #sprite
185 |
186 | if (go_info.id[0] == "tiled_anchor") {
187 | anchors[0] = get_go_anchor_from_collection(go_parsed, go_info.id[0])
188 | }
189 |
190 | for (let j in go_data.embedded_components) {
191 | let component = go_data.embedded_components[j]
192 | if (component.id[0] == "sprite") {
193 | let go_anchor = get_go_anchor_from_collection(go_parsed, go_info.id[0])
194 | anchors[1] = {}
195 | anchors[1].x = component.position[0].x[0] + go_anchor.x
196 | anchors[1].y = component.position[0].y[0] + go_anchor.y
197 | default_image = component.data[0].default_animation[0]
198 | image_url = go_info.id[0] + "#" + component.id[0]
199 | }
200 | }
201 | }
202 |
203 | let anchor = anchors[0] || anchors[1] || { x: 0, y: 0 }
204 | if (images.length > 0) {
205 | for (let i in images) {
206 | let image_path = path.join(image_folder_path, images[i])
207 | let size = image_size(image_path)
208 |
209 | let item = helper.get_assets_item_data(image_path, asset_name, go_properties, size,
210 | anchor, go_path, default_image, image_url, true)
211 | items[tileset_name].push(item)
212 | }
213 | } else {
214 | let item = helper.get_assets_item_data(null, asset_name, go_properties, constants.DEFAULT_IMAGE_SIZE,
215 | anchor, go_path, null, null, true)
216 | items[tileset_name].push(item)
217 | }
218 | }
219 |
220 |
221 | function process_asset(asset_path, tileset_path) {
222 | let tileset_name = tileset_path.join("-")
223 | items[tileset_name] = items[tileset_name] || []
224 |
225 | helper.log("Process game object asset", path.relative(process.cwd(), asset_path), tileset_path.join("-"))
226 |
227 | let asset_name = path.basename(asset_path)
228 | let image_folder_path = path.join(asset_path, constants.ASSETS_IMAGES_FOLDER)
229 | let images = []
230 | if (fs.existsSync(image_folder_path)) {
231 | images = fs.readdirSync(image_folder_path)
232 | .filter(name => name.endsWith(".png"))
233 | }
234 |
235 | let anchor = { x: 0, y: 0 }
236 | let default_image = null
237 | let image_url = null
238 | let go_path = path.join(asset_path, asset_name + ".go")
239 | let go_parsed = defold_parser.load_from_file(go_path)
240 | let go_properties = {}
241 |
242 | parse_properties_from_go(go_parsed, go_properties, asset_name)
243 |
244 | for (let i in go_parsed.embedded_components) {
245 | let elem = go_parsed.embedded_components[i]
246 | if (elem.id[0] == "sprite") {
247 | anchor.x = elem.position[0].x[0]
248 | anchor.y = elem.position[0].y[0]
249 | default_image = elem.data[0].default_animation[0].replace(/\\\"/g, "")
250 | image_url = "#" + elem.id[0]
251 | }
252 | }
253 |
254 | if (images.length > 0) {
255 | for (let i in images) {
256 | let image_path = path.join(image_folder_path, images[i])
257 | let size = image_size(image_path)
258 |
259 | let item = helper.get_assets_item_data(image_path, asset_name, go_properties, size,
260 | anchor, go_path, default_image, image_url, false)
261 | items[tileset_name].push(item)
262 | }
263 | } else {
264 | let item = helper.get_assets_item_data(null, asset_name, go_properties, constants.DEFAULT_IMAGE_SIZE,
265 | anchor, go_path, null, null, false)
266 | items[tileset_name].push(item)
267 | }
268 | }
269 |
270 |
271 | function process_tilesource(asset_path, tileset_path) {
272 | let tileset_name = tileset_path.join("-")
273 | tilesources[tileset_name] = tilesources[tileset_name] || []
274 |
275 | let asset_name = path.basename(asset_path)
276 | let tilesource_path = path.join(asset_path, asset_name + ".tilesource")
277 |
278 | let tilesource_data = fs.readFileSync(tilesource_path).toString('utf8')
279 | let tile_width = parseInt(tilesource_data.match(/tile_width: (.*)/)[1])
280 | let tile_height = parseInt(tilesource_data.match(/tile_height: (.*)/)[1])
281 | let tile_spacing = parseInt(tilesource_data.match(/tile_spacing: (.*)/)[1]) || 0
282 | let tile_margin = parseInt(tilesource_data.match(/tile_margin: (.*)/)[1]) || 0
283 | let tile_image = tilesource_data.match(/image: "(.*)"/)[1]
284 |
285 | let image_path = path.join(process.cwd(), tile_image)
286 | let size = image_size(image_path)
287 |
288 | let tileset = {
289 | name: asset_name,
290 | width: tile_width,
291 | height: tile_height,
292 | image_path: image_path,
293 | tilesource_path: "/" + path.relative(process.cwd(), tilesource_path),
294 | image_width: size.width,
295 | image_height: size.height,
296 | tile_spacing: tile_spacing,
297 | tile_margin: tile_margin,
298 | }
299 | tilesources[tileset_name].push(tileset)
300 | }
301 |
302 |
303 | function process_dir(assets_folder, output_path, tileset_path) {
304 | tileset_path = tileset_path || [ constants.ASSETS_FOLDER_NAME ]
305 | let files = fs.readdirSync(assets_folder)
306 | let folders = files.filter(name => fs.statSync(path.join(assets_folder, name)).isDirectory())
307 |
308 | for (let i in folders) {
309 | let target_path = path.join(assets_folder, folders[i])
310 | if (is_folder_contains_named_file(target_path, ".collection")) {
311 | process_collection_asset(target_path, tileset_path)
312 | } else if (is_folder_contains_named_file(target_path, ".go")) {
313 | process_asset(target_path, tileset_path)
314 | } else if (is_folder_contains_named_file(target_path, ".tilesource")) {
315 | process_tilesource(target_path, tileset_path)
316 | } else {
317 | // Recursive assets search
318 | let folder_name = path.basename(target_path)
319 | let new_path = tileset_path.slice()
320 | new_path.push(folder_name)
321 | process_dir(target_path, output_path, new_path)
322 | }
323 | }
324 | }
325 |
326 | function get_item_name(item_data) {
327 | if (item_data.image_name) {
328 | return item_data.item + "-" + item_data.image_name
329 | } else {
330 | return item_data.item + "-" + item_data.item
331 | }
332 | }
333 |
334 |
335 | function get_item_id(tileset, item_data) {
336 | let item_id = get_item_name(item_data)
337 |
338 | tilesets_db[tileset] = tilesets_db[tileset] || {}
339 |
340 | if (tilesets_db[tileset][item_id] === undefined) {
341 | let max_id = -1
342 | for (let i in tilesets_db[tileset]) {
343 | max_id = Math.max(tilesets_db[tileset][i], max_id)
344 | }
345 | tilesets_db[tileset][item_id] = max_id + 1
346 | }
347 |
348 | return tilesets_db[tileset][item_id]
349 | }
350 |
351 |
352 | function write_tilesets(output_path, items) {
353 | let tileset_folder = path.join(output_path, "tilesets")
354 | let images_folder = path.join(output_path, "images")
355 |
356 | rimraf.sync(images_folder)
357 | rimraf.sync(tileset_folder)
358 | fs.mkdirSync(images_folder, { recursive: true })
359 | fs.mkdirSync(tileset_folder, { recursive: true })
360 |
361 | for (let name in items) {
362 | let item_list = items[name]
363 |
364 | let tileset = TILESET_TEMPLATE.replace("{TILESET_NAME}", name)
365 | tileset = tileset.replace("{TILESET_COUNT}", item_list.length)
366 | let max_width = 0
367 | let max_height = 0
368 |
369 | let tileset_items = ""
370 | for (let i in item_list) {
371 | let data = item_list[i]
372 | let item_id = get_item_id(name, data)
373 | let item = TILESET_ITEM_TEMPLATE.replace("{ITEM_ID}", item_id)
374 | item = item.replace("{ITEM_CLASS}", get_item_name(data))
375 | item = item.replace("{IMAGE_WIDTH}", data.width)
376 | item = item.replace("{IMAGE_HEIGHT}", data.height)
377 | item = item.replace("{ANCHOR_X}", data.anchor_x)
378 | item = item.replace("{ANCHOR_Y}", data.anchor_y)
379 |
380 | let tiled_image_name = name + "-" + get_item_name(data) + ".png"
381 | let new_image_path = path.join(images_folder, name)
382 | let image_path = data.image_path || path.join(process.cwd(), constants.DEFAULT_IMAGE)
383 | new_image_path = path.join(new_image_path, tiled_image_name)
384 |
385 | fs.mkdirSync(path.dirname(new_image_path), { recursive: true })
386 | fs.copyFileSync(image_path, new_image_path)
387 | item = item.replace("{IMAGE_PATH}", path.relative(tileset_folder, new_image_path))
388 |
389 | let properties = ""
390 | properties += TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", "__object_name").replace("{VALUE}", data.item).replace("{TYPE}", "") + "\n"
391 | properties += TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", "__go_path").replace("{VALUE}", data.go_path).replace("{TYPE}", "") + "\n"
392 | properties += TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", "__image_name").replace("{VALUE}", path.basename(image_path, ".png")).replace("{TYPE}", "") + "\n"
393 | properties += TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", "__is_collection").replace("{VALUE}", data.is_collection && "true" || "false").replace("{TYPE}", 'type="bool"') + "\n"
394 | properties += TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", "__default_image_name").replace("{VALUE}", data.default_image).replace("{TYPE}", "")
395 | properties += TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", "__image_url").replace("{VALUE}", data.image_url).replace("{TYPE}", "")
396 |
397 | for (let key in data.properties) {
398 | let property_type = data.properties[key].type
399 | let property = data.properties[key].value
400 | let type = helper.defold_to_tiled_property_xml_type(property_type)
401 | properties += "\n" + TILESET_ITEM_PROPERTY_TEMPLATE.replace("{KEY}", key).replace("{VALUE}", property).replace("{TYPE}", type)
402 | }
403 |
404 | item = item.replace("{PROPERTIES}", properties)
405 |
406 | max_width = Math.max(data.width, max_width)
407 | max_height = Math.max(data.height, max_height)
408 | tileset_items += item
409 | }
410 |
411 | tileset = tileset.replace("{ITEMS}", tileset_items)
412 | tileset = tileset.replace("{TILESET_WIDTH}", max_width)
413 | tileset = tileset.replace("{TILESET_HEIGHT}", max_height)
414 |
415 | let tileset_path = path.join(tileset_folder, name + ".tsx")
416 | helper.log("Write tileset", tileset_path)
417 | fs.writeFileSync(tileset_path, tileset)
418 | }
419 |
420 | for (let category in tilesources) {
421 | for (let index in tilesources[category]) {
422 | let tilesource = tilesources[category][index]
423 | let filename = category + "-" + tilesource.name
424 |
425 | let tileset = TILESET_ITEM_TILESOURCE.replace("{TILESET_NAME}", tilesource.name)
426 | tileset = tileset.replace("{TILESET_WIDTH}", tilesource.width)
427 | tileset = tileset.replace("{TILESET_HEIGHT}", tilesource.height)
428 | tileset = tileset.replace("{TILESET_SPACING}", tilesource.tile_spacing)
429 | tileset = tileset.replace("{TILESET_MARGIN}", tilesource.tile_margin)
430 | tileset = tileset.replace("{TILESOURCE_PATH}", tilesource.tilesource_path)
431 | let count = (tilesource.image_height / tilesource.height) * (tilesource.image_width / tilesource.width)
432 | tileset = tileset.replace("{TILESET_COUNT}", count)
433 |
434 | let image_path = path.join(images_folder, category)
435 | image_path = path.join(image_path, path.basename(tilesource.image_path))
436 |
437 | fs.mkdirSync(path.dirname(image_path), { recursive: true })
438 | fs.copyFileSync(tilesource.image_path, image_path)
439 |
440 | let item = TILESET_ITEM_TILEITEM.replace("{TILESET_PATH}", path.relative(tileset_folder, image_path))
441 | item = item.replace("{IMAGE_WIDTH}", tilesource.image_width)
442 | item = item.replace("{IMAGE_HEIGHT}", tilesource.image_height)
443 | tileset = tileset.replace("{ITEMS}", item)
444 |
445 | let tileset_path = path.join(tileset_folder, filename + ".tsx")
446 | helper.log("Write tilesource tileset", tileset_path)
447 | fs.writeFileSync(tileset_path, tileset)
448 | }
449 | }
450 | }
451 |
452 |
453 | function start(assets_folder_path, output_folder_path) {
454 | helper.log("Start generate tilesets from Defold assets")
455 | let assets_folder = path.resolve(assets_folder_path)
456 | let output_path = path.resolve(output_folder_path)
457 |
458 | parse_tilesets_db_from_tsx(output_path)
459 | process_dir(assets_folder, output_path)
460 | write_tilesets(output_path, items)
461 | }
462 |
463 |
464 | module.exports.start = start
465 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/process_maps.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const path = require("path")
3 | const process = require("process")
4 | const settings = require("../settings.json")
5 |
6 | const COLLECTION_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/collection.template")).toString('utf8')
7 | const COLLECTION_GO_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/collection_go.template")).toString('utf8')
8 |
9 | const M = {}
10 |
11 |
12 | M.generate_spawners = function(name, data, output_path) {
13 | let filename = "spawner_" + name
14 | let collection = COLLECTION_TEMPLATE.replace("{1}", filename)
15 | let generated_path = output_path.replace(process.cwd(), "")
16 |
17 | let tilesets = data.tilesets
18 | let spawners_go = []
19 |
20 | for (let i in tilesets) {
21 | let tileset = tilesets[i]
22 | let tileset_name = path.basename(tileset.source, ".tsx")
23 |
24 | let spawner_name = "spawner_" + tileset_name
25 | let spawner_go = COLLECTION_GO_TEMPLATE.replace("{1}", spawner_name)
26 |
27 | let spawner_path = path.join(generated_path, "spawners", spawner_name + ".go")
28 | spawner_go = spawner_go.replace("{2}", spawner_path)
29 | // It can be that spawner is empty and we don't want create spawner link
30 | if (fs.existsSync(path.join(process.cwd(), spawner_path))) {
31 | spawners_go.push(spawner_go)
32 | }
33 | }
34 |
35 | collection += spawners_go.join("\n")
36 |
37 | let map_spawners_path = path.join(output_path, "maps", name)
38 | fs.mkdirSync(map_spawners_path, { recursive: true })
39 |
40 | let output_file = path.join(map_spawners_path, filename + ".collection")
41 | fs.writeFileSync(output_file, collection)
42 | console.log("Write map spawners:", output_file)
43 | }
44 |
45 |
46 | module.exports = M
47 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/process_tilesets.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const path = require("path")
3 | const process = require("process")
4 |
5 | const FACTORY_NODE_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/factory_node.template")).toString('utf8')
6 | const COLLECTION_FACTORY_NODE_TEMPLATE = fs.readFileSync(path.join(__dirname, "templates/collection_factory_node.template")).toString('utf8')
7 |
8 | const M = {}
9 |
10 |
11 | function get_all_properies(props) {
12 | let map = {}
13 | for (let i in props) {
14 | map[props[i].name] = props[i].value
15 | }
16 | return map
17 | }
18 |
19 |
20 | function get_anchor(tile) {
21 | if (tile.objectgroup) {
22 | let objects = tile.objectgroup.objects
23 | for (let i in objects) {
24 | let object = objects[i]
25 | if (object.point) {
26 | return {
27 | x: tile.imagewidth/2 - object.x,
28 | y: tile.imageheight/2 - (tile.imageheight - object.y)
29 | }
30 | }
31 | }
32 | }
33 | return {
34 | x: 0,
35 | y: 0
36 | }
37 | }
38 |
39 |
40 | /// Generate new objects for all images
41 | // It is not override previous objects, due to customization
42 | M.generate_factories = function(data, output_path, mapping) {
43 | console.log("Start generate factories for", data.name)
44 |
45 | mapping[data.name] = mapping[data.name] || {}
46 | let tiles = data.tiles
47 |
48 | let spawner_go = ""
49 | let objects_ready = {}
50 |
51 | for (let i in tiles) {
52 | let tile = tiles[i]
53 | let tile_image = path.basename(tile.image)
54 | let props = tile.properties
55 |
56 | if (!props) {
57 | console.log("No properties at object", tile_image)
58 | continue
59 | }
60 |
61 | let properties = get_all_properies(tile.properties)
62 | let anchor = get_anchor(tile)
63 | let object_name = properties.__object_name
64 |
65 | mapping[data.name][tile.id] = {
66 | object_name: object_name,
67 | is_collection: properties.__is_collection,
68 | image_name: properties.__image_name,
69 | image_url: properties.__image_url,
70 | anchor: anchor,
71 | width: tile.imagewidth,
72 | height: tile.imageheight,
73 | go_path: properties.__go_path,
74 | properties: properties
75 | }
76 |
77 | if (!objects_ready[object_name]) {
78 | let template = properties.__is_collection && COLLECTION_FACTORY_NODE_TEMPLATE || FACTORY_NODE_TEMPLATE
79 | let spawner_data = template.replace("{1}", object_name)
80 | spawner_data = spawner_data.replace("{2}", properties.__go_path)
81 | spawner_go += spawner_data
82 | objects_ready[object_name] = true
83 | }
84 |
85 | // Delete system properties from generator
86 | delete properties.__go_path
87 | delete properties.__object_name
88 | delete properties.__image_name
89 | delete properties.__image_url
90 | delete properties.__is_collection
91 | }
92 |
93 | if (spawner_go.length > 0) {
94 | let spawner_folder = path.join(output_path, "spawners")
95 | fs.mkdirSync(spawner_folder, { recursive: true })
96 | let spawner_path = path.join(spawner_folder, "spawner_" + data.name + ".go")
97 | fs.writeFileSync(spawner_path, spawner_go)
98 | console.log("Add", spawner_path)
99 | }
100 | }
101 |
102 |
103 | module.exports = M
104 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/collection.template:
--------------------------------------------------------------------------------
1 | name: "{1}"
2 | scale_along_z: 0
3 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/collection_factory_node.template:
--------------------------------------------------------------------------------
1 | embedded_components {
2 | id: "{1}"
3 | type: "collectionfactory"
4 | data: "prototype: \"{2}\"\n"
5 | "load_dynamically: false\n"
6 | ""
7 | position {
8 | x: 0.0
9 | y: 0.0
10 | z: 0.0
11 | }
12 | rotation {
13 | x: 0.0
14 | y: 0.0
15 | z: 0.0
16 | w: 1.0
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/collection_go.template:
--------------------------------------------------------------------------------
1 | instances {
2 | id: "{1}"
3 | prototype: "{2}"
4 | position {
5 | x: 0.0
6 | y: 0.0
7 | z: 0.0
8 | }
9 | rotation {
10 | x: 0.0
11 | y: 0.0
12 | z: 0.0
13 | w: 1.0
14 | }
15 | scale3 {
16 | x: 1.0
17 | y: 1.0
18 | z: 1.0
19 | }
20 | }
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/factory_node.template:
--------------------------------------------------------------------------------
1 | embedded_components {
2 | id: "{1}"
3 | type: "factory"
4 | data: "prototype: \"{2}\"\n"
5 | "load_dynamically: false\n"
6 | ""
7 | position {
8 | x: 0.0
9 | y: 0.0
10 | z: 0.0
11 | }
12 | rotation {
13 | x: 0.0
14 | y: 0.0
15 | z: 0.0
16 | w: 1.0
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/tileset_xml.template:
--------------------------------------------------------------------------------
1 |
2 |
3 | {ITEMS}
4 |
5 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/tileset_xml_item.template:
--------------------------------------------------------------------------------
1 |
2 |
3 | {PROPERTIES}
4 |
5 |
6 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/tileset_xml_item_property.template:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/tileset_xml_tileitem.template:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/detiled_exporter/scripts/templates/tileset_xml_tilesource.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {ITEMS}
7 |
8 |
--------------------------------------------------------------------------------
/detiled_exporter/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | }
3 |
--------------------------------------------------------------------------------
/example/assets/dungeon/dungeon_atlas.atlas:
--------------------------------------------------------------------------------
1 | images {
2 | image: "/example/assets/dungeon/objects/player/images/tile_0096.png"
3 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
4 | }
5 | images {
6 | image: "/example/assets/dungeon/objects/player/images/tile_0097.png"
7 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
8 | }
9 | images {
10 | image: "/example/assets/dungeon/objects/player/images/tile_0098.png"
11 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
12 | }
13 | images {
14 | image: "/example/assets/dungeon/objects/player/images/tile_0099.png"
15 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
16 | }
17 | images {
18 | image: "/example/assets/dungeon/objects/player/images/tile_0100.png"
19 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
20 | }
21 | images {
22 | image: "/example/assets/dungeon/objects/weapon/images/tile_0103.png"
23 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
24 | }
25 | images {
26 | image: "/example/assets/dungeon/objects/weapon/images/tile_0104.png"
27 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
28 | }
29 | images {
30 | image: "/example/assets/dungeon/objects/weapon/images/tile_0105.png"
31 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
32 | }
33 | images {
34 | image: "/example/assets/dungeon/objects/weapon/images/tile_0106.png"
35 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
36 | }
37 | images {
38 | image: "/example/assets/dungeon/objects/weapon/images/tile_0107.png"
39 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
40 | }
41 | images {
42 | image: "/example/assets/dungeon/objects/weapon/images/tile_0117.png"
43 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
44 | }
45 | images {
46 | image: "/example/assets/dungeon/objects/weapon/images/tile_0118.png"
47 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
48 | }
49 | images {
50 | image: "/example/assets/dungeon/objects/weapon/images/tile_0119.png"
51 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
52 | }
53 | images {
54 | image: "/example/assets/dungeon/objects/weapon/images/tile_0125.png"
55 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
56 | }
57 | images {
58 | image: "/example/assets/dungeon/objects/weapon/images/tile_0126.png"
59 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
60 | }
61 | images {
62 | image: "/example/assets/dungeon/objects/weapon/images/tile_0127.png"
63 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
64 | }
65 | images {
66 | image: "/example/assets/dungeon/objects/weapon/images/tile_0128.png"
67 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
68 | }
69 | images {
70 | image: "/example/assets/dungeon/objects/weapon/images/tile_0129.png"
71 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
72 | }
73 | images {
74 | image: "/example/assets/dungeon/objects/weapon/images/tile_0130.png"
75 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
76 | }
77 | images {
78 | image: "/example/assets/dungeon/objects/weapon/images/tile_0131.png"
79 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
80 | }
81 | margin: 0
82 | extrude_borders: 2
83 | inner_padding: 0
84 |
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/fire/fire.go:
--------------------------------------------------------------------------------
1 | embedded_components {
2 | id: "collisionobject"
3 | type: "collisionobject"
4 | data: "collision_shape: \"\"\n"
5 | "type: COLLISION_OBJECT_TYPE_DYNAMIC\n"
6 | "mass: 1.0\n"
7 | "friction: 0.1\n"
8 | "restitution: 0.5\n"
9 | "group: \"default\"\n"
10 | "mask: \"default\"\n"
11 | "embedded_collision_shape {\n"
12 | " shapes {\n"
13 | " shape_type: TYPE_BOX\n"
14 | " position {\n"
15 | " x: 0.0\n"
16 | " y: 0.0\n"
17 | " z: 0.0\n"
18 | " }\n"
19 | " rotation {\n"
20 | " x: 0.0\n"
21 | " y: 0.0\n"
22 | " z: 0.0\n"
23 | " w: 1.0\n"
24 | " }\n"
25 | " index: 0\n"
26 | " count: 3\n"
27 | " }\n"
28 | " data: 10.0\n"
29 | " data: 10.0\n"
30 | " data: 10.0\n"
31 | "}\n"
32 | "linear_damping: 0.0\n"
33 | "angular_damping: 0.0\n"
34 | "locked_rotation: false\n"
35 | "bullet: false\n"
36 | ""
37 | position {
38 | x: 0.0
39 | y: 0.0
40 | z: 0.0
41 | }
42 | rotation {
43 | x: 0.0
44 | y: 0.0
45 | z: 0.0
46 | w: 1.0
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/fire/images/fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/fire/images/fire.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/images/new_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/player/images/new_icon.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/images/tile_0096.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/player/images/tile_0096.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/images/tile_0097.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/player/images/tile_0097.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/images/tile_0098.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/player/images/tile_0098.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/images/tile_0099.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/player/images/tile_0099.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/images/tile_0100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/player/images/tile_0100.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/player.collection:
--------------------------------------------------------------------------------
1 | name: "default"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "player"
5 | children: "go"
6 | data: "components {\n"
7 | " id: \"detiled_init_image\"\n"
8 | " component: \"/detiled/detiled_init_image.script\"\n"
9 | " position {\n"
10 | " x: 0.0\n"
11 | " y: 0.0\n"
12 | " z: 0.0\n"
13 | " }\n"
14 | " rotation {\n"
15 | " x: 0.0\n"
16 | " y: 0.0\n"
17 | " z: 0.0\n"
18 | " w: 1.0\n"
19 | " }\n"
20 | " property_decls {\n"
21 | " }\n"
22 | "}\n"
23 | ""
24 | position {
25 | x: 0.0
26 | y: 0.0
27 | z: 0.0
28 | }
29 | rotation {
30 | x: 0.0
31 | y: 0.0
32 | z: 0.0
33 | w: 1.0
34 | }
35 | scale3 {
36 | x: 1.0
37 | y: 1.0
38 | z: 1.0
39 | }
40 | }
41 | embedded_instances {
42 | id: "go"
43 | data: "components {\n"
44 | " id: \"player_script\"\n"
45 | " component: \"/example/assets/dungeon/objects/player/player.script\"\n"
46 | " position {\n"
47 | " x: 0.0\n"
48 | " y: 0.0\n"
49 | " z: 0.0\n"
50 | " }\n"
51 | " rotation {\n"
52 | " x: 0.0\n"
53 | " y: 0.0\n"
54 | " z: 0.0\n"
55 | " w: 1.0\n"
56 | " }\n"
57 | " properties {\n"
58 | " id: \"life\"\n"
59 | " value: \"30.0\"\n"
60 | " type: PROPERTY_TYPE_NUMBER\n"
61 | " }\n"
62 | " properties {\n"
63 | " id: \"quar\"\n"
64 | " value: \"0.2880148, 0.2880148, 0.6457921, 0.6457921\"\n"
65 | " type: PROPERTY_TYPE_QUAT\n"
66 | " }\n"
67 | " properties {\n"
68 | " id: \"bool\"\n"
69 | " value: \"true\"\n"
70 | " type: PROPERTY_TYPE_BOOLEAN\n"
71 | " }\n"
72 | " properties {\n"
73 | " id: \"atlas\"\n"
74 | " value: \"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource\"\n"
75 | " type: PROPERTY_TYPE_HASH\n"
76 | " }\n"
77 | " property_decls {\n"
78 | " }\n"
79 | "}\n"
80 | "embedded_components {\n"
81 | " id: \"sprite\"\n"
82 | " type: \"sprite\"\n"
83 | " data: \"tile_set: \\\"/example/assets/dungeon/dungeon_atlas.atlas\\\"\\n"
84 | "default_animation: \\\"tile_0096\\\"\\n"
85 | "material: \\\"/builtins/materials/sprite.material\\\"\\n"
86 | "blend_mode: BLEND_MODE_ALPHA\\n"
87 | "\"\n"
88 | " position {\n"
89 | " x: 0.0\n"
90 | " y: 8.0\n"
91 | " z: 0.0\n"
92 | " }\n"
93 | " rotation {\n"
94 | " x: 0.0\n"
95 | " y: 0.0\n"
96 | " z: 0.0\n"
97 | " w: 1.0\n"
98 | " }\n"
99 | "}\n"
100 | ""
101 | position {
102 | x: 0.0
103 | y: 0.0
104 | z: 0.0
105 | }
106 | rotation {
107 | x: 0.0
108 | y: 0.0
109 | z: 0.0
110 | w: 1.0
111 | }
112 | scale3 {
113 | x: 1.0
114 | y: 1.0
115 | z: 1.0
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/player/player.script:
--------------------------------------------------------------------------------
1 | go.property("life", 10)
2 | go.property("v3", vmath.vector3(1, 2, 3))
3 | go.property("v4", vmath.vector4(4, 5, 6, 7))
4 | go.property("quar", vmath.quat(1, 2, 3, 4))
5 | go.property("url", msg.url("s"))
6 | go.property("hash", hash("set"))
7 | go.property("bool", false)
8 | go.property("atlas", resource.atlas(""))
9 | go.property("res_font", resource.font())
10 |
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/water/water.go:
--------------------------------------------------------------------------------
1 | embedded_components {
2 | id: "collisionobject"
3 | type: "collisionobject"
4 | data: "collision_shape: \"\"\n"
5 | "type: COLLISION_OBJECT_TYPE_DYNAMIC\n"
6 | "mass: 1.0\n"
7 | "friction: 0.1\n"
8 | "restitution: 0.5\n"
9 | "group: \"default\"\n"
10 | "mask: \"default\"\n"
11 | "embedded_collision_shape {\n"
12 | " shapes {\n"
13 | " shape_type: TYPE_BOX\n"
14 | " position {\n"
15 | " x: 0.0\n"
16 | " y: 0.0\n"
17 | " z: 0.0\n"
18 | " }\n"
19 | " rotation {\n"
20 | " x: 0.0\n"
21 | " y: 0.0\n"
22 | " z: 0.0\n"
23 | " w: 1.0\n"
24 | " }\n"
25 | " index: 0\n"
26 | " count: 3\n"
27 | " }\n"
28 | " data: 10.0\n"
29 | " data: 10.0\n"
30 | " data: 10.0\n"
31 | "}\n"
32 | "linear_damping: 0.0\n"
33 | "angular_damping: 0.0\n"
34 | "locked_rotation: false\n"
35 | "bullet: false\n"
36 | ""
37 | position {
38 | x: 0.0
39 | y: 0.0
40 | z: 0.0
41 | }
42 | rotation {
43 | x: 0.0
44 | y: 0.0
45 | z: 0.0
46 | w: 1.0
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0103.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0103.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0104.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0104.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0105.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0105.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0106.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0106.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0107.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0107.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0117.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0117.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0118.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0118.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0119.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0119.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0125.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0126.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0126.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0127.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0127.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0128.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0129.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0129.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0130.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0130.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/images/tile_0131.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/objects/weapon/images/tile_0131.png
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/weapon.go:
--------------------------------------------------------------------------------
1 | components {
2 | id: "weapon_script"
3 | component: "/example/assets/dungeon/objects/weapon/weapon.script"
4 | position {
5 | x: 0.0
6 | y: 0.0
7 | z: 0.0
8 | }
9 | rotation {
10 | x: 0.0
11 | y: 0.0
12 | z: 0.0
13 | w: 1.0
14 | }
15 | }
16 | components {
17 | id: "detiled_init_image"
18 | component: "/detiled/detiled_init_image.script"
19 | position {
20 | x: 0.0
21 | y: 0.0
22 | z: 0.0
23 | }
24 | rotation {
25 | x: 0.0
26 | y: 0.0
27 | z: 0.0
28 | w: 1.0
29 | }
30 | }
31 | embedded_components {
32 | id: "sprite"
33 | type: "sprite"
34 | data: "tile_set: \"/example/assets/dungeon/dungeon_atlas.atlas\"\n"
35 | "default_animation: \"tile_0126\"\n"
36 | "material: \"/builtins/materials/sprite.material\"\n"
37 | "blend_mode: BLEND_MODE_ALPHA\n"
38 | ""
39 | position {
40 | x: 0.0
41 | y: 8.0
42 | z: 0.0
43 | }
44 | rotation {
45 | x: 0.0
46 | y: 0.0
47 | z: 0.0
48 | w: 1.0
49 | }
50 | }
51 | embedded_components {
52 | id: "collisionobject"
53 | type: "collisionobject"
54 | data: "collision_shape: \"\"\n"
55 | "type: COLLISION_OBJECT_TYPE_TRIGGER\n"
56 | "mass: 0.0\n"
57 | "friction: 0.1\n"
58 | "restitution: 0.5\n"
59 | "group: \"default\"\n"
60 | "mask: \"default\"\n"
61 | "embedded_collision_shape {\n"
62 | " shapes {\n"
63 | " shape_type: TYPE_BOX\n"
64 | " position {\n"
65 | " x: 0.0\n"
66 | " y: 8.0\n"
67 | " z: 0.0\n"
68 | " }\n"
69 | " rotation {\n"
70 | " x: 0.0\n"
71 | " y: 0.0\n"
72 | " z: 0.0\n"
73 | " w: 1.0\n"
74 | " }\n"
75 | " index: 0\n"
76 | " count: 3\n"
77 | " }\n"
78 | " data: 8.0\n"
79 | " data: 8.0\n"
80 | " data: 10.0\n"
81 | "}\n"
82 | "linear_damping: 0.0\n"
83 | "angular_damping: 0.0\n"
84 | "locked_rotation: false\n"
85 | "bullet: false\n"
86 | ""
87 | position {
88 | x: 0.0
89 | y: 0.0
90 | z: 0.0
91 | }
92 | rotation {
93 | x: 0.0
94 | y: 0.0
95 | z: 0.0
96 | w: 1.0
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/example/assets/dungeon/objects/weapon/weapon.script:
--------------------------------------------------------------------------------
1 | go.property("power", 20)
2 |
3 | function init(self)
4 | -- Add initialization code here
5 | -- Learn more: https://defold.com/manuals/script/
6 | -- Remove this function if not needed
7 | end
8 |
9 | function final(self)
10 | -- Add finalization code here
11 | -- Learn more: https://defold.com/manuals/script/
12 | -- Remove this function if not needed
13 | end
14 |
15 | function update(self, dt)
16 | -- Add update code here
17 | -- Learn more: https://defold.com/manuals/script/
18 | -- Remove this function if not needed
19 | end
20 |
21 | function fixed_update(self, dt)
22 | -- Add update code here
23 | -- Learn more: https://defold.com/manuals/script/
24 | -- Remove this function if not needed
25 | end
26 |
27 | function on_message(self, message_id, message, sender)
28 | -- Add message-handling code here
29 | -- Learn more: https://defold.com/manuals/message-passing/
30 | -- Remove this function if not needed
31 | end
32 |
33 | function on_input(self, action_id, action)
34 | -- Add input-handling code here. The game object this script is attached to
35 | -- must have acquired input focus:
36 | --
37 | -- msg.post(".", "acquire_input_focus")
38 | --
39 | -- All mapped input bindings will be received. Mouse and touch input will
40 | -- be received regardless of where on the screen it happened.
41 | -- Learn more: https://defold.com/manuals/input/
42 | -- Remove this function if not needed
43 | end
44 |
45 | function on_reload(self)
46 | -- Add reload-handling code here
47 | -- Learn more: https://defold.com/manuals/hot-reload/
48 | -- Remove this function if not needed
49 | end
50 |
--------------------------------------------------------------------------------
/example/assets/dungeon/tileset/dungeon/dungeon.tilesource:
--------------------------------------------------------------------------------
1 | image: "/example/assets/dungeon/tileset/dungeon/dungeon_tilemap.png"
2 | tile_width: 16
3 | tile_height: 16
4 | tile_margin: 0
5 | tile_spacing: 1
6 | collision: ""
7 | material_tag: "tile"
8 | collision_groups: "default"
9 | animations {
10 | id: "anim"
11 | start_tile: 1
12 | end_tile: 1
13 | playback: PLAYBACK_ONCE_FORWARD
14 | fps: 30
15 | flip_horizontal: 0
16 | flip_vertical: 0
17 | }
18 | extrude_borders: 1
19 | inner_padding: 0
20 | sprite_trim_mode: SPRITE_TRIM_MODE_OFF
21 |
--------------------------------------------------------------------------------
/example/assets/dungeon/tileset/dungeon/dungeon_tilemap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example/assets/dungeon/tileset/dungeon/dungeon_tilemap.png
--------------------------------------------------------------------------------
/example/example.collection:
--------------------------------------------------------------------------------
1 | name: "main"
2 | collection_instances {
3 | id: "dungeon_01"
4 | collection: "/example/generated/maps/dungeon_01/dungeon_01.collection"
5 | position {
6 | x: 0.0
7 | y: 0.0
8 | z: 0.0
9 | }
10 | rotation {
11 | x: 0.0
12 | y: 0.0
13 | z: 0.0
14 | w: 1.0
15 | }
16 | scale3 {
17 | x: 2.0
18 | y: 2.0
19 | z: 1.0
20 | }
21 | }
22 | scale_along_z: 0
23 |
--------------------------------------------------------------------------------
/example/generated/json_maps/dungeon_01.json:
--------------------------------------------------------------------------------
1 | {"compressionlevel":-1,"height":20,"infinite":false,"layers":[{"data":[49,49,49,49,49,49,50,49,49,49,49,49,49,50,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,50,49,49,49,5,27,27,27,27,27,27,27,27,6,49,49,49,50,49,49,49,49,49,49,49,49,50,49,49,50,49,49,49,49,16,1,1,1,1,1,1,1,1,26,27,27,27,27,27,27,27,6,49,50,49,49,50,49,49,50,49,49,49,49,16,1,1,1,13,1,1,1,1,1,1,1,1,1,1,1,25,14,1610612787,50,49,49,50,49,49,49,49,49,49,49,16,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,18,1610612787,49,49,49,49,49,49,49,49,50,49,49,17,7,3,7,3,4,1,1,1,1,13,1,1,1,1,14,29,60,1610612787,49,49,49,49,50,49,49,49,50,49,49,58,19,29,19,15,16,25,1,1,1,1,1,1,1,1,14,41,60,1610612787,50,49,49,49,49,50,49,49,49,50,49,58,19,41,19,41,17,3,3,3,3,4,1,1,1,1,14,1610612789,52,54,50,49,49,49,49,49,49,49,49,49,49,51,31,51,31,53,58,15,29,41,41,16,1,1,1,1,14,1610612787,49,49,49,49,49,49,49,49,49,49,49,49,43,49,50,49,50,2684354612,58,41,41,41,41,17,3,3,3,3,18,1610612787,49,49,50,49,49,49,49,49,49,50,49,49,49,49,49,49,50,49,51,52,52,52,53,58,30,41,41,30,60,1610612787,49,49,50,49,49,49,49,49,49,49,49,50,49,49,49,49,49,49,49,49,49,49,2684354612,58,21,35,36,21,60,1610612787,49,50,49,49,49,49,49,50,49,49,49,49,49,49,49,49,49,49,49,49,49,49,2684354614,53,33,53,1610612789,33,1610612789,54,49,49,49,49,49,49,49,50,49,49,49,49,49,49,49,49,49,49,50,49,49,49,49,49,49,2684354614,54,50,43,49,49,50,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,50,49,49,49,49,50,49,49,49,49,43,50,49,49,50,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,50,49,50,49,49,49,50,49,49,49,50,49,49,49,49,49,49,49,49,50,49,49,50,49,49,49,49,49,50,49,50,43,49,49,50,49,50,49,49,49,49,49,50,49,49,49,49,49,49,49,49,49,49,50,49,49,49,49,49,49,49,50,49,50,50,49,49,49,49,49,50,49,50,49,50,49,49,49,49,49,49,49,49,49,49,49,50,50,49,49,50,49,49,50,49,49,49,49,50,49,49,49,50,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,50,49,50,49],"height":20,"id":1,"name":"Tile Layer 1","opacity":1,"type":"tilelayer","visible":true,"width":30,"x":0,"y":0},{"draworder":"topdown","id":3,"name":"Object Layer 1","objects":[{"class":"","gid":140,"height":16,"id":2,"name":"","rotation":0,"visible":true,"width":16,"x":321.19,"y":144.6,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0104"}]},{"class":"","gid":135,"height":16,"id":6,"name":"","rotation":0,"visible":true,"width":16,"x":335.486,"y":144.6,"properties":[{"name":"player:detiled_init_image:detiled_image_url","type":"string","value":"go#sprite"},{"name":"player:detiled_init_image:detiled_init_image","type":"string","value":"tile_0097"}]},{"class":"","gid":144,"height":16,"id":7,"name":"","rotation":0,"visible":true,"width":16,"x":352.958,"y":143.012,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0117"}]},{"class":"","gid":146,"height":16,"id":8,"name":"","rotation":0,"visible":true,"width":16,"x":369.239,"y":142.615,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0119"}]},{"class":"","gid":134,"height":16,"id":9,"name":"","rotation":35.0365,"visible":true,"width":16,"x":144.874,"y":231.021,"properties":[{"name":"player:detiled_init_image:detiled_image_url","type":"string","value":"go#sprite"},{"name":"player:detiled_init_image:detiled_init_image","type":"string","value":"tile_0096"}]},{"class":"","gid":134,"height":16,"id":10,"name":"","rotation":138.484,"visible":true,"width":16,"x":156.705,"y":191.57,"properties":[{"name":"player:detiled_init_image:detiled_image_url","type":"string","value":"go#sprite"},{"name":"player:detiled_init_image:detiled_init_image","type":"string","value":"tile_0096"}]},{"class":"","gid":134,"height":16,"id":11,"name":"","rotation":225,"visible":true,"width":16,"x":192.375,"y":203.722,"properties":[{"name":"player:detiled_init_image:detiled_image_url","type":"string","value":"go#sprite"},{"name":"player:detiled_init_image:detiled_init_image","type":"string","value":"tile_0096"}]},{"class":"","gid":134,"height":16,"id":12,"name":"","rotation":314.47,"visible":true,"width":16,"x":180.735,"y":239.384,"properties":[{"name":"player:detiled_init_image:detiled_image_url","type":"string","value":"go#sprite"},{"name":"player:detiled_init_image:detiled_init_image","type":"string","value":"tile_0096"}]},{"class":"","gid":142,"height":81.0317,"id":13,"name":"","rotation":0,"visible":true,"width":57.5263,"x":77.8184,"y":177.708,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0106"}]},{"class":"","gid":142,"height":81.0317,"id":14,"name":"","properties":[{"name":"weapon:weapon_script:power","type":"float","value":2000},{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0106"}],"rotation":121.164,"visible":true,"width":57.5263,"x":52.6905,"y":32.4431},{"class":"","gid":142,"height":81.0317,"id":15,"name":"","rotation":234.24,"visible":true,"width":57.5263,"x":189.184,"y":75.2423,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0106"}]},{"class":"","gid":142,"height":81.0317,"id":16,"name":"","rotation":234.24,"visible":true,"width":57.5263,"x":189.184,"y":75.2423,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0106"}]},{"class":"","gid":148,"height":16,"id":18,"name":"","rotation":0,"visible":true,"width":16,"x":296.941,"y":231.294,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0126"}]},{"class":"","gid":149,"height":16,"id":19,"name":"","rotation":0,"visible":true,"width":16,"x":366.815,"y":227.876,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0127"}]},{"class":"","gid":149,"height":16,"id":20,"name":"","rotation":0,"visible":true,"width":16,"x":276.434,"y":281.421,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0127"}]},{"class":"","gid":149,"height":16,"id":21,"name":"","rotation":0,"visible":true,"width":16,"x":331.498,"y":284.459,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0127"}]},{"class":"","gid":144,"height":16,"id":23,"name":"","rotation":0,"visible":true,"width":16,"x":98.4942,"y":106.02,"properties":[{"name":"weapon:detiled_init_image:detiled_image_url","type":"string","value":"#sprite"},{"name":"weapon:detiled_init_image:detiled_init_image","type":"string","value":"tile_0117"}]},{"class":"","gid":134,"height":102.468,"id":25,"name":"","properties":[{"name":"go:player_script:hash","type":"string","value":"osoe"},{"name":"player:detiled_init_image:detiled_image_url","type":"string","value":"go#sprite"},{"name":"player:detiled_init_image:detiled_init_image","type":"string","value":"tile_0096"}],"rotation":0.480196,"visible":true,"width":80.7421,"x":35.7189,"y":298.032},{"class":"","gid":159,"height":32,"id":26,"name":"","rotation":0,"visible":true,"width":32,"x":145.272,"y":300.7},{"class":"","gid":159,"height":32,"id":27,"name":"","rotation":0,"visible":true,"width":32,"x":175.698,"y":300.7},{"class":"","gid":160,"height":32,"id":31,"name":"","rotation":0,"visible":true,"width":32,"x":272.153,"y":192.366}],"opacity":1,"type":"objectgroup","visible":true,"x":0,"y":0},{"draworder":"topdown","id":12,"name":"Object Layer 2","objects":[{"class":"","gid":143,"height":16,"id":32,"name":"","rotation":0,"visible":true,"width":16,"x":226.615,"y":317.615},{"class":"","gid":143,"height":16,"id":33,"name":"","rotation":0,"visible":true,"width":16,"x":243.282,"y":317.615},{"class":"","gid":143,"height":16,"id":34,"name":"","rotation":0,"visible":true,"width":16,"x":253.538,"y":317.615},{"class":"","gid":143,"height":16,"id":35,"name":"","rotation":0,"visible":true,"width":16,"x":266.359,"y":317.615},{"class":"","gid":143,"height":16,"id":36,"name":"","rotation":0,"visible":true,"width":16,"x":286.231,"y":317.615}],"opacity":1,"properties":[{"name":"no_export","type":"bool","value":true}],"type":"objectgroup","visible":true,"x":0,"y":0},{"id":11,"layers":[{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,64,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,92,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,111,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"height":20,"id":2,"name":"Tile Layer 2","opacity":1,"type":"tilelayer","visible":true,"width":30,"x":0,"y":0},{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,78,79,0,77,78,79,0,77,78,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"height":20,"id":9,"name":"Tile Layer 3","opacity":1,"type":"tilelayer","visible":true,"width":30,"x":0,"y":0}],"name":"Group 1","opacity":1,"type":"group","visible":true,"x":0,"y":0}],"nextlayerid":13,"nextobjectid":37,"orientation":"orthogonal","renderorder":"right-down","tiledversion":"2022.09.22","tileheight":16,"tilesets":[{"firstgid":1,"source":"../../../../../Users/insality/code/js/detiled/example_tiled_export/tilesets/assets-dungeon-tileset-dungeon.tsx","name":"assets-dungeon-tileset-dungeon"},{"firstgid":133,"source":"../../../../../Users/insality/code/js/detiled/example_tiled_export/tilesets/assets-dungeon-objects.tsx","name":"assets-dungeon-objects"},{"firstgid":161,"source":":/automap-tiles.tsx","name":"automap-tiles"}],"tilewidth":16,"type":"map","version":"1.9","width":30}
--------------------------------------------------------------------------------
/example/generated/mapping.json:
--------------------------------------------------------------------------------
1 | {"assets-dungeon-objects":{"1":{"object_name":"player","is_collection":true,"image_name":"tile_0096","image_url":"go#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/player/player.collection","properties":{"__default_image_name":"tile_0096","go:player_script:atlas":"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource","go:player_script:bool":true,"go:player_script:hash":"set","go:player_script:life":30,"go:player_script:quar":"quat 0.2880148, 0.2880148, 0.6457921, 0.6457921","go:player_script:res_font":"","go:player_script:url":"s","go:player_script:v3":"1.0, 2.0, 3.0","go:player_script:v4":"4.0, 5.0, 6.0, 7.0","player:detiled_init_image:detiled_image_url":"","player:detiled_init_image:detiled_init_image":""}},"2":{"object_name":"player","is_collection":true,"image_name":"tile_0097","image_url":"go#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/player/player.collection","properties":{"__default_image_name":"tile_0096","go:player_script:atlas":"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource","go:player_script:bool":true,"go:player_script:hash":"set","go:player_script:life":30,"go:player_script:quar":"quat 0.2880148, 0.2880148, 0.6457921, 0.6457921","go:player_script:res_font":"","go:player_script:url":"s","go:player_script:v3":"1.0, 2.0, 3.0","go:player_script:v4":"4.0, 5.0, 6.0, 7.0","player:detiled_init_image:detiled_image_url":"","player:detiled_init_image:detiled_init_image":""}},"3":{"object_name":"player","is_collection":true,"image_name":"tile_0098","image_url":"go#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/player/player.collection","properties":{"__default_image_name":"tile_0096","go:player_script:atlas":"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource","go:player_script:bool":true,"go:player_script:hash":"set","go:player_script:life":30,"go:player_script:quar":"quat 0.2880148, 0.2880148, 0.6457921, 0.6457921","go:player_script:res_font":"","go:player_script:url":"s","go:player_script:v3":"1.0, 2.0, 3.0","go:player_script:v4":"4.0, 5.0, 6.0, 7.0","player:detiled_init_image:detiled_image_url":"","player:detiled_init_image:detiled_init_image":""}},"4":{"object_name":"player","is_collection":true,"image_name":"tile_0099","image_url":"go#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/player/player.collection","properties":{"__default_image_name":"tile_0096","go:player_script:atlas":"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource","go:player_script:bool":true,"go:player_script:hash":"set","go:player_script:life":30,"go:player_script:quar":"quat 0.2880148, 0.2880148, 0.6457921, 0.6457921","go:player_script:res_font":"","go:player_script:url":"s","go:player_script:v3":"1.0, 2.0, 3.0","go:player_script:v4":"4.0, 5.0, 6.0, 7.0","player:detiled_init_image:detiled_image_url":"","player:detiled_init_image:detiled_init_image":""}},"5":{"object_name":"player","is_collection":true,"image_name":"tile_0100","image_url":"go#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/player/player.collection","properties":{"__default_image_name":"tile_0096","go:player_script:atlas":"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource","go:player_script:bool":true,"go:player_script:hash":"set","go:player_script:life":30,"go:player_script:quar":"quat 0.2880148, 0.2880148, 0.6457921, 0.6457921","go:player_script:res_font":"","go:player_script:url":"s","go:player_script:v3":"1.0, 2.0, 3.0","go:player_script:v4":"4.0, 5.0, 6.0, 7.0","player:detiled_init_image:detiled_image_url":"","player:detiled_init_image:detiled_init_image":""}},"6":{"object_name":"weapon","is_collection":false,"image_name":"tile_0103","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"7":{"object_name":"weapon","is_collection":false,"image_name":"tile_0104","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"8":{"object_name":"weapon","is_collection":false,"image_name":"tile_0105","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"9":{"object_name":"weapon","is_collection":false,"image_name":"tile_0106","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"10":{"object_name":"weapon","is_collection":false,"image_name":"tile_0107","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"11":{"object_name":"weapon","is_collection":false,"image_name":"tile_0117","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"12":{"object_name":"weapon","is_collection":false,"image_name":"tile_0118","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"13":{"object_name":"weapon","is_collection":false,"image_name":"tile_0119","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"14":{"object_name":"weapon","is_collection":false,"image_name":"tile_0125","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"15":{"object_name":"weapon","is_collection":false,"image_name":"tile_0126","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"16":{"object_name":"weapon","is_collection":false,"image_name":"tile_0127","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"17":{"object_name":"weapon","is_collection":false,"image_name":"tile_0128","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"18":{"object_name":"weapon","is_collection":false,"image_name":"tile_0129","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"19":{"object_name":"weapon","is_collection":false,"image_name":"tile_0130","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"20":{"object_name":"weapon","is_collection":false,"image_name":"tile_0131","image_url":"#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/weapon/weapon.go","properties":{"__default_image_name":"tile_0126","weapon:detiled_init_image:detiled_image_url":"","weapon:detiled_init_image:detiled_init_image":"","weapon:weapon_script:power":20}},"25":{"object_name":"player","is_collection":true,"image_name":"new_icon","image_url":"go#sprite","anchor":{"x":0,"y":8},"width":16,"height":16,"go_path":"/example/assets/dungeon/objects/player/player.collection","properties":{"__default_image_name":"tile_0096","go:player_script:atlas":"/example/assets/dungeon/tileset/dungeon/dungeon.tilesource","go:player_script:bool":true,"go:player_script:hash":"set","go:player_script:life":30,"go:player_script:quar":"quat 0.2880148, 0.2880148, 0.6457921, 0.6457921","go:player_script:res_font":"","go:player_script:url":"s","go:player_script:v3":"1.0, 2.0, 3.0","go:player_script:v4":"4.0, 5.0, 6.0, 7.0","player:detiled_init_image:detiled_image_url":"","player:detiled_init_image:detiled_init_image":""}},"26":{"object_name":"fire","is_collection":false,"image_name":"fire","image_url":"null","anchor":{"x":0,"y":0},"width":80,"height":80,"go_path":"/example/assets/dungeon/objects/fire/fire.go","properties":{"__default_image_name":"null"}},"27":{"object_name":"water","is_collection":false,"image_name":"entity","image_url":"null","anchor":{"x":0,"y":0},"width":32,"height":32,"go_path":"/example/assets/dungeon/objects/water/water.go","properties":{"__default_image_name":"null"}}},"dungeon":{}}
--------------------------------------------------------------------------------
/example/generated/maps/dungeon_01/dungeon_01-Group 1-dungeon.tilemap:
--------------------------------------------------------------------------------
1 | tile_set: "/example/assets/dungeon/tileset/dungeon/dungeon.tilesource"
2 | layers {
3 | id: "Tile Layer 2"
4 | z: 1.0E-4
5 | is_visible: 1
6 | cell {
7 | x: 10
8 | y: 6
9 | tile: 110
10 | h_flip: 0
11 | v_flip: 0
12 | rotate90: 0
13 | }
14 | cell {
15 | x: 16
16 | y: 7
17 | tile: 98
18 | h_flip: 0
19 | v_flip: 0
20 | rotate90: 0
21 | }
22 | cell {
23 | x: 17
24 | y: 7
25 | tile: 91
26 | h_flip: 0
27 | v_flip: 0
28 | rotate90: 0
29 | }
30 | cell {
31 | x: 14
32 | y: 9
33 | tile: 72
34 | h_flip: 0
35 | v_flip: 0
36 | rotate90: 0
37 | }
38 | cell {
39 | x: 15
40 | y: 9
41 | tile: 63
42 | h_flip: 0
43 | v_flip: 0
44 | rotate90: 0
45 | }
46 | cell {
47 | x: 16
48 | y: 9
49 | tile: 63
50 | h_flip: 0
51 | v_flip: 0
52 | rotate90: 0
53 | }
54 | }
55 | layers {
56 | id: "Tile Layer 3"
57 | z: 1.00009995E-4
58 | is_visible: 1
59 | cell {
60 | x: 13
61 | y: 4
62 | tile: 76
63 | h_flip: 0
64 | v_flip: 0
65 | rotate90: 0
66 | }
67 | cell {
68 | x: 14
69 | y: 4
70 | tile: 77
71 | h_flip: 0
72 | v_flip: 0
73 | rotate90: 0
74 | }
75 | cell {
76 | x: 15
77 | y: 4
78 | tile: 78
79 | h_flip: 0
80 | v_flip: 0
81 | rotate90: 0
82 | }
83 | cell {
84 | x: 17
85 | y: 4
86 | tile: 76
87 | h_flip: 0
88 | v_flip: 0
89 | rotate90: 0
90 | }
91 | cell {
92 | x: 18
93 | y: 4
94 | tile: 77
95 | h_flip: 0
96 | v_flip: 0
97 | rotate90: 0
98 | }
99 | cell {
100 | x: 19
101 | y: 4
102 | tile: 78
103 | h_flip: 0
104 | v_flip: 0
105 | rotate90: 0
106 | }
107 | cell {
108 | x: 21
109 | y: 4
110 | tile: 76
111 | h_flip: 0
112 | v_flip: 0
113 | rotate90: 0
114 | }
115 | cell {
116 | x: 22
117 | y: 4
118 | tile: 77
119 | h_flip: 0
120 | v_flip: 0
121 | rotate90: 0
122 | }
123 | cell {
124 | x: 23
125 | y: 4
126 | tile: 78
127 | h_flip: 0
128 | v_flip: 0
129 | rotate90: 0
130 | }
131 | }
132 | material: "/builtins/materials/tile_map.material"
133 | blend_mode: BLEND_MODE_ALPHA
134 |
--------------------------------------------------------------------------------
/example/generated/maps/dungeon_01/dungeon_01.collection:
--------------------------------------------------------------------------------
1 | name: "dungeon_01"
2 | scale_along_z: 0
3 | embedded_instances {
4 | id: "tilemaps"
5 | children: "Group 1"
6 | data: "components {\n"
7 | " id: \"dungeon_01-dungeon\"\n"
8 | " component: \"/example/generated/maps/dungeon_01/dungeon_01-dungeon.tilemap\"\n"
9 | " position {\n"
10 | " x: 0.0\n"
11 | " y: 0.0\n"
12 | " z: 0.0\n"
13 | " }\n"
14 | " rotation {\n"
15 | " x: 0.0\n"
16 | " y: 0.0\n"
17 | " z: 0.0\n"
18 | " w: 1.0\n"
19 | " }\n"
20 | "}\n"
21 | ""
22 | position {
23 | x: 0.0
24 | y: 0.0
25 | z: 0.0
26 | }
27 | rotation {
28 | x: 0.0
29 | y: 0.0
30 | z: 0.0
31 | w: 1.0
32 | }
33 | scale3 {
34 | x: 1.0
35 | y: 1.0
36 | z: 1.0
37 | }
38 | }
39 | embedded_instances {
40 | id: "Group 1"
41 | data: "components {\n"
42 | " id: \"dungeon_01-Group 1-dungeon\"\n"
43 | " component: \"/example/generated/maps/dungeon_01/dungeon_01-Group 1-dungeon.tilemap\"\n"
44 | " position {\n"
45 | " x: 0.0\n"
46 | " y: 0.0\n"
47 | " z: 0.0\n"
48 | " }\n"
49 | " rotation {\n"
50 | " x: 0.0\n"
51 | " y: 0.0\n"
52 | " z: 0.0\n"
53 | " w: 1.0\n"
54 | " }\n"
55 | "}\n"
56 | ""
57 | position {
58 | x: 0.0
59 | y: 0.0
60 | z: 0.0
61 | }
62 | rotation {
63 | x: 0.0
64 | y: 0.0
65 | z: 0.0
66 | w: 1.0
67 | }
68 | scale3 {
69 | x: 1.0
70 | y: 1.0
71 | z: 1.0
72 | }
73 | }
74 | collection_instances {
75 | id: "object_layer_1"
76 | collection: "/example/generated/maps/dungeon_01/dungeon_01_object_layer_1.collection"
77 | position {
78 | x: 0.0
79 | y: 0.0
80 | z: 0.0001
81 | }
82 | rotation {
83 | x: 0.0
84 | y: 0.0
85 | z: 0.0
86 | w: 0.0
87 | }
88 | scale3 {
89 | x: 0.0
90 | y: 0.0
91 | z: 0.0
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/example/generated/maps/dungeon_01/dungeon_01_object_layer_1.collection:
--------------------------------------------------------------------------------
1 | name: "dungeon_01_object_layer_1"
2 | instances {
3 | id: "weapon_2"
4 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
5 | position {
6 | x: 329.19
7 | y: 175.4
8 | z: 0.0
9 | }
10 | rotation {
11 | x: 0.0
12 | y: 0.0
13 | z: 0.0
14 | w: 1.0
15 | }
16 | component_properties {
17 | id: "detiled_init_image"
18 | properties {
19 | id: "detiled_init_image"
20 | value: "tile_0104"
21 | type: PROPERTY_TYPE_HASH
22 | }
23 | properties {
24 | id: "detiled_image_url"
25 | value: "#sprite"
26 | type: PROPERTY_TYPE_URL
27 | }
28 | }
29 | scale3 {
30 | x: 1.0
31 | y: 1.0
32 | z: 1.0
33 | }
34 | }
35 | instances {
36 | id: "weapon_7"
37 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
38 | position {
39 | x: 360.958
40 | y: 176.988
41 | z: 0.0
42 | }
43 | rotation {
44 | x: 0.0
45 | y: 0.0
46 | z: 0.0
47 | w: 1.0
48 | }
49 | component_properties {
50 | id: "detiled_init_image"
51 | properties {
52 | id: "detiled_init_image"
53 | value: "tile_0117"
54 | type: PROPERTY_TYPE_HASH
55 | }
56 | properties {
57 | id: "detiled_image_url"
58 | value: "#sprite"
59 | type: PROPERTY_TYPE_URL
60 | }
61 | }
62 | scale3 {
63 | x: 1.0
64 | y: 1.0
65 | z: 1.0
66 | }
67 | }
68 | instances {
69 | id: "weapon_8"
70 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
71 | position {
72 | x: 377.239
73 | y: 177.385
74 | z: 0.0
75 | }
76 | rotation {
77 | x: 0.0
78 | y: 0.0
79 | z: 0.0
80 | w: 1.0
81 | }
82 | component_properties {
83 | id: "detiled_init_image"
84 | properties {
85 | id: "detiled_init_image"
86 | value: "tile_0119"
87 | type: PROPERTY_TYPE_HASH
88 | }
89 | properties {
90 | id: "detiled_image_url"
91 | value: "#sprite"
92 | type: PROPERTY_TYPE_URL
93 | }
94 | }
95 | scale3 {
96 | x: 1.0
97 | y: 1.0
98 | z: 1.0
99 | }
100 | }
101 | instances {
102 | id: "weapon_13"
103 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
104 | position {
105 | x: 106.58155
106 | y: 142.292
107 | z: 0.0
108 | }
109 | rotation {
110 | x: 0.0
111 | y: 0.0
112 | z: 0.0
113 | w: 1.0
114 | }
115 | component_properties {
116 | id: "detiled_init_image"
117 | properties {
118 | id: "detiled_init_image"
119 | value: "tile_0106"
120 | type: PROPERTY_TYPE_HASH
121 | }
122 | properties {
123 | id: "detiled_image_url"
124 | value: "#sprite"
125 | type: PROPERTY_TYPE_URL
126 | }
127 | }
128 | scale3 {
129 | x: 3.5953937
130 | y: 5.0644813
131 | z: 1.0
132 | }
133 | }
134 | instances {
135 | id: "weapon_14"
136 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
137 | position {
138 | x: 37.805874
139 | y: 262.94458
140 | z: 0.0
141 | }
142 | rotation {
143 | x: 0.0
144 | y: 0.0
145 | z: -0.87105954
146 | w: 0.49117744
147 | }
148 | component_properties {
149 | id: "weapon_script"
150 | properties {
151 | id: "power"
152 | value: "2000.0"
153 | type: PROPERTY_TYPE_NUMBER
154 | }
155 | }
156 | component_properties {
157 | id: "detiled_init_image"
158 | properties {
159 | id: "detiled_init_image"
160 | value: "tile_0106"
161 | type: PROPERTY_TYPE_HASH
162 | }
163 | properties {
164 | id: "detiled_image_url"
165 | value: "#sprite"
166 | type: PROPERTY_TYPE_URL
167 | }
168 | }
169 | scale3 {
170 | x: 3.5953937
171 | y: 5.0644813
172 | z: 1.0
173 | }
174 | }
175 | instances {
176 | id: "weapon_15"
177 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
178 | position {
179 | x: 172.37506
180 | y: 268.0982
181 | z: 0.0
182 | }
183 | rotation {
184 | x: 0.0
185 | y: 0.0
186 | z: -0.89005375
187 | w: -0.4558556
188 | }
189 | component_properties {
190 | id: "detiled_init_image"
191 | properties {
192 | id: "detiled_init_image"
193 | value: "tile_0106"
194 | type: PROPERTY_TYPE_HASH
195 | }
196 | properties {
197 | id: "detiled_image_url"
198 | value: "#sprite"
199 | type: PROPERTY_TYPE_URL
200 | }
201 | }
202 | scale3 {
203 | x: 3.5953937
204 | y: 5.0644813
205 | z: 1.0
206 | }
207 | }
208 | instances {
209 | id: "weapon_16"
210 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
211 | position {
212 | x: 172.37506
213 | y: 268.0982
214 | z: 0.0
215 | }
216 | rotation {
217 | x: 0.0
218 | y: 0.0
219 | z: -0.89005375
220 | w: -0.4558556
221 | }
222 | component_properties {
223 | id: "detiled_init_image"
224 | properties {
225 | id: "detiled_init_image"
226 | value: "tile_0106"
227 | type: PROPERTY_TYPE_HASH
228 | }
229 | properties {
230 | id: "detiled_image_url"
231 | value: "#sprite"
232 | type: PROPERTY_TYPE_URL
233 | }
234 | }
235 | scale3 {
236 | x: 3.5953937
237 | y: 5.0644813
238 | z: 1.0
239 | }
240 | }
241 | instances {
242 | id: "weapon_18"
243 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
244 | position {
245 | x: 304.941
246 | y: 88.706
247 | z: 0.0
248 | }
249 | rotation {
250 | x: 0.0
251 | y: 0.0
252 | z: 0.0
253 | w: 1.0
254 | }
255 | component_properties {
256 | id: "detiled_init_image"
257 | properties {
258 | id: "detiled_init_image"
259 | value: "tile_0126"
260 | type: PROPERTY_TYPE_HASH
261 | }
262 | properties {
263 | id: "detiled_image_url"
264 | value: "#sprite"
265 | type: PROPERTY_TYPE_URL
266 | }
267 | }
268 | scale3 {
269 | x: 1.0
270 | y: 1.0
271 | z: 1.0
272 | }
273 | }
274 | instances {
275 | id: "weapon_19"
276 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
277 | position {
278 | x: 374.815
279 | y: 92.124
280 | z: 0.0
281 | }
282 | rotation {
283 | x: 0.0
284 | y: 0.0
285 | z: 0.0
286 | w: 1.0
287 | }
288 | component_properties {
289 | id: "detiled_init_image"
290 | properties {
291 | id: "detiled_init_image"
292 | value: "tile_0127"
293 | type: PROPERTY_TYPE_HASH
294 | }
295 | properties {
296 | id: "detiled_image_url"
297 | value: "#sprite"
298 | type: PROPERTY_TYPE_URL
299 | }
300 | }
301 | scale3 {
302 | x: 1.0
303 | y: 1.0
304 | z: 1.0
305 | }
306 | }
307 | instances {
308 | id: "weapon_20"
309 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
310 | position {
311 | x: 284.434
312 | y: 38.579
313 | z: 0.0
314 | }
315 | rotation {
316 | x: 0.0
317 | y: 0.0
318 | z: 0.0
319 | w: 1.0
320 | }
321 | component_properties {
322 | id: "detiled_init_image"
323 | properties {
324 | id: "detiled_init_image"
325 | value: "tile_0127"
326 | type: PROPERTY_TYPE_HASH
327 | }
328 | properties {
329 | id: "detiled_image_url"
330 | value: "#sprite"
331 | type: PROPERTY_TYPE_URL
332 | }
333 | }
334 | scale3 {
335 | x: 1.0
336 | y: 1.0
337 | z: 1.0
338 | }
339 | }
340 | instances {
341 | id: "weapon_21"
342 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
343 | position {
344 | x: 339.498
345 | y: 35.541
346 | z: 0.0
347 | }
348 | rotation {
349 | x: 0.0
350 | y: 0.0
351 | z: 0.0
352 | w: 1.0
353 | }
354 | component_properties {
355 | id: "detiled_init_image"
356 | properties {
357 | id: "detiled_init_image"
358 | value: "tile_0127"
359 | type: PROPERTY_TYPE_HASH
360 | }
361 | properties {
362 | id: "detiled_image_url"
363 | value: "#sprite"
364 | type: PROPERTY_TYPE_URL
365 | }
366 | }
367 | scale3 {
368 | x: 1.0
369 | y: 1.0
370 | z: 1.0
371 | }
372 | }
373 | instances {
374 | id: "weapon_23"
375 | prototype: "/example/assets/dungeon/objects/weapon/weapon.go"
376 | position {
377 | x: 106.4942
378 | y: 213.98
379 | z: 0.0
380 | }
381 | rotation {
382 | x: 0.0
383 | y: 0.0
384 | z: 0.0
385 | w: 1.0
386 | }
387 | component_properties {
388 | id: "detiled_init_image"
389 | properties {
390 | id: "detiled_init_image"
391 | value: "tile_0117"
392 | type: PROPERTY_TYPE_HASH
393 | }
394 | properties {
395 | id: "detiled_image_url"
396 | value: "#sprite"
397 | type: PROPERTY_TYPE_URL
398 | }
399 | }
400 | scale3 {
401 | x: 1.0
402 | y: 1.0
403 | z: 1.0
404 | }
405 | }
406 | instances {
407 | id: "fire_26"
408 | prototype: "/example/assets/dungeon/objects/fire/fire.go"
409 | position {
410 | x: 161.272
411 | y: 35.3
412 | z: 0.0
413 | }
414 | rotation {
415 | x: 0.0
416 | y: 0.0
417 | z: 0.0
418 | w: 1.0
419 | }
420 | scale3 {
421 | x: 0.4
422 | y: 0.4
423 | z: 1.0
424 | }
425 | }
426 | instances {
427 | id: "fire_27"
428 | prototype: "/example/assets/dungeon/objects/fire/fire.go"
429 | position {
430 | x: 191.698
431 | y: 35.3
432 | z: 0.0
433 | }
434 | rotation {
435 | x: 0.0
436 | y: 0.0
437 | z: 0.0
438 | w: 1.0
439 | }
440 | scale3 {
441 | x: 0.4
442 | y: 0.4
443 | z: 1.0
444 | }
445 | }
446 | instances {
447 | id: "water_31"
448 | prototype: "/example/assets/dungeon/objects/water/water.go"
449 | position {
450 | x: 288.153
451 | y: 143.634
452 | z: 0.0
453 | }
454 | rotation {
455 | x: 0.0
456 | y: 0.0
457 | z: 0.0
458 | w: 1.0
459 | }
460 | scale3 {
461 | x: 1.0
462 | y: 1.0
463 | z: 1.0
464 | }
465 | }
466 | collection_instances {
467 | id: "player_6"
468 | collection: "/example/assets/dungeon/objects/player/player.collection"
469 | position {
470 | x: 343.486
471 | y: 175.4
472 | z: 0.0
473 | }
474 | rotation {
475 | x: 0.0
476 | y: 0.0
477 | z: 0.0
478 | w: 1.0
479 | }
480 | instance_properties {
481 | id: "player"
482 | properties {
483 | id: "detiled_init_image"
484 | properties {
485 | id: "detiled_init_image"
486 | value: "tile_0097"
487 | type: PROPERTY_TYPE_HASH
488 | }
489 | properties {
490 | id: "detiled_image_url"
491 | value: "go#sprite"
492 | type: PROPERTY_TYPE_URL
493 | }
494 | }
495 | }
496 | scale3 {
497 | x: 1.0
498 | y: 1.0
499 | z: 1.0
500 | }
501 | }
502 | collection_instances {
503 | id: "player_9"
504 | collection: "/example/assets/dungeon/objects/player/player.collection"
505 | position {
506 | x: 151.42429
507 | y: 84.386215
508 | z: 0.0
509 | }
510 | rotation {
511 | x: 0.0
512 | y: 0.0
513 | z: -0.30100957
514 | w: 0.95362115
515 | }
516 | instance_properties {
517 | id: "player"
518 | properties {
519 | id: "detiled_init_image"
520 | properties {
521 | id: "detiled_init_image"
522 | value: "tile_0096"
523 | type: PROPERTY_TYPE_HASH
524 | }
525 | properties {
526 | id: "detiled_image_url"
527 | value: "go#sprite"
528 | type: PROPERTY_TYPE_URL
529 | }
530 | }
531 | }
532 | scale3 {
533 | x: 1.0
534 | y: 1.0
535 | z: 1.0
536 | }
537 | }
538 | collection_instances {
539 | id: "player_10"
540 | collection: "/example/assets/dungeon/objects/player/player.collection"
541 | position {
542 | x: 150.71483
543 | y: 123.127365
544 | z: 0.0
545 | }
546 | rotation {
547 | x: 0.0
548 | y: 0.0
549 | z: -0.9350857
550 | w: 0.35442162
551 | }
552 | instance_properties {
553 | id: "player"
554 | properties {
555 | id: "detiled_init_image"
556 | properties {
557 | id: "detiled_init_image"
558 | value: "tile_0096"
559 | type: PROPERTY_TYPE_HASH
560 | }
561 | properties {
562 | id: "detiled_image_url"
563 | value: "go#sprite"
564 | type: PROPERTY_TYPE_URL
565 | }
566 | }
567 | }
568 | scale3 {
569 | x: 1.0
570 | y: 1.0
571 | z: 1.0
572 | }
573 | }
574 | collection_instances {
575 | id: "player_11"
576 | collection: "/example/assets/dungeon/objects/player/player.collection"
577 | position {
578 | x: 186.71814
579 | y: 121.93485
580 | z: 0.0
581 | }
582 | rotation {
583 | x: 0.0
584 | y: 0.0
585 | z: -0.9238795
586 | w: -0.38268343
587 | }
588 | instance_properties {
589 | id: "player"
590 | properties {
591 | id: "detiled_init_image"
592 | properties {
593 | id: "detiled_init_image"
594 | value: "tile_0096"
595 | type: PROPERTY_TYPE_HASH
596 | }
597 | properties {
598 | id: "detiled_image_url"
599 | value: "go#sprite"
600 | type: PROPERTY_TYPE_URL
601 | }
602 | }
603 | }
604 | scale3 {
605 | x: 1.0
606 | y: 1.0
607 | z: 1.0
608 | }
609 | }
610 | collection_instances {
611 | id: "player_12"
612 | collection: "/example/assets/dungeon/objects/player/player.collection"
613 | position {
614 | x: 186.33928
615 | y: 86.324936
616 | z: 0.0
617 | }
618 | rotation {
619 | x: 0.0
620 | y: 0.0
621 | z: -0.38695237
622 | w: -0.9220997
623 | }
624 | instance_properties {
625 | id: "player"
626 | properties {
627 | id: "detiled_init_image"
628 | properties {
629 | id: "detiled_init_image"
630 | value: "tile_0096"
631 | type: PROPERTY_TYPE_HASH
632 | }
633 | properties {
634 | id: "detiled_image_url"
635 | value: "go#sprite"
636 | type: PROPERTY_TYPE_URL
637 | }
638 | }
639 | }
640 | scale3 {
641 | x: 1.0
642 | y: 1.0
643 | z: 1.0
644 | }
645 | }
646 | collection_instances {
647 | id: "player_25"
648 | collection: "/example/assets/dungeon/objects/player/player.collection"
649 | position {
650 | x: 76.08853
651 | y: 21.629654
652 | z: 0.0
653 | }
654 | rotation {
655 | x: 0.0
656 | y: 0.0
657 | z: -0.0041904883
658 | w: 0.99999124
659 | }
660 | instance_properties {
661 | id: "player"
662 | properties {
663 | id: "detiled_init_image"
664 | properties {
665 | id: "detiled_init_image"
666 | value: "tile_0096"
667 | type: PROPERTY_TYPE_HASH
668 | }
669 | properties {
670 | id: "detiled_image_url"
671 | value: "go#sprite"
672 | type: PROPERTY_TYPE_URL
673 | }
674 | }
675 | }
676 | instance_properties {
677 | id: "go"
678 | properties {
679 | id: "player_script"
680 | properties {
681 | id: "hash"
682 | value: "osoe"
683 | type: PROPERTY_TYPE_HASH
684 | }
685 | }
686 | }
687 | scale3 {
688 | x: 5.0463815
689 | y: 6.40425
690 | z: 1.0
691 | }
692 | }
693 | scale_along_z: 0
694 |
--------------------------------------------------------------------------------
/example/generated/maps/dungeon_01/spawner_dungeon_01.collection:
--------------------------------------------------------------------------------
1 | name: "spawner_dungeon_01"
2 | scale_along_z: 0
3 | instances {
4 | id: "spawner_assets-dungeon-objects"
5 | prototype: "/example/generated/spawners/spawner_assets-dungeon-objects.go"
6 | position {
7 | x: 0.0
8 | y: 0.0
9 | z: 0.0
10 | }
11 | rotation {
12 | x: 0.0
13 | y: 0.0
14 | z: 0.0
15 | w: 1.0
16 | }
17 | scale3 {
18 | x: 1.0
19 | y: 1.0
20 | z: 1.0
21 | }
22 | }
--------------------------------------------------------------------------------
/example/generated/spawners/spawner_assets-dungeon-objects.go:
--------------------------------------------------------------------------------
1 | embedded_components {
2 | id: "fire"
3 | type: "factory"
4 | data: "prototype: \"/example/assets/dungeon/objects/fire/fire.go\"\n"
5 | "load_dynamically: false\n"
6 | ""
7 | position {
8 | x: 0.0
9 | y: 0.0
10 | z: 0.0
11 | }
12 | rotation {
13 | x: 0.0
14 | y: 0.0
15 | z: 0.0
16 | w: 1.0
17 | }
18 | }
19 | embedded_components {
20 | id: "player"
21 | type: "collectionfactory"
22 | data: "prototype: \"/example/assets/dungeon/objects/player/player.collection\"\n"
23 | "load_dynamically: false\n"
24 | ""
25 | position {
26 | x: 0.0
27 | y: 0.0
28 | z: 0.0
29 | }
30 | rotation {
31 | x: 0.0
32 | y: 0.0
33 | z: 0.0
34 | w: 1.0
35 | }
36 | }
37 | embedded_components {
38 | id: "water"
39 | type: "factory"
40 | data: "prototype: \"/example/assets/dungeon/objects/water/water.go\"\n"
41 | "load_dynamically: false\n"
42 | ""
43 | position {
44 | x: 0.0
45 | y: 0.0
46 | z: 0.0
47 | }
48 | rotation {
49 | x: 0.0
50 | y: 0.0
51 | z: 0.0
52 | w: 1.0
53 | }
54 | }
55 | embedded_components {
56 | id: "weapon"
57 | type: "factory"
58 | data: "prototype: \"/example/assets/dungeon/objects/weapon/weapon.go\"\n"
59 | "load_dynamically: false\n"
60 | ""
61 | position {
62 | x: 0.0
63 | y: 0.0
64 | z: 0.0
65 | }
66 | rotation {
67 | x: 0.0
68 | y: 0.0
69 | z: 0.0
70 | w: 1.0
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-fire-fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-fire-fire.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-new_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-new_icon.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0096.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0096.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0097.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0097.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0098.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0098.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0099.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0099.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-player-tile_0100.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-water-water.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-water-water.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0103.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0103.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0104.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0104.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0105.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0105.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0106.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0106.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0107.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0107.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0117.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0117.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0118.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0118.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0119.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0119.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0125.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0126.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0126.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0127.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0127.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0128.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0129.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0129.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0130.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0130.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0131.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-objects/assets-dungeon-objects-weapon-tile_0131.png
--------------------------------------------------------------------------------
/example_tiled_export/images/assets-dungeon-tileset/dungeon_tilemap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/example_tiled_export/images/assets-dungeon-tileset/dungeon_tilemap.png
--------------------------------------------------------------------------------
/example_tiled_export/tilesets/assets-dungeon-objects.tsx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
457 |
458 |
459 |
460 |
461 |
--------------------------------------------------------------------------------
/example_tiled_export/tilesets/assets-dungeon-tileset-dungeon.tsx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/export_from_tiled.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | node detiled export ./example_tiled_export/ ./tiled_example_maps/ ./example/generated
4 |
--------------------------------------------------------------------------------
/export_to_tiled.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | node detiled generate_tilesets ./example/assets/ ./example_tiled_export
4 |
--------------------------------------------------------------------------------
/game.project:
--------------------------------------------------------------------------------
1 | [bootstrap]
2 | main_collection = /example/example.collectionc
3 |
4 | [script]
5 | shared_state = 1
6 |
7 | [display]
8 | width = 960
9 | height = 640
10 |
11 | [android]
12 | input_method = HiddenInputField
13 |
14 | [project]
15 | title = Detiled
16 | version = 1.0.0
17 | publisher = Insality
18 | developer = Insality
19 |
20 | [library]
21 | include_dirs = detiled
22 |
23 | [graphics]
24 | default_texture_min_filter = nearest
25 | default_texture_mag_filter = nearest
26 |
--------------------------------------------------------------------------------
/input/game.input_binding:
--------------------------------------------------------------------------------
1 | mouse_trigger {
2 | input: MOUSE_BUTTON_1
3 | action: "touch"
4 | }
5 |
--------------------------------------------------------------------------------
/media/detiled_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/media/detiled_logo.png
--------------------------------------------------------------------------------
/media/detiled_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insality/detiled_nodejs/48e770948ecf760961057bb4d8032c435ff2810e/media/detiled_thumb.png
--------------------------------------------------------------------------------
/notes.md:
--------------------------------------------------------------------------------
1 | Physics is can't be scaled non uniformly (it will be scaled my minimal object scale, so it's not possible to scale box physics to box with different sides)
2 |
3 |
4 | Current export from tiled used defoldcollection Tiled plugin (it should be enabled in Tiled app). So it will generate collections
5 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "detiled",
3 | "version": "0.1.3",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "detiled",
9 | "version": "0.1.3",
10 | "license": "MIT",
11 | "dependencies": {
12 | "defold-parser": "^0.1.2",
13 | "fast-xml-parser": "^4.0.10",
14 | "image-size": "^1.0.2",
15 | "quaternion": "^1.4.0",
16 | "rimraf": "^3.0.2"
17 | },
18 | "bin": {
19 | "detiled": "detiled.js"
20 | },
21 | "funding": {
22 | "url": "https://github.com/sponsors/insality"
23 | }
24 | },
25 | "node_modules/balanced-match": {
26 | "version": "1.0.2",
27 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
28 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
29 | },
30 | "node_modules/brace-expansion": {
31 | "version": "1.1.11",
32 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
33 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
34 | "dependencies": {
35 | "balanced-match": "^1.0.0",
36 | "concat-map": "0.0.1"
37 | }
38 | },
39 | "node_modules/concat-map": {
40 | "version": "0.0.1",
41 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
42 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
43 | },
44 | "node_modules/defold-parser": {
45 | "version": "0.1.2",
46 | "resolved": "https://registry.npmjs.org/defold-parser/-/defold-parser-0.1.2.tgz",
47 | "integrity": "sha512-0W0zXefrT88WycFWFLEnoFvfd5y8ORdMU8r7Q1lSPoS/bbaPr1ny1mmJ7Fx/eShq9Y3DI/BfO9QRdwCu79+jdQ==",
48 | "funding": {
49 | "url": "https://github.com/sponsors/insality"
50 | }
51 | },
52 | "node_modules/fast-xml-parser": {
53 | "version": "4.0.11",
54 | "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz",
55 | "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==",
56 | "dependencies": {
57 | "strnum": "^1.0.5"
58 | },
59 | "bin": {
60 | "fxparser": "src/cli/cli.js"
61 | },
62 | "funding": {
63 | "type": "paypal",
64 | "url": "https://paypal.me/naturalintelligence"
65 | }
66 | },
67 | "node_modules/fs.realpath": {
68 | "version": "1.0.0",
69 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
70 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
71 | },
72 | "node_modules/glob": {
73 | "version": "7.2.3",
74 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
75 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
76 | "dependencies": {
77 | "fs.realpath": "^1.0.0",
78 | "inflight": "^1.0.4",
79 | "inherits": "2",
80 | "minimatch": "^3.1.1",
81 | "once": "^1.3.0",
82 | "path-is-absolute": "^1.0.0"
83 | },
84 | "engines": {
85 | "node": "*"
86 | },
87 | "funding": {
88 | "url": "https://github.com/sponsors/isaacs"
89 | }
90 | },
91 | "node_modules/image-size": {
92 | "version": "1.0.2",
93 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
94 | "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
95 | "dependencies": {
96 | "queue": "6.0.2"
97 | },
98 | "bin": {
99 | "image-size": "bin/image-size.js"
100 | },
101 | "engines": {
102 | "node": ">=14.0.0"
103 | }
104 | },
105 | "node_modules/inflight": {
106 | "version": "1.0.6",
107 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
108 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
109 | "dependencies": {
110 | "once": "^1.3.0",
111 | "wrappy": "1"
112 | }
113 | },
114 | "node_modules/inherits": {
115 | "version": "2.0.4",
116 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
117 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
118 | },
119 | "node_modules/minimatch": {
120 | "version": "3.1.2",
121 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
122 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
123 | "dependencies": {
124 | "brace-expansion": "^1.1.7"
125 | },
126 | "engines": {
127 | "node": "*"
128 | }
129 | },
130 | "node_modules/once": {
131 | "version": "1.4.0",
132 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
133 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
134 | "dependencies": {
135 | "wrappy": "1"
136 | }
137 | },
138 | "node_modules/path-is-absolute": {
139 | "version": "1.0.1",
140 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
141 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
142 | "engines": {
143 | "node": ">=0.10.0"
144 | }
145 | },
146 | "node_modules/quaternion": {
147 | "version": "1.4.0",
148 | "resolved": "https://registry.npmjs.org/quaternion/-/quaternion-1.4.0.tgz",
149 | "integrity": "sha512-SIUOOoFbJOiu8vftqHsT7W1eH8YEDTpup00/Yj67Rx0CYq4bslH+T+bkt0Z7idQqk17U9aYfDCp4l5v7t/9Sxg==",
150 | "engines": {
151 | "node": "*"
152 | }
153 | },
154 | "node_modules/queue": {
155 | "version": "6.0.2",
156 | "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
157 | "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
158 | "dependencies": {
159 | "inherits": "~2.0.3"
160 | }
161 | },
162 | "node_modules/rimraf": {
163 | "version": "3.0.2",
164 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
165 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
166 | "dependencies": {
167 | "glob": "^7.1.3"
168 | },
169 | "bin": {
170 | "rimraf": "bin.js"
171 | },
172 | "funding": {
173 | "url": "https://github.com/sponsors/isaacs"
174 | }
175 | },
176 | "node_modules/strnum": {
177 | "version": "1.0.5",
178 | "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
179 | "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
180 | },
181 | "node_modules/wrappy": {
182 | "version": "1.0.2",
183 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
184 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
185 | }
186 | },
187 | "dependencies": {
188 | "balanced-match": {
189 | "version": "1.0.2",
190 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
191 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
192 | },
193 | "brace-expansion": {
194 | "version": "1.1.11",
195 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
196 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
197 | "requires": {
198 | "balanced-match": "^1.0.0",
199 | "concat-map": "0.0.1"
200 | }
201 | },
202 | "concat-map": {
203 | "version": "0.0.1",
204 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
205 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
206 | },
207 | "defold-parser": {
208 | "version": "0.1.2",
209 | "resolved": "https://registry.npmjs.org/defold-parser/-/defold-parser-0.1.2.tgz",
210 | "integrity": "sha512-0W0zXefrT88WycFWFLEnoFvfd5y8ORdMU8r7Q1lSPoS/bbaPr1ny1mmJ7Fx/eShq9Y3DI/BfO9QRdwCu79+jdQ=="
211 | },
212 | "fast-xml-parser": {
213 | "version": "4.0.11",
214 | "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz",
215 | "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==",
216 | "requires": {
217 | "strnum": "^1.0.5"
218 | }
219 | },
220 | "fs.realpath": {
221 | "version": "1.0.0",
222 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
223 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
224 | },
225 | "glob": {
226 | "version": "7.2.3",
227 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
228 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
229 | "requires": {
230 | "fs.realpath": "^1.0.0",
231 | "inflight": "^1.0.4",
232 | "inherits": "2",
233 | "minimatch": "^3.1.1",
234 | "once": "^1.3.0",
235 | "path-is-absolute": "^1.0.0"
236 | }
237 | },
238 | "image-size": {
239 | "version": "1.0.2",
240 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
241 | "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
242 | "requires": {
243 | "queue": "6.0.2"
244 | }
245 | },
246 | "inflight": {
247 | "version": "1.0.6",
248 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
249 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
250 | "requires": {
251 | "once": "^1.3.0",
252 | "wrappy": "1"
253 | }
254 | },
255 | "inherits": {
256 | "version": "2.0.4",
257 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
258 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
259 | },
260 | "minimatch": {
261 | "version": "3.1.2",
262 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
263 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
264 | "requires": {
265 | "brace-expansion": "^1.1.7"
266 | }
267 | },
268 | "once": {
269 | "version": "1.4.0",
270 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
271 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
272 | "requires": {
273 | "wrappy": "1"
274 | }
275 | },
276 | "path-is-absolute": {
277 | "version": "1.0.1",
278 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
279 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
280 | },
281 | "quaternion": {
282 | "version": "1.4.0",
283 | "resolved": "https://registry.npmjs.org/quaternion/-/quaternion-1.4.0.tgz",
284 | "integrity": "sha512-SIUOOoFbJOiu8vftqHsT7W1eH8YEDTpup00/Yj67Rx0CYq4bslH+T+bkt0Z7idQqk17U9aYfDCp4l5v7t/9Sxg=="
285 | },
286 | "queue": {
287 | "version": "6.0.2",
288 | "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
289 | "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
290 | "requires": {
291 | "inherits": "~2.0.3"
292 | }
293 | },
294 | "rimraf": {
295 | "version": "3.0.2",
296 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
297 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
298 | "requires": {
299 | "glob": "^7.1.3"
300 | }
301 | },
302 | "strnum": {
303 | "version": "1.0.5",
304 | "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
305 | "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
306 | },
307 | "wrappy": {
308 | "version": "1.0.2",
309 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
310 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
311 | }
312 | }
313 | }
314 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "defold-parser": "^0.1.2",
4 | "fast-xml-parser": "^4.0.10",
5 | "image-size": "^1.0.2",
6 | "quaternion": "^1.4.0",
7 | "rimraf": "^3.0.2"
8 | },
9 | "name": "detiled",
10 | "description": "Generate tilesets from Defold and Defold collections from Tiled maps",
11 | "version": "0.1.3",
12 | "main": "detiled.js",
13 | "bin": "detiled.js",
14 | "scripts": {
15 | "test": "echo \"Error: no test specified\" && exit 1"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/Insality/detiled.git"
20 | },
21 | "keywords": [
22 | "defold",
23 | "tiled",
24 | "export",
25 | "import",
26 | "workflow",
27 | "processing",
28 | "assets"
29 | ],
30 | "author": "Insality",
31 | "license": "MIT",
32 | "bugs": {
33 | "url": "https://github.com/Insality/detiled/issues"
34 | },
35 | "funding": {
36 | "url": "https://github.com/sponsors/insality"
37 | },
38 | "homepage": "https://github.com/Insality/detiled#readme"
39 | }
40 |
--------------------------------------------------------------------------------
/tiled_example_maps/dungeon_01.tiled-project:
--------------------------------------------------------------------------------
1 | {
2 | "automappingRulesFile": "",
3 | "commands": [
4 | ],
5 | "extensionsPath": "extensions",
6 | "folders": [
7 | "."
8 | ],
9 | "propertyTypes": [
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/tiled_example_maps/dungeon_01.tmx:
--------------------------------------------------------------------------------
1 |
2 |
125 |
--------------------------------------------------------------------------------