Is it possible to generate a TileMap in an extension?

I made a block that converts a TileMap to stringified JSON (For saving TileMaps to the device with the Settings extension), but now that I need to write a block that converts the stringified JSON back to a Tilemap I need to generate a new TileMap, the closest built-in function I found was the tiles.createTilemap function which takes in the arguments data: Buffer, layer: Image, tiles: Image[], scale: TileScale but I don’t know how to use data, layer, and scale. They’re used to generate a TileMap from assets but I’m generating one from JSON not from assets.

An example of the stringified JSON of a TileMap:


Converts to:

{"size":[3,3],"tiles":[[{"id":1,"wall":true},{"id":0,"wall":false},{"id":1,"wall":true}],[{"id":0,"wall":false},{"id":0,"wall":true},{"id":0,"wall":false}],[{"id":1,"wall":false},{"id":0,"wall":true},{"id":1,"wall":false}]]}
2 Likes

I’m trying to create a new empty TileMap with tiles.createTilemap(hex, img, [], TileScale.Sixteen); but I cant change the width and height because they’re constant values. So I can’t generate a TileMap like this:

const data = {
    "size": [3, 3],
    "tiles": []
}

const tilemap = tiles.createTilemap(hex``, img``, [], TileScale.Sixteen);

tilemap.width = data.size[0]; // Error, 'width' is a constant value.
tilemap.height = data.size[1]; // Error, 'height' is a constant value.
1 Like

Oops, markdown error! It’s suppose to be tiles.createTilemap(hex​`​`, img​`​`, [], TileScale.Sixteen); and not tiles.createTilemap(hex, img, [], TileScale.Sixteen);. And as I expected, the code doesn’t work. Does anyone know how to generate an empty TileMap with a specific width and height? Thanks!

can you not change:

const data = {
    "size": [3, 3],
    "tiles": []
}

to:

data = { // Change from constant to normal
    "size": [3, 3],
    "tiles": []
}

// Set "size" to something higher in an 'on game update' or 'while True' 
// or some other code
1 Like

It’s an example, and I can’t define variables without var/let/const (This is JavaScript). The low size is also for an example.

then could you not do

let data = { …

1 Like

The variable doesn’t get changed, so it can be const instead of let. Const also uses less memory.

The buffer must have a size of the number of tiles in x * the number of y + 4 bytes. Since the first two bytes are used to specify the x size of the tilemap and the second two for the y size.

let buffer = Buffer.create((xSize * ySize) + 4);
buffer.setNumber(NumberFormat.UInt16LE, 0, xSize);
buffer.setNumber(NumberFormat.UInt16LE, 2, ySize);

and the image should be the same size as the tilemap

image.create(xSize, ySize)

it would fit you like this…

const xSize = 16; // tilemap width
const ySize = 16; // tilemap height
const buffer = Buffer.create((xSize * ySize) + 4);
buffer.setNumber(NumberFormat.UInt16LE, 0, xSize);
buffer.setNumber(NumberFormat.UInt16LE, 2, ySize);
const tilemapImg = image.create(xSize, ySize);
const tilemap = tiles.createTilemap(buffer, tilemapImg, [], TileScale.Sixteen);
1 Like

I was thinking more in this direction:

let SizeVar: number 

SizeVar = 3 // size as a variable

let data = { // The list / Dictionary
    'size' : [3, 3]
}

game.onUpdate(function () {
    data.size[0] = SizeVar // Assign different positions to the 'size' variable
    data.size[1] = SizeVar
})

game.onUpdateInterval(1000, function () {
    SizeVar += 1 // Change SizeVar by 1 every second
})

The code assigns ‘size’ to to a variable in addition to appending it to our ‘data.size’ list

What? I’m not trying to increase the size of the tilemap, I’m trying to generate a new empty tilemap with a specified width and height. What would I need to use this code for?

Hmm, no errors but the tilemap is empty even after I call tilemap.setTile(x, y, id). The only parameter that you left empty was tiles: Image[], maybe I have to give it the image of every tile in the assets? Wouldn’t that use too much memory? I can access tiles: Image[] with tilemap.getTileset() and the output is Image[] . But when I log the variable (Either converted to JSON or not), it just logs [object Object], [object Object], [object Object], ... or {{}, {}, {}, ...}. Maybe I have to pass through every image in getTileset() into the converted JSON from a tilemap, like this (Look in the tileset key):

{
    "size": {"width": 3, "height": 3},
    "tiles": [
        // Array of ID and walls
    ],
    "tileset": [
        [
            id: 0,
            image: img`22221919999995888888888888333329855555`
            // Just an example, hex doesn't work like that in JSON
        ]
    ]
}

To get a clue of build a tilemap with code, see the “tilemap.g.ts” file in your projet, after created a tilemap.

To place tiles you must add the images to the empty array, and the id of setTile(x, y, id) would be the index of the image in the array.

const tilemap = tiles.createTilemap(buffer, tilemapImg, [/* Fill this with your images */], TileScale.Sixteen);

Also you must call tiles.setTilemap to set the tilemap on the scene, otherwise you won’t see the changes you make to the tilemap when you call setTile.

tiles.setTilemap(tilemap);

One minor point, you should use tiles.setCurrentTilemap(tilemap) instead of tiles.setTilemap(tilemap) as setTilemap is deprecated / doesn’t play nice with variables and decompiling to blocks (https://github.com/microsoft/pxt-common-packages/blob/stable10.3/libs/game/tilemap.ts#L600)

2 Likes