статистика на экране смерти
This commit is contained in:
+10
@@ -376,6 +376,16 @@
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.game-over-overlay__stats {
|
||||
font-size: 11px;
|
||||
color: var(--text);
|
||||
text-align: center;
|
||||
line-height: 1.8;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
@keyframes chop-shake {
|
||||
0%, 100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
|
||||
@@ -56,6 +56,12 @@ const GameOverOverlay = observer(function GameOverOverlay({
|
||||
<div className="game-over-overlay__message">
|
||||
Вы прожили {store.day} {dayWord(store.day)}, но вас поймали кролики
|
||||
</div>
|
||||
<div className="game-over-overlay__stats">
|
||||
<div>Пройдено: {Math.round(store.character.distanceTraveled)} px</div>
|
||||
<div>Срублено: {store.treesChoppedCount} деревьев, {store.bushesChoppedCount} кустов</div>
|
||||
<div>Поймано кроликов: {store.rabbitsCaughtCount}</div>
|
||||
<div>Заработано монет: {store.totalCoinsEarned.toFixed(1)}</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="menu-btn"
|
||||
|
||||
+30
-1
@@ -69,6 +69,15 @@ export class GameStore {
|
||||
bloodMoonBannerTimer = 0;
|
||||
upgradeLevels: Record<UpgradeId, number> = { ...DEFAULT_UPGRADE_LEVELS };
|
||||
|
||||
// This life's run-summary stats, shown on the death screen — reset to 0 on a fresh game,
|
||||
// restored from the save when continuing one (see initialize()).
|
||||
treesChoppedCount = 0;
|
||||
bushesChoppedCount = 0;
|
||||
rabbitsCaughtCount = 0;
|
||||
/** Cumulative coins earned from converting resources — unlike inventory.coins, this never goes
|
||||
* down when coins are spent on upgrades. */
|
||||
totalCoinsEarned = 0;
|
||||
|
||||
private coinProgress = 0;
|
||||
private saveProgress = 0;
|
||||
private lastTimestamp: number | null = null;
|
||||
@@ -257,7 +266,7 @@ export class GameStore {
|
||||
this.upgradeLevels = { ...DEFAULT_UPGRADE_LEVELS, ...save?.upgradeLevels };
|
||||
|
||||
if (save?.character && save.nodes && save.resourceDrops) {
|
||||
this.character = new Character(save.character.x, save.character.y, save.characterHp ?? this.characterMaxHp);
|
||||
this.character = new Character(save.character.x, save.character.y, save.characterHp ?? this.characterMaxHp, save.distanceTraveled ?? 0);
|
||||
this.nodes = save.nodes.map((node) => ResourceNode.restore(node));
|
||||
this.resourceDrops = save.resourceDrops.map((drop) => ResourceDrop.restore(drop));
|
||||
} else {
|
||||
@@ -266,6 +275,13 @@ export class GameStore {
|
||||
this.resourceDrops = [];
|
||||
}
|
||||
|
||||
// This life's run-summary stats — restored from the save when continuing a life, reset to 0
|
||||
// for a fresh one (matching the character branch above, since both represent the same life).
|
||||
this.treesChoppedCount = save?.treesChoppedCount ?? 0;
|
||||
this.bushesChoppedCount = save?.bushesChoppedCount ?? 0;
|
||||
this.rabbitsCaughtCount = save?.rabbitsCaughtCount ?? 0;
|
||||
this.totalCoinsEarned = save?.totalCoinsEarned ?? 0;
|
||||
|
||||
// Rabbits are restored/spawned independently of the world-state branch above so a save from
|
||||
// before rabbits existed still loads fine — it just gets a freshly spawned batch of them.
|
||||
this.rabbits = save?.rabbits
|
||||
@@ -312,6 +328,11 @@ export class GameStore {
|
||||
day: this.day,
|
||||
hour: this.hour,
|
||||
characterHp: this.character.hp,
|
||||
distanceTraveled: this.character.distanceTraveled,
|
||||
treesChoppedCount: this.treesChoppedCount,
|
||||
bushesChoppedCount: this.bushesChoppedCount,
|
||||
rabbitsCaughtCount: this.rabbitsCaughtCount,
|
||||
totalCoinsEarned: this.totalCoinsEarned,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -585,6 +606,10 @@ export class GameStore {
|
||||
this.nodes = this.nodes.filter((n) => n.id !== node.id);
|
||||
this.heldNodeId = null;
|
||||
this.character.resetChopProgress();
|
||||
if (node.kind === 'tree')
|
||||
this.treesChoppedCount += 1;
|
||||
else
|
||||
this.bushesChoppedCount += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -631,6 +656,7 @@ export class GameStore {
|
||||
this.heldRabbitId = null;
|
||||
this.character.resetAttackProgress();
|
||||
}
|
||||
this.rabbitsCaughtCount += 1;
|
||||
this.ejectDrop(rabbit, 'meat');
|
||||
}
|
||||
|
||||
@@ -697,14 +723,17 @@ export class GameStore {
|
||||
if (this.inventory.logs > 0) {
|
||||
this.inventory.logs -= 1;
|
||||
this.inventory.coins += this.coinsPerLog;
|
||||
this.totalCoinsEarned += this.coinsPerLog;
|
||||
}
|
||||
if (this.inventory.twigs > 0) {
|
||||
this.inventory.twigs -= 1;
|
||||
this.inventory.coins += this.coinsPerTwig;
|
||||
this.totalCoinsEarned += this.coinsPerTwig;
|
||||
}
|
||||
if (this.inventory.meat > 0) {
|
||||
this.inventory.meat -= 1;
|
||||
this.inventory.coins += this.coinsPerMeat;
|
||||
this.totalCoinsEarned += this.coinsPerMeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,18 @@ export class Character {
|
||||
x: number;
|
||||
y: number;
|
||||
hp: number;
|
||||
/** Total px moved so far this life — an odometer for the death-screen run summary. */
|
||||
distanceTraveled: number;
|
||||
|
||||
private chopProgress = 0;
|
||||
private attackProgress = 0;
|
||||
private regenProgress = 0;
|
||||
|
||||
constructor(x: number, y: number, hp: number) {
|
||||
constructor(x: number, y: number, hp: number, distanceTraveled = 0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.hp = hp;
|
||||
this.distanceTraveled = distanceTraveled;
|
||||
makeAutoObservable(this, {}, { autoBind: true });
|
||||
}
|
||||
|
||||
@@ -36,6 +39,7 @@ export class Character {
|
||||
const ratio = step / distance;
|
||||
this.x += dx * ratio;
|
||||
this.y += dy * ratio;
|
||||
this.distanceTraveled += step;
|
||||
return distance - step;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@ export interface SaveData {
|
||||
hour?: number;
|
||||
/** Absent on saves from before the character had hp, which default to a full characterMaxHp. */
|
||||
characterHp?: number;
|
||||
/** This life's run-summary stats (shown on the death screen) — absent on older saves or a
|
||||
* fresh game, which default to 0. */
|
||||
distanceTraveled?: number;
|
||||
treesChoppedCount?: number;
|
||||
bushesChoppedCount?: number;
|
||||
rabbitsCaughtCount?: number;
|
||||
/** Cumulative coins earned from converting resources — unlike inventory.coins, this never goes
|
||||
* down when coins are spent on upgrades. */
|
||||
totalCoinsEarned?: number;
|
||||
}
|
||||
|
||||
function isValidSave(value: unknown): value is SaveData {
|
||||
|
||||
Reference in New Issue
Block a user