Session 18: Prestige Progress Bar (live visual progress toward next Stellar Essence)
This commit is contained in:
@@ -1060,6 +1060,51 @@ h2, h3 {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prestige Progress Bar */
|
||||||
|
.prestige-progress {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prestige-progress-label {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prestige-progress-label #prestige-progress-pct {
|
||||||
|
color: var(--accent-purple);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prestige-progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 12px;
|
||||||
|
background: var(--bg-card-2, var(--text-muted));
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prestige-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
width: 0%;
|
||||||
|
background: linear-gradient(90deg, var(--accent-purple), #b366ff);
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: width 0.25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prestige-progress-fill.filling {
|
||||||
|
animation: prestigeGlow 1.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes prestigeGlow {
|
||||||
|
0%, 100% { filter: brightness(1); }
|
||||||
|
50% { filter: brightness(1.25); }
|
||||||
|
}
|
||||||
|
|
||||||
/* Prestige Upgrade Cards */
|
/* Prestige Upgrade Cards */
|
||||||
#prestige-upgrades-list {
|
#prestige-upgrades-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -496,3 +496,27 @@ Wrote a headless Node.js test (`/opt/data/idle-game-test/sound-toggle-test.mjs`)
|
|||||||
- Consider adding a mute-state persistence across slots explicitly tested via the UI (currently preserved in state; could add a dedicated test that switches slots and checks the button).
|
- Consider adding a mute-state persistence across slots explicitly tested via the UI (currently preserved in state; could add a dedicated test that switches slots and checks the button).
|
||||||
- Potential new building tiers or prestige milestones / new prestige upgrades.
|
- Potential new building tiers or prestige milestones / new prestige upgrades.
|
||||||
- Background music track or per-effect volume sliders.
|
- Background music track or per-effect volume sliders.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Session 18 - 2026-08-25 (Morning)
|
||||||
|
**Status:** ✅ Prestige Progress Bar Added
|
||||||
|
|
||||||
|
#### What was done:
|
||||||
|
- Followed up on Sessions 14-17's recurring "prestige milestones" next-goal by adding a **live prestige progress bar** to the Prestige tab. The tab already showed a static "Next prestige: N ✦" number (the essence you'd gain right now), but players had no visual sense of how close they were to earning their next Stellar Essence — a staple idle-game UX element that makes the prestige loop feel rewarding between resets.
|
||||||
|
- New math derived from the existing `PRESTIGE.calculateEssence()` formula: essence level e = floor(sqrt(totalStardust / 1e6)), so tier e begins at e²·1M stardust and tier (e+1) begins at (e+1)²·1M. The bar fills linearly across a tier's stardust range and resets to 0% exactly when a new essence level is reached, so it stays perfectly consistent with `calculateEssence()` (verified: at 999,999 total → 100%, at 1,000,000 → 0% and essence = 1).
|
||||||
|
- Added the DOM in index.html: a `.prestige-progress` block with a "Prestige progress / N%" label row and a `.prestige-progress-bar` track + `.prestige-progress-fill` bar (purple gradient) inserted between the existing "Next prestige" line and the explanatory paragraph.
|
||||||
|
- Added CSS (.prestige-progress, .prestige-progress-label, .prestige-progress-bar, .prestige-progress-fill) matching the existing prestige card theme: purple gradient fill, subtle border, 0.25s ease-out width transition, and a gentle pulsing glow (keyframes `prestigeGlow`) applied only while 0% < progress < 100%, so a freshly-emptied bar sits still after prestige.
|
||||||
|
- Added `PrestigeUI.updatePrestigeProgress()` (read-only: mutates DOM only) and wired it into `PrestigeUI.update()` right after the "Next prestige" number, so the bar refreshes every tick alongside the other prestige stats.
|
||||||
|
|
||||||
|
#### Files modified:
|
||||||
|
- `index.html` - added `.prestige-progress` block (label + percentage + progress bar) in Prestige tab
|
||||||
|
- `css/game.css` - `.prestige-progress*` styles + `.prestige-progress-fill.filling` glow keyframes
|
||||||
|
- `js/prestigeUI.js` - added `updatePrestigeProgress()` method; called it from `update()` each tick
|
||||||
|
|
||||||
|
#### Verification:
|
||||||
|
Wrote a headless Node.js test (`/opt/data/idle-game-test/prestige-progress-bar-test.cjs`) that loads the REAL game.js, prestige.js, and prestigeUI.js in-process via node:vm with DOM/UI/audio/particle stubs. **20/20 checks pass**, covering: empty-state (0%), mid-tier fill (500K→50%, 2M→33%, 6.5M→50%), tier boundary behavior (999,999→100% no glow, 1M→0% reset with essence=1), the glow class toggling correctly (active only while 0<pct<100), monotonicity within tiers with resets allowed only at true boundaries, cross-check against an independent reference implementation at 19 sample points, read-only guarantee (totalStardust unchanged after update), graceful no-crash when DOM elements are absent, and full `PrestigeUI.update()` integration. All modified JS passes `node --check`.
|
||||||
|
|
||||||
|
#### Next goals:
|
||||||
|
- Potential new building tiers or prestige milestones / new prestige upgrades.
|
||||||
|
- Background music track or per-effect volume sliders.
|
||||||
|
|||||||
+10
@@ -92,6 +92,16 @@
|
|||||||
<div class="prestige-next">
|
<div class="prestige-next">
|
||||||
Next prestige: <span id="prestige-next-essence">0</span> ✦
|
Next prestige: <span id="prestige-next-essence">0</span> ✦
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Live progress toward the next Stellar Essence -->
|
||||||
|
<div class="prestige-progress">
|
||||||
|
<div class="prestige-progress-label">
|
||||||
|
Prestige progress
|
||||||
|
<span id="prestige-progress-pct">0%</span>
|
||||||
|
</div>
|
||||||
|
<div class="prestige-progress-bar">
|
||||||
|
<div id="prestige-progress-fill" class="prestige-progress-fill" style="width:0%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<p style="font-size:0.8rem; color:var(--text-muted); margin:8px 0">
|
<p style="font-size:0.8rem; color:var(--text-muted); margin:8px 0">
|
||||||
Requires 1M total stardust for the first ✦. Prestige resets
|
Requires 1M total stardust for the first ✦. Prestige resets
|
||||||
stardust, buildings and upgrades — but keeps essence and
|
stardust, buildings and upgrades — but keeps essence and
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ const PrestigeUI = {
|
|||||||
nextEl.textContent = nextEssence;
|
nextEl.textContent = nextEssence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prestige progress bar: how far total stardust is toward the next
|
||||||
|
// Stellar Essence level. essence(e) = floor(sqrt(totalStardust/1e6)),
|
||||||
|
// so tier e needs e^2*1M stardust and tier (e+1) needs (e+1)^2*1M.
|
||||||
|
this.updatePrestigeProgress();
|
||||||
|
|
||||||
// Update prestige button state
|
// Update prestige button state
|
||||||
const prestigeBtn = document.getElementById('prestige-btn');
|
const prestigeBtn = document.getElementById('prestige-btn');
|
||||||
if (prestigeBtn) {
|
if (prestigeBtn) {
|
||||||
@@ -134,6 +139,35 @@ const PrestigeUI = {
|
|||||||
this.updateBuyMaxPrestigeButton();
|
this.updateBuyMaxPrestigeButton();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the prestige progress bar showing how close total stardust is to
|
||||||
|
* earning the next Stellar Essence. essence level e = floor(sqrt(totalStardust/1e6)),
|
||||||
|
* so tier e begins at e^2*1M and tier (e+1) begins at (e+1)^2*1M; the bar
|
||||||
|
* fills linearly across that tier's stardust range and resets to 0% exactly
|
||||||
|
* when a new essence level is reached. Read-only: mutates only DOM.
|
||||||
|
*/
|
||||||
|
updatePrestigeProgress() {
|
||||||
|
const totalStardust = Game.state.totalStardust || 0;
|
||||||
|
const e = Math.floor(Math.sqrt(totalStardust / 1e6));
|
||||||
|
const tierFloor = e * e * 1e6;
|
||||||
|
const tierCeil = (e + 1) * (e + 1) * 1e6;
|
||||||
|
const progress = Math.min(1, Math.max(0, (totalStardust - tierFloor) / (tierCeil - tierFloor)));
|
||||||
|
|
||||||
|
const fillEl = document.getElementById('prestige-progress-fill');
|
||||||
|
if (fillEl) {
|
||||||
|
const pct = Math.round(progress * 100);
|
||||||
|
fillEl.style.width = `${pct}%`;
|
||||||
|
// Only apply the pulsing glow while there is progress to show, so a
|
||||||
|
// freshly-emptied bar (e.g. right after prestige) sits still.
|
||||||
|
fillEl.classList.toggle('filling', pct > 0 && pct < 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pctLabel = document.getElementById('prestige-progress-pct');
|
||||||
|
if (pctLabel) {
|
||||||
|
pctLabel.textContent = `${Math.round(progress * 100)}%`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show/hide and enable/disable the "Buy Max" prestige-upgrades button
|
* Show/hide and enable/disable the "Buy Max" prestige-upgrades button
|
||||||
* depending on whether at least one unowned, requirement-met prestige
|
* depending on whether at least one unowned, requirement-met prestige
|
||||||
|
|||||||
Reference in New Issue
Block a user