Clear the sprites in a first loop before drawing (#692)

## Description:
Split the clearRect from the drawImage in a first loop so that moving
units don't erase other units. There should not be a perfomance
lowering.
There is still an issue of unit erasing other units when the other unit
is not updated (unit didn't move) but it's a rare case and the fix would
be to update all units regardless of their activity, so I think this
might be a good compromise, performance wise.

before:

![image](https://github.com/user-attachments/assets/c0f500ca-2465-4986-9755-0d5f07a17bd7)

after:

![image](https://github.com/user-attachments/assets/ebaef73e-9bf1-485f-8a79-da96c949e4f5)


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Vivacious Box
This commit is contained in:
Rouillard
2025-05-10 15:12:48 +02:00
committed by GitHub
parent 843bfe40d3
commit 1c6c4c0512
+38 -20
View File
@@ -15,7 +15,11 @@ import { MoveWarshipIntentEvent } from "../../Transport";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
import { getColoredSprite, loadAllSprites } from "../SpriteLoader";
import {
getColoredSprite,
isSpriteReady,
loadAllSprites,
} from "../SpriteLoader";
enum Relationship {
Self,
@@ -65,9 +69,8 @@ export class UnitLayer implements Layer {
if (this.myPlayer == null) {
this.myPlayer = this.game.playerByClientID(this.clientID);
}
this.game.updatesSinceLastTick()?.[GameUpdateType.Unit]?.forEach((unit) => {
this.onUnitEvent(this.game.unit(unit.id));
});
this.updateUnitsSprites();
}
init() {
@@ -194,11 +197,9 @@ export class UnitLayer implements Layer {
this.canvas.height = this.game.height();
this.transportShipTrailCanvas.width = this.game.width();
this.transportShipTrailCanvas.height = this.game.height();
this.game
?.updatesSinceLastTick()
?.[GameUpdateType.Unit]?.forEach((unit) => {
this.onUnitEvent(this.game.unit(unit.id));
});
this.updateUnitsSprites();
this.boatToTrail.forEach((trail, unit) => {
for (const t of trail) {
this.paintCell(
@@ -213,6 +214,34 @@ export class UnitLayer implements Layer {
});
}
private updateUnitsSprites() {
const unitsToUpdate = this.game
.updatesSinceLastTick()
?.[GameUpdateType.Unit]?.map((unit) => this.game.unit(unit.id));
unitsToUpdate
?.filter((UnitView) => isSpriteReady(UnitView.type()))
.forEach((unitView) => {
this.clearUnitCells(unitView);
});
unitsToUpdate?.forEach((unitView) => {
this.onUnitEvent(unitView);
});
}
private clearUnitCells(unit: UnitView) {
const sprite = getColoredSprite(unit, this.theme);
const clearsize = sprite.width + 1;
const lastX = this.game.x(unit.lastTile());
const lastY = this.game.y(unit.lastTile());
this.context.clearRect(
lastX - clearsize / 2,
lastY - clearsize / 2,
clearsize,
clearsize,
);
}
private relationship(unit: UnitView): Relationship {
if (this.myPlayer == null) {
return Relationship.Enemy;
@@ -419,8 +448,6 @@ export class UnitLayer implements Layer {
drawSprite(unit: UnitView, customTerritoryColor?: Colord) {
const x = this.game.x(unit.tile());
const y = this.game.y(unit.tile());
const lastX = this.game.x(unit.lastTile());
const lastY = this.game.y(unit.lastTile());
let alternateViewColor = null;
@@ -457,15 +484,6 @@ export class UnitLayer implements Layer {
alternateViewColor,
);
const clearsize = sprite.width + 1;
this.context.clearRect(
lastX - clearsize / 2,
lastY - clearsize / 2,
clearsize,
clearsize,
);
if (unit.isActive()) {
this.context.drawImage(
sprite,