Skip to content

Commit

Permalink
fix(client): prevent drawing when standing (canvas)
Browse files Browse the repository at this point in the history
  • Loading branch information
Veradictus committed Sep 24, 2023
1 parent db49554 commit 0455d8c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 21 deletions.
13 changes: 13 additions & 0 deletions packages/client/src/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,19 @@ export default class Game {
if (this.map.hasCachedDate()) this.app.fadeMenu();

this.menu.synchronize();

// Forcibly render the game for a few frames to ensure animated tiles are rendered.
let count = 0,
interval = setInterval(() => {
this.renderer.forceRendering = true;

count++;

if (count > 3) {
clearInterval(interval);
this.renderer.forceRendering = false;
}
}, 50);
}

/**
Expand Down
71 changes: 56 additions & 15 deletions packages/client/src/renderer/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface RendererCell {

export default class Canvas extends Renderer {
public animatedTiles: { [tileId: number | string]: Tile } = {};
public animatedTileIndexes: { [tileId: number | string]: number[] } = {};

// Used for storing and caching tile information.
private tiles: { [id: string]: RendererTile } = {};
Expand Down Expand Up @@ -85,7 +86,7 @@ export default class Canvas extends Renderer {
*/

private draw(): void {
if (this.hasRenderedFrame()) return;
if (this.hasRenderedFrame()) return this.drawAnimatedIndexes();

this.clearDrawing();
this.saveDrawing();
Expand All @@ -96,8 +97,8 @@ export default class Canvas extends Renderer {
/**
* I made a decision to sacrifice legibility to maximize performance. We avoid using
* `forEachVisiblePosition` so that we do not make a ridiculous amount of callbacks
* for each tile. We do the iteration through the visible tiles manually and
* draw which tiles are visible.
* for each tile. We do the iteration through the visible tiles using a for loop and
* all within one function.
*/

for (let y = this.camera.gridY - 2; y < this.camera.gridY + this.map.height + 2; y++)
Expand All @@ -108,18 +109,7 @@ export default class Canvas extends Renderer {
let index = x + y * this.map.width,
tile = this.map.data[index];

if (tile === 0) continue;

// Check for transformed tiles and draw them.
if ((tile as TransformedTile).tileId) {
this.drawVisibleTile(tile as TransformedTile, index);
continue;
}

// This is a hackfix to check if the tile is an array at the index.
if (~~tile === 0)
for (let info of tile as number[]) this.drawVisibleTile(info, index);
else this.drawVisibleTile(tile, index);
this.parseTile(tile, index);
}

this.saveFrame();
Expand Down Expand Up @@ -157,6 +147,30 @@ export default class Canvas extends Renderer {
else this.drawTile(context, tile as number, index, flips);
}

/**
* We iterate through the animated indexes for each animated tile and draw them.
* We store the animated tiles in a dictionary since it makes it easier to delete
* them when they are no longer used. For each index we render the whole tile information
* at that index to ensure that the tile is drawn correctly.
*/

private drawAnimatedIndexes(): void {
this.saveDrawing();
this.updateDrawingView();

for (let tileId in this.animatedTileIndexes) {
let indexes = this.animatedTileIndexes[tileId];

for (let index of indexes) {
let tile = this.map.data[index];

this.parseTile(tile, index);
}
}

this.restoreDrawing();
}

/**
* Given the index of the specified animated tile, we draw the tile contained at
* that index. We first have to check whether the tile is a foreground tile or not.
Expand All @@ -183,6 +197,11 @@ export default class Canvas extends Renderer {
if (!animatedTile)
return this.addAnimatedTile(tile as number, isDynamicallyAnimated ? index : -1);

// Store the indices of animated tiles for later use.
if (!this.animatedTileIndexes[tile]) this.animatedTileIndexes[tile] = [];
else if (!this.animatedTileIndexes[tile].includes(index))
this.animatedTileIndexes[tile].push(index);

// Update the last accessed time.
animatedTile.lastAccessed = this.game.time;

Expand Down Expand Up @@ -438,6 +457,28 @@ export default class Canvas extends Renderer {
this.resetAnimatedTiles();
}

/**
* Parses a map tile at a specified index and determines what to do
* with it. If it's an array, we iterate through the array and draw
* each tile. Otherwise, we draw the tile.
* @param tile The tile we are parsing, raw from the client map.
* @param index The index of the tile on the map.
*/

private parseTile(tile: ClientTile, index: number): void {
if (tile === 0) return;

// Check for transformed tiles and draw them.
if ((tile as TransformedTile).tileId) {
this.drawVisibleTile(tile as TransformedTile, index);
return;
}

// This is a hackfix to check if the tile is an array at the index.
if (~~tile === 0) for (let info of tile as number[]) this.drawVisibleTile(info, index);
else this.drawVisibleTile(tile, index);
}

// ---------- Getters and Checkers ----------

/**
Expand Down
6 changes: 1 addition & 5 deletions packages/client/src/renderer/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1494,9 +1494,7 @@ export default class Renderer {
*/

protected hasRenderedFrame(): boolean {
if (this.forceRendering || !this.game.isLowPowerMode()) return false;

if (this.stopRendering) return true;
if (this.forceRendering) return false;

return this.renderedFrame[0] === this.camera.x && this.renderedFrame[1] === this.camera.y;
}
Expand Down Expand Up @@ -1547,8 +1545,6 @@ export default class Renderer {
*/

protected saveFrame(): void {
if (!this.game.isLowPowerMode()) return;

this.renderedFrame[0] = this.camera.x;
this.renderedFrame[1] = this.camera.y;

Expand Down
1 change: 1 addition & 0 deletions packages/client/src/renderer/updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ export default class Updater {
// Delete the tile and continue if it's unused or expired.
if (tile.unused || tile.expired) {
delete this.renderer.animatedTiles[identifier];
delete this.renderer.animatedTileIndexes[identifier];

continue;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/renderer/webgl/webgl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export default class WebGL extends Renderer {

private draw(x = this.camera.x, y = this.camera.y): void {
// Used for low power mode
if (this.hasRenderedFrame()) return;
if (this.hasRenderedFrame() && this.game.isLowPowerMode()) return;

// Iterate through the drawing contexts and apply the necessary transformations/attributes.
this.forEachDrawingContext((context: WebGLRenderingContext) => {
Expand Down

0 comments on commit 0455d8c

Please sign in to comment.