├── .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 | [![](media/detiled_logo.png)](https://insality.github.io/detiled/) 3 | [![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality) 4 | 5 | [![npm](https://img.shields.io/npm/v/detiled?label=detiled)](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 | [![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](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 | 8 | 9 | 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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 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 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 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, 12 | 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, 13 | 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, 14 | 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, 15 | 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, 16 | 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, 17 | 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, 18 | 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, 19 | 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, 20 | 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, 21 | 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, 22 | 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, 23 | 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, 24 | 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, 25 | 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, 26 | 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, 27 | 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, 28 | 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, 29 | 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, 30 | 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 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 78 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 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, 80 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 81 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 82 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 83 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 84 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 85 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 86 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 87 | 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, 88 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 89 | 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, 90 | 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, 91 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 92 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 93 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 94 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 95 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 96 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 97 | 98 | 99 | 100 | 101 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 102 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 103 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 104 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 105 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 106 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 107 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 108 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 109 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 110 | 0,0,0,0,0,0,0,0,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, 112 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 113 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 114 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 115 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 116 | 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, 117 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 118 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 119 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 120 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 121 | 122 | 123 | 124 | 125 | --------------------------------------------------------------------------------