Skip to content

Different tile sizes not accounted for when adding tiles with PutTileAt #5644

Closed
@stuffisthings

Description

@stuffisthings

Version

  • Phaser Version: 3.54.0
  • Operating system: Windows 10
  • Browser: Chrome

Description

I'm trying to use a Tilemap with different sized tiles (isometric, though I don't think it matters): a "flat" terrain tileset of 64x32 tiles, and a buildings set of 64x64 tiles. Maps and tilesets are created in Tiled and exported per the examples. The map is based on a 62x32 isometric grid, but the buildings tileset is "taller". This works fine in Tiled, though to display properly in Phaser the Buildings layer seems to need a -32 vertical offset.

The problem is that when I use PutTileAt to place a 64x64 tile in an empty cell on the Buildings layer, it gets "squished" down to 64x32. Expected behavior is that the new tile would use the tileWidth and tileHeight set in its tileset. Placing a tile over an existing one works as the index is just swapped on the properly-constructed Tile.

I think the problem is in PutTileAt but I may just be misunderstanding something more fundamental here.

Here are the tilesets to better visualize what I'm trying to achieve:

terrains
roads
buildings_1x1

(By the way, I was really excited to see you've added isometric support -- this is my first time working with this library and it's been a really great experience so far even as I've been struggling with this issue.)

Example Test Code

(nb this code has some other bugs including issues with tile positioning)

phaser3-project-template

index.js

import Phaser from 'phaser';
import terrains from './assets/terrains.png';
import roads from './assets/roads.png';
import buildings from './assets/buildings_1x1.png';
import ui from './assets/ui.png';
import mapJSON from './assets/test_small.json';

import putTileAt from './lib/putTileAt.js';

class MyGame extends Phaser.Scene
{
    constructor ()
    {
        super();
        this.map = null;
        this.controls = null;
    }

    preload ()
    {
        this.load.image('terrains', terrains);
        this.load.image('roads', roads);
        this.load.image('buildings', buildings);
        this.load.image('ui', ui);
        this.load.tilemapTiledJSON('map', mapJSON)
    }
      
    create ()
    {
        this.map = this.add.tilemap('map');
        const terrainTiles = this.map.addTilesetImage('terrain', 'terrains', 64, 32);
        const roadTiles = this.map.addTilesetImage('roads', 'roads', 64, 32);
        const buildingTiles = this.map.addTilesetImage('buildings_1x1', 'buildings', 64, 64);

        const terrain = this.map.createLayer('Terrain', terrainTiles);
        const ground = this.map.createLayer('Roads', roadTiles);
        const buildings = this.map.createLayer('Buildings', buildingTiles);

        // set up the marker
        this.marker = this.add.image(0, 0, 'ui');
        this.marker.originY = 0;

        // set up camera controls
        const cursors = this.input.keyboard.createCursorKeys();

        const controlConfig = {
            camera: this.cameras.main,
            left: cursors.left,
            right: cursors.right,
            up: cursors.up,
            down: cursors.down,
            acceleration: 0.04,
            drag: 0.0005,
            maxSpeed: 0.7
        };

        this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
        this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
           if (deltaY < 0) {
             if (this.cameras.main.zoom < 1) this.cameras.main.setZoom(this.cameras.main.zoom * 1.25);
           } else {
            if (this.cameras.main.zoom > 0.1) this.cameras.main.setZoom(this.cameras.main.zoom * 0.75);
           }
        });

        this.input.on('pointerdown', (pointer) => {
            const worldToTilePoint = this.map.worldToTileXY(pointer.worldX, pointer.worldY, true);
            // PROBLEM IS HERE
            const newTile = putTileAt(247, worldToTilePoint.x, worldToTilePoint.y, false, buildings.layer); // works with new putTileAt
            // below works also
            // const selectedTile = buildings.layer.data[0][0];
            // const newTile = putTileAt(selectedTile, worldToTilePoint.x, worldToTilePoint.y, false, buildings.layer);
            // built-in methods don't work, tile is squished:
            // const newTile = this.map.putTileAt(247, worldToTilePoint.x, worldToTilePoint.y);
            // const newTile = this.map.putTileAt(selectedTile, worldToTilePoint.x, worldToTilePoint.y);
            console.log('put tile', newTile);
        });
    }

    update(time, delta) {
        // update camera
        this.controls.update(delta);

        const worldPoint = this.input.activePointer.positionToCamera(this.cameras.main);
        const worldToTilePoint = this.map.worldToTileXY(worldPoint.x, worldPoint.y, true);
        const tilePoint = this.map.tileToWorldXY(worldToTilePoint.x, worldToTilePoint.y);
        // Snap to tile coordinates, but in world space
        this.marker.x = tilePoint.x;
        this.marker.y = tilePoint.y;
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: MyGame
};

