Feat/breathing animation around spawn cell (#1951)

## Description:

Noticed many people are struggling to see where they choose to spawn or
forget where they chose , what leads to confusion.
solved it with this animation around the spawning player cell.


![giphy](https://github.com/user-attachments/assets/938f7dc8-97cb-40d0-8222-9f8ddbc2b21f)

<img width="231" height="265" alt="image"
src="https://github.com/user-attachments/assets/22e157a5-301d-4d41-8f2c-21a9dd09a1f6"
/>




ALSO: Added a missing translation for hebrew


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

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

boostry

Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
yanir
2025-09-05 21:25:17 +03:00
committed by GitHub
parent 76723e6739
commit 8010688d27
@@ -23,6 +23,7 @@ export class TerritoryLayer implements Layer {
private context: CanvasRenderingContext2D;
private imageData: ImageData;
private alternativeImageData: ImageData;
private borderAnimTime = 0;
private cachedTerritoryPatternsEnabled: boolean | undefined;
@@ -195,6 +196,37 @@ export class TerritoryLayer implements Layer {
}
}
}
// Breathing border animation
this.borderAnimTime += 1;
const minPadding = 3;
const maxPadding = 8;
// Range: [minPadding..maxPadding]
const breathingPadding =
minPadding +
(maxPadding - minPadding) *
(0.5 + 0.5 * Math.sin(this.borderAnimTime * 0.3));
if (focusedPlayer) {
// Clear previous animated border
if (this.highlightContext) {
this.highlightContext.clearRect(
0,
0,
this.game.width(),
this.game.height(),
);
}
const center = focusedPlayer.nameLocation();
if (center) {
this.drawBreathingRing(
center.x,
center.y,
breathingPadding,
this.theme.spawnHighlightColor(),
);
}
}
}
init() {
@@ -550,4 +582,18 @@ export class TerritoryLayer implements Layer {
const y = this.game.y(tile);
this.highlightContext.clearRect(x, y, 1, 1);
}
private drawBreathingRing(
cx: number,
cy: number,
radius: number,
color: Colord,
) {
const ctx = this.highlightContext;
if (!ctx) return;
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.strokeStyle = color.toRgbString();
ctx.lineWidth = 2;
ctx.stroke();
}
}