adrien-gueret / tilesheets

A small library providing helpers to handle tile sheets.
https://adrien-gueret.github.io/tilesheets/
5 stars 0 forks source link

Canvas Resizing (and Wiping) Even When Not Needed #20

Open Quzzar opened 1 month ago

Quzzar commented 1 month ago

Describe the bug

When you render a Scene to a canvas, it will wipe the existing canvas - even when the scene tiles and tilesheet tile size is the same.

To Reproduce

Steps to reproduce the behavior:

Render two sets of tiles to the same canvas. Even though some tiles may be transparent, it will always wipe the canvas resulting in an inability to layer two different scene tiles on top of each other in the same canvas.

Additional context

I don't have the ability to open PRs or else I would for the fix!

Quzzar commented 1 month ago

If anyone else has this issue, I hacked this together after taking a look at the project's source code:

const renderToCanvas = (layer: number[][], tiles: Tilesheet, canvas: HTMLCanvasElement) => {
  const scene = new Scene(layer, null);
  scene.useTilesheet(tiles);
  const sceneWidth = scene.getWidth();
  const sceneHeight = scene.getHeight();
  if (canvas.width !== sceneWidth || canvas.height !== sceneHeight) {
    canvas.width = sceneWidth;
    canvas.height = sceneHeight;
  }
  scene.render(canvas);
};
adrien-gueret commented 1 month ago

Hi there, and thanks for creating this issue.

Can you provide some lines of code of what you're trying to do? The method render of Scene does not reset the canvas, so I wonder what is exactly your usecase.

This library was not made with layers in mind, that's true, but what you're trying to do should be possible. To do that, you should have two scenes: one for each layer. Please check the code below:

  const backgroundSheet = new Tilesheet('./path/to/backgroundSheet.png');
  const foregroundSheet = new Tilesheet('./path/to/foregroundSheet.png');

  const backgroundTiles = [/* your background tiles */];
  const foregroundTiles = [/* your foreground tiles */];

  const myCanvas = document.getElementById("your-canvas");

  const backgroundScene = new Scene(backgroundTiles , myCanvas);
  const foregroundScene = new Scene(foregroundTiles , myCanvas);
  backgroundScene .useTilesheet(backgroundSheet);
  foregroundScene.useTilesheet(foregroundSheet);

  backgroundScene.render();
  foregroundScene.render();

That's said, if you have animations on the transparent tiles, the behavior will probably be a little buggy. I would advice to create two separate canvas and put the foreground one above the background one (via position: absolute).