Add VIP+ mode to PIN screen and Play Again options

This commit is contained in:
OpenClaw Engineer 2026-03-05 06:39:06 -06:00
parent be519d515e
commit e106d8ea65
3 changed files with 39 additions and 11 deletions

View File

@ -21,9 +21,12 @@
<label for="startPassword">Password</label> <label for="startPassword">Password</label>
<input id="startPassword" type="password" required placeholder="Enter password" /> <input id="startPassword" type="password" required placeholder="Enter password" />
<label class="inline-option" for="vipMode"> <label for="accessMode">Access Mode</label>
<input id="vipMode" type="checkbox" /> VIP mode (6 hearts) <select id="accessMode">
</label> <option value="standard" selected>Standard (3 hearts)</option>
<option value="vip">VIP (6 hearts)</option>
<option value="vipPlus">VIP+ (9 hearts)</option>
</select>
<label for="difficulty">Difficulty</label> <label for="difficulty">Difficulty</label>
<select id="difficulty"> <select id="difficulty">
@ -49,7 +52,11 @@
<input id="playerName" maxlength="20" required /> <input id="playerName" maxlength="20" required />
<button type="submit">Save Score</button> <button type="submit">Save Score</button>
</form> </form>
<button id="restartBtn">Play Again</button> <div class="play-again-row">
<button id="restartBtn">Play Again</button>
<button id="restartVipBtn" type="button">Play Again (VIP)</button>
<button id="restartVipPlusBtn" type="button">Play Again (VIP+)</button>
</div>
</div> </div>
</div> </div>

View File

@ -8,11 +8,13 @@ const leaderboardEl = document.getElementById('leaderboard');
const saveScoreFormEl = document.getElementById('saveScoreForm'); const saveScoreFormEl = document.getElementById('saveScoreForm');
const playerNameEl = document.getElementById('playerName'); const playerNameEl = document.getElementById('playerName');
const restartBtnEl = document.getElementById('restartBtn'); const restartBtnEl = document.getElementById('restartBtn');
const restartVipBtnEl = document.getElementById('restartVipBtn');
const restartVipPlusBtnEl = document.getElementById('restartVipPlusBtn');
const startScreenEl = document.getElementById('startScreen'); const startScreenEl = document.getElementById('startScreen');
const startFormEl = document.getElementById('startForm'); const startFormEl = document.getElementById('startForm');
const passwordEl = document.getElementById('startPassword'); const passwordEl = document.getElementById('startPassword');
const vipModeEl = document.getElementById('vipMode'); const accessModeEl = document.getElementById('accessMode');
const difficultyEl = document.getElementById('difficulty'); const difficultyEl = document.getElementById('difficulty');
const startErrorEl = document.getElementById('startError'); const startErrorEl = document.getElementById('startError');
@ -60,7 +62,7 @@ const BIOMES = [
]; ];
let audioCtx = null; let audioCtx = null;
let gameConfig = { vipMode: false, difficulty: 'medium' }; let gameConfig = { accessMode: 'standard', difficulty: 'medium' };
function ensureAudioCtx() { function ensureAudioCtx() {
if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
@ -142,8 +144,14 @@ function getBiomeAt(x) {
return BIOMES.find((b) => x >= b.start && x < b.end) || BIOMES[BIOMES.length - 1]; return BIOMES.find((b) => x >= b.start && x < b.end) || BIOMES[BIOMES.length - 1];
} }
function getMaxHearts(accessMode) {
if (accessMode === 'vipPlus') return 9;
if (accessMode === 'vip') return 6;
return 3;
}
function createInitialState(config = gameConfig) { function createInitialState(config = gameConfig) {
const maxHearts = config.vipMode ? 6 : 3; const maxHearts = getMaxHearts(config.accessMode);
return { return {
running: false, running: false,
dead: false, dead: false,
@ -218,7 +226,7 @@ startFormEl.addEventListener('submit', (e) => {
} }
gameConfig = { gameConfig = {
vipMode: vipModeEl.checked, accessMode: accessModeEl.value,
difficulty: difficultyEl.value difficulty: difficultyEl.value
}; };
@ -233,7 +241,8 @@ startFormEl.addEventListener('submit', (e) => {
startErrorEl.textContent = ''; startErrorEl.textContent = '';
}); });
restartBtnEl.addEventListener('click', () => { function restartRun(accessModeOverride = null) {
if (accessModeOverride) gameConfig.accessMode = accessModeOverride;
state = createInitialState(gameConfig); state = createInitialState(gameConfig);
keys.clear(); keys.clear();
deathScreenEl.classList.add('hidden'); deathScreenEl.classList.add('hidden');
@ -242,7 +251,11 @@ restartBtnEl.addEventListener('click', () => {
scoreSavedThisRun = false; scoreSavedThisRun = false;
setSaveFormBusy(false); setSaveFormBusy(false);
state.running = true; state.running = true;
}); }
restartBtnEl.addEventListener('click', () => restartRun());
restartVipBtnEl.addEventListener('click', () => restartRun('vip'));
restartVipPlusBtnEl.addEventListener('click', () => restartRun('vipPlus'));
saveScoreFormEl.addEventListener('submit', async (e) => { saveScoreFormEl.addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
@ -307,7 +320,8 @@ function drawBackground() {
ctx.font = 'bold 20px Arial'; ctx.font = 'bold 20px Arial';
ctx.fillText(`Biome: ${biome.name}`, 18, 70); ctx.fillText(`Biome: ${biome.name}`, 18, 70);
ctx.fillText(`Difficulty: ${gameConfig.difficulty.toUpperCase()}`, 18, 96); ctx.fillText(`Difficulty: ${gameConfig.difficulty.toUpperCase()}`, 18, 96);
ctx.fillText(gameConfig.vipMode ? 'VIP MODE' : 'STANDARD', 18, 122); const modeLabel = gameConfig.accessMode === 'vipPlus' ? 'VIP+ MODE' : gameConfig.accessMode === 'vip' ? 'VIP MODE' : 'STANDARD';
ctx.fillText(modeLabel, 18, 122);
} }
function drawTRex(p) { function drawTRex(p) {

View File

@ -67,6 +67,13 @@ label {
} }
ol { padding-left: 22px; } ol { padding-left: 22px; }
.play-again-row {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
margin-top: 10px;
}
.heart { .heart {
display: inline-block; display: inline-block;
margin-right: 2px; margin-right: 2px;