├── .gitignore ├── wrapper.js ├── rollup.config.js ├── package.json ├── LICENSE ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /wrapper.js: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser'; 2 | import registerTiledJSONExternalLoader from './index.js'; 3 | registerTiledJSONExternalLoader(Phaser); 4 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | input: 'wrapper.js', 3 | output: { 4 | file: 'dist/phaser-tiled-json-external-loader.js', 5 | globals: { 6 | phaser: 'Phaser', 7 | }, 8 | format: 'iife', 9 | }, 10 | external: ['phaser'], 11 | }; 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser-tiled-json-external-loader", 3 | "version": "0.1.1", 4 | "description": "A Phaser loader for Tiled JSON tilemaps that supports external tilesets.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "rollup -c" 8 | }, 9 | "author": "Richard Davey ", 10 | "license": "MIT", 11 | "peerDependencies": { 12 | "phaser": ">= 3.16.0" 13 | }, 14 | "devDependencies": { 15 | "rollup": "^1.4.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Richard Davey, Photon Storm Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phaser Tiled JSON External Loader 2 | 3 | `phaser-tiled-json-external-loader` is a Phaser loader that loads [Tiled][] tilemaps exported as JSON. Unlike the built-in loader, external tilemaps are supported. 4 | 5 | [Tiled]: https://www.mapeditor.org/ 6 | 7 | ## Prerequisites 8 | 9 | - Phaser 3.16.3 or higher (I think? I haven't tested much.) 10 | - Tiled 1.1.5 or higher (Again, this isn't terribly well-tested.) 11 | 12 | ## Tileset Format 13 | 14 | Only JSON-formatted tilesets are supported. TMX and other formats are not supported. Make sure to export your tilesets from Tiled as JSON files. 15 | 16 | ## Relative Tileset Paths 17 | 18 | Tilesets paths are saved by Tiled as relative to the tilemap file, and it's assumed that they are similarly relative to each other on your web server. 19 | 20 | What this means is that your webpage should serve the tilemap and tileset files at the same paths relative to each other as when you're editing them. For example, let's say your tilemap is at `/foo/tilemap.json` and uses a tileset at `/foo/bar/tileset.json`. If your tilemap is loaded on the server at `http://example.com/tilemap.json`, then the tileset must be served at `http://example.com/bar/tileset.json`. 21 | 22 | ## Installation and Setup 23 | 24 | ### Via Webpack 25 | 26 | 1. Install the library: 27 | 28 | ```sh 29 | npm install --save phaser-tiled-json-external-loader 30 | ``` 31 | 2. Import and register the loader before initializing your game: 32 | 33 | ```js 34 | import registerTiledJSONExternalLoader from 'phaser-tiled-json-external-loader'; 35 | registerTiledJSONExternalLoader(Phaser); 36 | ``` 37 | 38 | ### Via Bundled JS File 39 | 40 | 1. Download the JS bundle from the [Releases][] tab. 41 | 2. Load the JS bundle in your HTML file: 42 | 43 | ```html 44 | 45 | ``` 46 | 47 | [Releases]: https://github.com/Osmose/phaser-tiled-json-external-loader/releases 48 | 49 | ## Usage 50 | 51 | Use the `tilemapTiledJSONExternal` loader to load your tilemap's JSON: 52 | 53 | ```js 54 | this.load.tilemapTiledJSONExternal('tilemap', 'tilemap.json'); 55 | ``` 56 | 57 | Assuming the paths are set up correctly as described above, you should see your tilemap JSON as well as the tilesets being loaded in the network tab on your browser's devtools. 58 | 59 | ## License & Copyright 60 | 61 | Originally adapted from the Phaser built-in MutliAtlasFile loader. `phaser-tiled-json-external-loader` is licensed under the MIT license. See `LICENSE` for more info. 62 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Richard Davey , Michael Kelly 3 | * @copyright 2019 Photon Storm Ltd. 4 | * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} 5 | */ 6 | 7 | export default function registerTiledJSONExternalLoader(Phaser) { 8 | const FileTypesManager = Phaser.Loader.FileTypesManager; 9 | const GetFastValue = Phaser.Utils.Objects.GetFastValue; 10 | const IsPlainObject = Phaser.Utils.Objects.IsPlainObject; 11 | const JSONFile = Phaser.Loader.FileTypes.JSONFile; 12 | const MultiFile = Phaser.Loader.MultiFile; 13 | 14 | class TiledJSONExternalFile extends MultiFile { 15 | constructor(loader, key, tilemapURL, path, baseURL, tilemapXhrSettings, tilesetXhrSettings) { 16 | if (IsPlainObject(key)) { 17 | const config = key; 18 | 19 | key = GetFastValue(config, 'key'); 20 | tilemapURL = GetFastValue(config, 'url'); 21 | tilemapXhrSettings = GetFastValue(config, 'xhrSettings'); 22 | path = GetFastValue(config, 'path'); 23 | baseURL = GetFastValue(config, 'baseURL'); 24 | tilesetXhrSettings = GetFastValue(config, 'tilesetXhrSettings'); 25 | } 26 | 27 | const tilemapFile = new JSONFile(loader, key, tilemapURL, tilemapXhrSettings); 28 | super(loader, 'tilemapJSON', key, [tilemapFile]); 29 | 30 | this.config.path = path; 31 | this.config.baseURL = baseURL; 32 | this.config.tilesetXhrSettings = tilesetXhrSettings; 33 | } 34 | 35 | onFileComplete(file) { 36 | const index = this.files.indexOf(file); 37 | if (index !== -1) { 38 | this.pending--; 39 | 40 | if (file.type === 'json' && file.data.hasOwnProperty('tilesets')) { 41 | // Inspect the data for the files to now load 42 | const tilesets = file.data.tilesets; 43 | 44 | const config = this.config; 45 | const loader = this.loader; 46 | 47 | const currentBaseURL = loader.baseURL; 48 | const currentPath = loader.path; 49 | const currentPrefix = loader.prefix; 50 | 51 | const baseURL = GetFastValue(config, 'baseURL', currentBaseURL); 52 | const path = GetFastValue(config, 'path', currentPath); 53 | const prefix = GetFastValue(config, 'prefix', currentPrefix); 54 | const tilesetXhrSettings = GetFastValue(config, 'tilesetXhrSettings'); 55 | 56 | loader.setBaseURL(baseURL); 57 | loader.setPath(path); 58 | loader.setPrefix(prefix); 59 | 60 | for (const [index, tileset] of tilesets.entries()) { 61 | if (!tileset.source) { 62 | continue; 63 | } 64 | 65 | // Tileset is relative to the tilemap filename, so we abuse URL to 66 | // get the relative path. 67 | const url = new URL(file.src, 'http://example.com'); 68 | url.pathname += `/../${tileset.source}`; 69 | const tilesetUrl = url.pathname.slice(1); 70 | 71 | const tilesetFile = new JSONFile( 72 | loader, 73 | `_TILESET_${file.key}_${tilesetUrl}`, 74 | tilesetUrl, 75 | tilesetXhrSettings, 76 | ); 77 | tilesetFile.tilesetIndex = index; 78 | this.addToMultiFile(tilesetFile); 79 | loader.addFile(tilesetFile); 80 | } 81 | 82 | // Reset the loader settings 83 | loader.setBaseURL(currentBaseURL); 84 | loader.setPath(currentPath); 85 | loader.setPrefix(currentPrefix); 86 | } 87 | } 88 | } 89 | 90 | addToCache() { 91 | if (this.isReadyToProcess()) { 92 | const tilemapFile = this.files[0]; 93 | for (const file of this.files.slice(1)) { 94 | const index = file.tilesetIndex; 95 | tilemapFile.data.tilesets[index] = { 96 | ...tilemapFile.data.tilesets[index], 97 | ...file.data, 98 | source: undefined, // Avoid throwing in tilemap creator 99 | }; 100 | } 101 | 102 | this.loader.cacheManager.tilemap.add(tilemapFile.key, { 103 | format: Phaser.Tilemaps.Formats.TILED_JSON, 104 | data: tilemapFile.data, 105 | }); 106 | 107 | this.complete = true; 108 | 109 | for (const file of this.files) { 110 | file.pendingDestroy(); 111 | } 112 | } 113 | } 114 | 115 | } 116 | 117 | FileTypesManager.register( 118 | 'tilemapTiledJSONExternal', 119 | function (key, tilemapURL, path, baseURL, tilemapXhrSettings) { 120 | 121 | // Supports an Object file definition in the key argument 122 | // Or an array of objects in the key argument 123 | // Or a single entry where all arguments have been defined 124 | 125 | if (Array.isArray(key)) { 126 | for (var i = 0; i < key.length; i++) { 127 | const multifile = new TiledJSONExternalFile(this, key[i]); 128 | this.addFile(multifile.files); 129 | } 130 | } else { 131 | const multifile = new TiledJSONExternalFile(this, key, tilemapURL, path, baseURL, tilemapXhrSettings); 132 | this.addFile(multifile.files); 133 | } 134 | 135 | return this; 136 | }, 137 | ); 138 | } 139 | --------------------------------------------------------------------------------