pixijs / tilemap

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

Question: Is there a way to use this with `@pixi/spritesheet`? #163

Open earthiverse opened 4 months ago

earthiverse commented 4 months ago

I am currently adding tiles as individual sprites / animated sprites to a container, but performance is not ideal on large maps, and I was wondering if this could help me improve performance.

I'm using Typescript, and I have a sprite sheet that I created and I want to use.

import { Assets } from "@pixi/assets";
import { Spritesheet } from "@pixi/spritesheet";

const sheetJson = await fetch("src/assets/map.json");
const sheetImage = await Assets.load("src/assets/map.png");
const spritesheet = new Spritesheet(sheetImage, await sheetJson.json());
await this.spritesheet.parse();
ivanpopelyshev commented 4 months ago

Tilemap is already optimized to work with spritesheets.

earthiverse commented 4 months ago

Tilemap is already optimized to work with spritesheets.

Is there example code anywhere? I'm using @pixi/tilemap 4.1.0 and @pixi/* 7.4.2

I can get the textures from the spritesheet and create an animated sprite with

const textures = spritesheet.animations[key];
const sprite = new AnimatedSprite(textures)

But I have no idea how to create a TileSheet with the textures from the spritesheet. This is what I tried, but I get The tile texture was not found in the tilemap tileset.

const tilemap = new Tilemap(spritesheet.baseTexture);
const textures = spritesheet.animations[key];
tilemap.tile(textures[0], 0, 0);
earthiverse commented 4 months ago

I tried with the latest pixi.js 8.1.0 and @pixi/tilemap 5.0.1, and I can now tile static textures with

const tilemap = new Tilemap(spritesheet.textureSource);
const textures = spritesheet.animations[key];
tilemap.tile(textures[0], 0, 0);
ajur commented 4 months ago

@earthiverse I'm not sure what is your exact use case, but remember, that animations in Tilemap are handled differently than in SpriteAnimations. SpriteAnimations changes texture (so, it's placement on spritesheet doesn't matter), but in Tileset all frames have to be in a fixed grid close to first tile. (you just provide number of frames and rows) - see basic example.

Also, you actually may not need to put each individual sprite in the spritesheet, as you can just provide whole tileset TextureSource and place tile providing source position by hand:

const tilemap = new Tilemap(textureSource);
// place tile, i.e. rect on textureSource image (sourceX, sourceY, tileWidth, tileHeight) on (targetX, targetY) position.
this.tilemap.tile(0, targetX, targetY, {tileWidth, tileHeight, u: sourceX, v: sourceY});

This might be especially useful if you use some tilemap editor with fixed-tile tilemap image source.

earthiverse commented 4 months ago

@ajur I can see how the code I posted is very misleading, sorry, I was just trying to get something working before moving on.

I ended up with different issues using tilemap with a large number of tiles. They just stopped rendering. I got this about 1/3 the way through tiling a map 3936 x 3272 with a tile size of 16 x 16 firefox_Big8cX7vnv

I do have a mix of animated and non-animated tiles in my project, but the animated tiles are only 3 frames.

Making 3 RenderTextures, and just rendering the tiles to the textures is working well enough for me. I made a large animated sprite from my 3 large render textures.

ivanpopelyshev commented 4 months ago

Did you enable 32-bit indices?

earthiverse commented 3 months ago

Did you enable 32-bit indices?

I did not.

The readme on the main page says for use32bitIndex to "please use PixiJS v5.1.0", I guess I'll try again and see if it works on newer versions of PixiJS, too.