const game = new Phaser.Game(config);

test_small.json

{ "compressionlevel":-1,
 "editorsettings":
    {
     "export":
        {
         "format":"json",
         "target":"test_small.json"
        }
    },
 "height":25,
 "infinite":false,
 "layers":[
        {
         "data":[16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
         "height":25,
         "id":1,
         "name":"Terrain",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":25,
         "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, 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, 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, 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, 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, 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, 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, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 83, 83, 83, 83, 83, 83, 83, 83, 99, 83, 83, 83, 83, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":25,
         "id":3,
         "name":"Roads",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":25,
         "x":0,
         "y":0
        }, 
        {
         "data":[253, 255, 244, 246, 253, 257, 248, 255, 244, 257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 247, 253, 247, 253, 256, 244, 244, 253, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 256, 246, 247, 257, 253, 256, 256, 246, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 245, 257, 253, 256, 254, 255, 245, 257, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 255, 256, 255, 257, 255, 253, 245, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 248, 257, 247, 245, 246, 248, 255, 245, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 248, 247, 253, 245, 253, 257, 244, 247, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 247, 254, 254, 254, 256, 246, 257, 255, 257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 244, 257, 254, 244, 244, 248, 256, 245, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 248, 255, 244, 254, 247, 253, 246, 255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 256, 247, 254, 256, 256, 246, 245, 244, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":25,
         "id":2,
         "name":"Buildings",
         "offsetx":0,
         "offsety":-32,
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":25,
         "x":0,
         "y":0
        }],
 "nextlayerid":5,
 "nextobjectid":3,
 "orientation":"isometric",
 "renderorder":"right-down",
 "tiledversion":"1.5.0",
 "tileheight":32,
 "tilesets":[
        {
         "columns":7,
         "firstgid":1,
         "grid":
            {
             "height":32,
             "orientation":"isometric",
             "width":64
            },
         "image":"..\/..\/..\/..\/Pictures\/projects\/terrains.png",
         "imageheight":192,
         "imagewidth":448,
         "margin":0,
         "name":"terrain",
         "spacing":0,
         "tilecount":81,
         "tileheight":32,
         "tilewidth":64
        }, 
        {
         "columns":8,
         "firstgid":82,
         "grid":
            {
             "height":32,
             "orientation":"isometric",
             "width":64
            },
         "image":"..\/..\/..\/..\/Pictures\/projects\/roads.png",
         "imageheight":192,
         "imagewidth":512,
         "margin":0,
         "name":"roads",
         "spacing":0,
         "tilecount":162,
         "tileheight":32,
         "tiles":[
                {
                 "id":0
                }, 
                {
                 "id":1
                }, 
                {
                 "id":2
                }, 
                {
                 "id":3
                }, 
                {
                 "id":8
                }, 
                {
                 "id":9
                }, 
                {
                 "id":10
                }, 
                {
                 "id":11
                }, 
                {
                 "id":16
                }, 
                {
                 "id":17
                }, 
                {
                 "id":18
                }],
         "tilewidth":64
        }, 
        {
         "columns":9,
         "firstgid":244,
         "grid":
            {
             "height":32,
             "orientation":"isometric",
             "width":64
            },
         "image":"..\/..\/..\/..\/Pictures\/projects\/buildings_1x1.png",
         "imageheight":512,
         "imagewidth":576,
         "margin":0,
         "name":"buildings_1x1",
         "objectalignment":"bottomleft",
         "spacing":0,
         "tilecount":81,
         "tileheight":64,
         "tilewidth":64
        }],
 "tilewidth":64,
 "type":"map",
 "version":1.5,
 "width":25
}

Additional Information

Possible solution

After digging around in the source code I see a possible issue with PutTileAt.js, similar to #4756 which was closed for some reason.

First problem: when PutTileAt creates new Tiles, it just sets the tile width/height based on the layer (not the tileset). It also doesn't pass the baseTileWidth and baseTileHeight, which I think is needed if a different width/height is actually set in the width/height parameters.

Second problem: sparse layers get their data filled in with Tiles having index -1. So the layer.data[tileY][tileX] === null check in PutTileAt never passes, the method only ever copies the tile data (if a tile was provided) or sets the new index, and the "empty" tiles don't have the right width/height/baseWidth/baseHeight, because the "filler" Tiles don't have them. In fact, the first problem doesn't come into play because new tiles are never created -- at least not when interacting with a layer created the way I did it.

I was able to get around this with a modified putTileAt method which is used in the code above:

putTileat.js

import Phaser from 'phaser';

 const Tile = Phaser.Tilemaps.Tile;
 const { IsInLayerBounds, CalculateFacesAt, SetTileCollision } = Phaser.Tilemaps.Components;
 
 /**
  * Puts a tile at the given tile coordinates in the specified layer. You can pass in either an index
  * or a Tile object. If you pass in a Tile, all attributes will be copied over to the specified
  * location. If you pass in an index, only the index at the specified location will be changed.
  * Collision information will be recalculated at the specified location.
  *
  * @function Phaser.Tilemaps.Components.PutTileAt
  * @since 3.0.0
  *
  * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object.
  * @param {number} tileX - The x coordinate, in tiles, not pixels.
  * @param {number} tileY - The y coordinate, in tiles, not pixels.
  * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated.
  * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon.
  *
  * @return {Phaser.Tilemaps.Tile} The Tile object that was created or added to this map.
  */
 var PutTileAt = function (tile, tileX, tileY, recalculateFaces, layer)
 {
     if (recalculateFaces === undefined) { recalculateFaces = true; }
 
     if (!IsInLayerBounds(tileX, tileY, layer))
     {
         return null;
     }
 
     var oldTile = layer.data[tileY][tileX];
     var oldTileCollides = oldTile && oldTile.collides;
 
     if (tile instanceof Tile)
     {
        layer.data[tileY][tileX] = new Tile(layer, tile.index, tileX, tileY, tile.width, tile.height, layer.baseTileWidth, layer.baseTileHeight);
        layer.data[tileY][tileX].copy(tile);
     }
     else
     {
         var tileset = layer.tilemapLayer.gidMap[tile];
         var index = tile;
         layer.data[tileY][tileX] = new Tile(layer, index, tileX, tileY, tileset.tileWidth, tileset.tileHeight, layer.baseTileWidth, layer.baseTileHeight);
     }
 
     // Updating colliding flag on the new tile
     var newTile = layer.data[tileY][tileX];
     var collides = layer.collideIndexes.indexOf(newTile.index) !== -1;
 
     SetTileCollision(newTile, collides);
 
     // Recalculate faces only if the colliding flag at (tileX, tileY) has changed
     if (recalculateFaces && (oldTileCollides !== newTile.collides))
     {
         CalculateFacesAt(tileX, tileY, layer);
     }
 
     return newTile;
 };
 
export default PutTileAt;

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions