Add VIP+ mode to PIN screen and Play Again options
This commit is contained in:
parent
be519d515e
commit
e106d8ea65
15
index.php
15
index.php
@ -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>
|
||||||
|
|
||||||
|
|||||||
28
js/game.js
28
js/game.js
@ -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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user