I am making my own world editor from a folder of individual tiles that you can place on the so called map. The tile placing works but when I try to save the map the json file map data indicates that the map is empty.
The map and layer are created as blank so you can create your own but after placing tiles they are still undefined and blank and I dont know how to fix the problem
There is a fake tileset i am using for my layer because otherwise the tile placing doesnt work
this is my code
class WorldEditor extends Phaser.Scene {
constructor() {
super("editWorld")
this.tileSize = 48
this.tileIndex = 0
this.tileFolder = 'Assets/Tiles/'
this.tilesPerRow = 37
this.totalTiles = 160
this.tilePicked = false
this.tileset = []
this.dragging = false
}
preload() {
// Load tile images from the folder
for (let i = 0; i < this.totalTiles; i++) {
this.load.image('tile (' + i + ')', this.tileFolder + 'tile (' + i + ').png')
}
}
create() {
const tileWidth = this.tileSize
const tileHeight = this.tileSize
const tilesPerRow = this.tilesPerRow
if(!this.map){
this.map = this.make.tilemap({
tileWidth: this.tileSize,
tileHeight: this.tileSize,
width: 1200,
height: 720
})
const tileset = this.map.addTilesetImage('tiles', 'tiles', this.tileSize, this.tileSize)
this.layer = this.map.createBlankLayer('layer', tileset)
}
this.input.keyboard.on('keydown-S', () => {
console.log('map saved')
this.saveMapData(this.map)
})
for (let i = 0; i < this.totalTiles; i++) {
const x = ((i % tilesPerRow) * tileWidth)/1.48
const y = (Math.floor(i / tilesPerRow) * tileHeight)/1.48
this.tile = this.add.image(x, y, 'tile (' + i + ')')
this.tile.setOrigin(0)
this.tile.setScale((tileWidth / this.tile.width)/1.48, (tileHeight / this.tile.height)/1.48)
this.tileset.push(this.tile)
}
// Set up pointer events
this.setupPointerEvents()
}
setupPointerEvents() {
this.input.off('pointerdown')
const tiles = this.children.list.filter(child => child.texture && child.texture.key.startsWith('tile ('))
tiles.forEach((tile, i) => {
tile.setInteractive()
tile.on('pointerdown', function() {
this.tileset.forEach(tile => tile.clearTint())
this.tileIndex = i
this.tilePicked = true
tile.setTint(0xff0000)
}, this)
})
this.input.on('pointerdown', function(){
this.dragging = true
}, this)
this.input.on('pointerup', function(){
this.dragging = false
}, this)
this.input.on('pointermove', function(pointer) {
if(this.dragging){
this.tileX = Math.floor(pointer.x / this.tileSize)
this.tileY = Math.floor(pointer.y / this.tileSize)
this.placeTile(this.tileX, this.tileY)
}
}, this)
}
// Other methods...
placeTile(tileX, tileY) {
if (this.map && this.layer) {
if (tileY < 4) {
console.log('Cannot place tile on the tile selection area');
return;
}
if (!this.tilePicked) {
console.log('No tile is chosen');
} else {
this.map.putTileAt(this.tileIndex + 1, tileX, tileY, this.layer);
}
} else {
console.log('Tilemap or layer is not properly initialized');
}
}
saveMapData() {
const mapData = {
width: this.map.width,
height: this.map.height,
layers: []
};
// Iterate over each layer in the map
this.map.layers.forEach(layer => {
const layerData = {
name: layer.name || 'layer', // Default name if not provided
data: []
};
// Iterate over each row of tiles in the layer
for (let y = 0; y < this.map.height; y++) {
// Iterate over each tile in the row
for (let x = 0; x < this.map.width; x++) {
// Get the tile index at the current position
const tileIndex = layer.data[y][x].index;
// Record the tile index
layerData.data.push(tileIndex);
}
}
// Push the layer data to the map data
mapData.layers.push(layerData);
});
const jsonString = JSON.stringify(mapData, null, 2);
const blob = new Blob([jsonString], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'map.json';
a.click();
URL.revokeObjectURL(url);
}
// Implement saveMap and loadMap functions to save and load level data
}
I've tried to get the data straight from the map and deleting the tileset used for the layer but if there is no tileset it doesnt work
I don't see the issue, it works for me (except to auto open with
click). But just to be on the save side, if everything is setup correct, you should atleast see all vaules set to-1, if this is not the case something is not configured correct.Also important is that the tileset has atleast as many images as images that you want to place on the map, if not an error will occur.
Update:
It depends on your usecase, but lets says:
Short Demo, how I would do this (using
tilemap):And for "importing" the data later I would use a 2D array to create the map, like in this example.