pixijs / tilemap

Rectangular tilemap implementation for PixiJS
https://pixijs.io/tilemap/docs/
MIT License
289 stars 55 forks source link

Tiles are reset to original, after x amount of changes #132

Closed Deenis closed 3 years ago

Deenis commented 3 years ago

Description I'm working on a game, where players will change the tiles frequently. However, after calling tilemap.tile enough times, it starts to reset previous tiles to initial tile.

I've recreated an exaggeratee example, that shows my issue:

import * as PIXI from "pixi.js";
import * as TileMap from "@pixi/tilemap";

const app = new PIXI.Application();
document.body.appendChild(app.view);

const loader = PIXI.Loader.shared;

loader
  .add([
    {
      name: "tilesheet",
      url: "https://pixijs.io/examples/examples/assets/tilemaps/atlas.json"
    }
  ])
  .load();

// New tilemap:
const tilemap = new TileMap.CompositeTilemap();

// Set all tiles to grass.png
for (let x = 0; x < 64; x += 1) {
  for (let y = 0; y < 64; y += 1) {
    tilemap.tile("grass.png", x * 32, y * 32);
  }
}

app.stage.addChild(tilemap);

// Run continously, every 500ms
setInterval(() => {
  // Set all tiles to brick.png
  for (let x = 0; x < 64; x += 1) {
    for (let y = 0; y < 64; y += 1) {
      tilemap.tile("brick.png", x * 32, y * 32);
    }
  }
}, 500);

Expected behavoiur: I would expect the whole map to start as grass, and then change to bricks after 500ms, and then stay as bricks (because continuously overwriting with same brick tile every 500ms).

Actual behaviour: Whole map starts as grass, becomes bricks after 500ms, but then changes back to grass.

I've read about textures per tilemap in documentation, but setting it, doesn't change anything for me:

TileMap.settings.TEXTURES_PER_TILEMAP = 32 * 32

Live example: https://codesandbox.io/s/upbeat-vaughan-6rhjx?file=/src/index.js:0-709

ivanpopelyshev commented 3 years ago

You dont overwrite things. To overwrite, you have to access internal array, change it, and also set the modified flag.

Here you add stuff, and there's a limit on how much tyou can do before you hit 16-bit limit, as explained inreadme (readme is a bit botched at the moment). You can set 32-bit limt, but, you'll still have performance problem, because all previous tile will be done each frame

So, either you overwrite the plugin method tile() so they actually override previous tiles, either you do as the plugin is supposed tow work: clear() and tile() all from start when you have chnage in this particular tilemap. Your map might consists of many of them/

There are many algos that you can use on high-level, but hivh-level is your problem. pixi-tilemap is low-level problem. If your high-level requires to override existing tiles and cant keep up tile list itself - well, you can use pixi containers + sprites.

Deenis commented 3 years ago

Oh, right. So tilemap.tile("brick.png", 0, 0) basically keeps adding draw calls, instead of changing the tile data?

I've done previously implementation in different engines before, and usually consists a shader that draws a bunch of tiles from an array each frame. So if the array is changed, it's just drawning the new tile instead.

But in this implementation, you basically add a draw call when calling tilemap.tile(), and then on each frame all the draw calls are executed? So this actually enables me to create multiple layered tiles.

I guess my confusing came from how I usually implemented tiles, but this actually makes more sense.

You're right, I've misused this as a high-level, but it's actually low-level. Thanks for elaborating.

Thanks!