Math_Adventure_8thgrade / gemstone.html
Lashtw's picture
Upload 5 files
c0b6856 verified
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>數學探險島 - 寶石洞窟</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Noto Sans TC', sans-serif;
background-image: url('https://i.meee.com.tw/pI0c5ue.png');
background-size: cover;
background-position: center;
}
canvas {
background-color: #2d241d;
display: block;
border-radius: 0.5rem;
box-shadow: inset 0 0 20px rgba(0,0,0,0.5);
}
.action-button {
transition: all 0.2s ease-in-out;
box-shadow: 0 5px #995f00;
}
.action-button:active {
transform: translateY(3px);
box-shadow: 0 2px #995f00;
}
.move-button {
transition: all 0.2s ease-in-out;
box-shadow: 0 5px #1e3a8a;
}
.move-button:active {
transform: translateY(3px);
box-shadow: 0 2px #1e3a8a;
}
.gem-button {
transition: transform 0.1s ease-in-out;
}
.gem-button:active {
transform: scale(0.9);
}
.secret-bg {
background-image: url('https://i.meee.com.tw/EKZpYKI.png');
background-size: cover;
background-position: center;
}
</style>
</head>
<body class="flex items-center justify-center h-screen overflow-hidden">
<div id="container" class="w-full max-w-md mx-auto text-white p-4 flex flex-col h-full">
<!-- 引導畫面 -->
<div id="start-screen" class="flex flex-col items-center justify-center text-center p-8 bg-black bg-opacity-60 rounded-lg my-auto">
<h1 class="text-4xl font-bold text-amber-300 mb-4">寶石洞窟</h1>
<p class="text-lg text-gray-200 mb-8">這是一個已經廢棄的寶石洞窟,接下來你必須駕駛一台礦車,成功閃避障礙物來獲得璀璨寶石!</p>
<button id="start-button" class="action-button bg-amber-500 hover:bg-amber-600 text-gray-900 font-bold py-4 px-8 rounded-lg text-2xl">
開始採礦
</button>
</div>
<!-- 遊戲畫面 -->
<div id="game-screen" class="hidden flex-col h-full">
<div id="canvas-wrapper" class="relative">
<canvas id="gameCanvas"></canvas>
<!-- 操作說明畫面 -->
<div id="instructions-screen" class="hidden absolute inset-0 bg-black bg-opacity-80 flex flex-col items-center justify-center text-center p-4 rounded-lg">
<h2 class="text-3xl font-bold text-amber-300 mb-6">操作說明</h2>
<div class="space-y-4 text-lg">
<p>點擊畫面<span class="text-blue-400 font-bold">左半邊</span>或按<span class="text-blue-400 font-bold">左方向鍵</span> ← 向左移動</p>
<p>點擊畫面<span class="text-blue-400 font-bold">右半邊</span>或按<span class="text-blue-400 font-bold">右方向鍵</span> → 向右移動</p>
<p class="mt-4">也可以使用下方的按鈕操作!</p>
</div>
<button id="play-game-button" class="action-button bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-8 rounded-lg text-xl mt-8">
了解!
</button>
</div>
<!-- 遊戲結束畫面 -->
<div id="game-over-screen" class="hidden absolute inset-0 bg-black bg-opacity-70 flex flex-col items-center justify-center text-center p-4 rounded-lg">
<h2 class="text-4xl font-bold text-red-500 mb-4">挑戰失敗!</h2>
<p class="text-xl mb-6">礦車撞毀了!</p>
<button id="restart-button" class="action-button bg-amber-500 hover:bg-amber-600 text-gray-900 font-bold py-3 px-6 rounded-lg text-xl">
重新挑戰
</button>
</div>
<!-- 遊戲獲勝畫面 -->
<div id="win-screen" class="hidden absolute inset-0 bg-black bg-opacity-70 flex flex-col items-center justify-center text-center p-4 rounded-lg">
<h2 class="text-4xl font-bold text-green-400 mb-4">成功!</h2>
<p class="text-xl mb-2">你成功抵達了寶石區域!</p>
<p id="win-perfect-dodges" class="text-2xl text-amber-300 font-bold mb-6"></p>
<button id="continue-button" class="action-button bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg text-xl">
繼續前進
</button>
</div>
</div>
<!-- 移動按鈕 -->
<div id="controls" class="flex justify-between mt-4">
<button id="move-left-button" class="move-button bg-blue-600 hover:bg-blue-700 text-white font-bold p-4 rounded-lg w-24 h-16">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 mx-auto" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" /></svg>
</button>
<button id="move-right-button" class="move-button bg-blue-600 hover:bg-blue-700 text-white font-bold p-4 rounded-lg w-24 h-16">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 mx-auto" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
</button>
</div>
</div>
<!-- 寶石解謎畫面 -->
<div id="puzzle-screen" class="hidden flex-col h-full p-6 bg-black bg-opacity-60 rounded-lg">
<div class="flex-grow overflow-y-auto">
<h1 class="text-3xl font-bold text-amber-300 text-center mb-4">寶石組合挑戰</h1>
<p class="text-center mb-4">觀察大寶石,點擊下方的小寶石,組合出正確的配方!</p>
<div class="flex justify-center mb-4">
<img id="large-gem-image" src="" class="h-40 object-contain" alt="[大寶石的Image]">
</div>
<div id="answer-slots" class="bg-gray-900/50 min-h-[80px] rounded-lg p-2 flex flex-wrap items-center justify-center gap-2 mb-4 border-2 border-amber-400"></div>
<div id="small-gem-options" class="flex justify-center items-center gap-4 mb-6 flex-wrap"></div>
<div id="puzzle-feedback" class="text-center text-xl font-bold min-h-[32px] mb-4"></div>
</div>
<div class="flex gap-4 mt-auto pt-4">
<button id="reset-puzzle-button" class="w-1/2 bg-gray-500 hover:bg-gray-600 text-white font-bold py-3 rounded-lg">重置</button>
<button id="check-puzzle-button" class="w-1/2 bg-green-500 hover:bg-green-600 text-white font-bold py-3 rounded-lg">鑑定寶石</button>
</div>
</div>
<!-- 過場畫面 -->
<div id="intermission-screen" class="hidden flex-col text-center p-8 bg-black bg-opacity-60 rounded-lg my-auto">
<h1 class="text-3xl font-bold text-amber-300 mb-4">準備挑戰下一區!</h1>
<p class="text-lg text-gray-200 mb-8">前方的礦道更加危險,速度會更快!</p>
<button id="start-next-stage-button" class="action-button bg-amber-500 hover:bg-amber-600 text-gray-900 font-bold py-4 px-8 rounded-lg text-2xl">
繼續採礦
</button>
</div>
<!-- 最終通關畫面 -->
<div id="final-win-screen" class="hidden flex-col text-center p-8 bg-black bg-opacity-60 rounded-lg my-auto">
<h1 class="text-4xl font-bold text-green-400 mb-4">恭喜你完成所有寶石挑戰!</h1>
<button id="unlock-secret-button" class="action-button bg-purple-600 hover:bg-purple-700 text-white font-bold py-4 px-8 rounded-lg text-2xl">
解鎖寶石洞窟的秘密
</button>
</div>
</div>
<!-- 秘密揭曉畫面 (獨立於 container 之外) -->
<div id="secret-screen" class="hidden absolute inset-0 w-screen h-screen secret-bg p-8 text-white flex-col items-center justify-center">
<div class="w-full max-w-2xl bg-black bg-opacity-70 p-8 rounded-xl">
<div id="secret-question">
<h2 class="text-3xl font-bold text-amber-300 mb-6">你認為這個洞窟的秘密是...</h2>
<div class="space-y-4 text-lg">
<button data-choice="A" class="secret-choice w-full text-left p-4 bg-white/10 hover:bg-white/20 rounded-lg transition-colors">A. 如何完美駕駛礦車,一次通關</button>
<button data-choice="B" class="secret-choice w-full text-left p-4 bg-white/10 hover:bg-white/20 rounded-lg transition-colors">B. 如何增加完美閃避的次數</button>
<button data-choice="C" class="secret-choice w-full text-left p-4 bg-white/10 hover:bg-white/20 rounded-lg transition-colors">C. 寶石分析術</button>
</div>
<p id="secret-feedback" class="mt-6 min-h-[28px] text-xl"></p>
</div>
<div id="secret-reveal" class="hidden text-left space-y-4">
<p class="text-lg">從最小的寶石到浩瀚的星辰,萬事萬物都由更基本的元素構成。你學會的『寶石分析術』,在數學的世界裡,它被稱為『因式分解』。</p>
<p class="text-2xl font-bold text-amber-300">這個洞窟的秘密就是:學會分析與拆解,就是看透事物本質的第一步。</p>
<p class="text-lg">無論是分析一顆寶石的成分、一道數學題的結構,還是未來你遇到的任何複雜問題,這種化繁為簡的智慧,才是你從這裡帶走、永不消失的真正寶藏。</p>
</div>
<div class="mt-12 text-center">
<a href="index.html" id="back-to-map-button" class="action-button inline-block bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-8 rounded-lg text-xl">
回到探險島地圖
</a>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// --- 畫面元素 ---
const container = document.getElementById('container');
const startScreen = document.getElementById('start-screen');
const gameScreen = document.getElementById('game-screen');
const puzzleScreen = document.getElementById('puzzle-screen');
const intermissionScreen = document.getElementById('intermission-screen');
const finalWinScreen = document.getElementById('final-win-screen');
const secretScreen = document.getElementById('secret-screen');
const startButton = document.getElementById('start-button');
const instructionsScreen = document.getElementById('instructions-screen');
const playGameButton = document.getElementById('play-game-button');
const gameOverScreen = document.getElementById('game-over-screen');
const winScreen = document.getElementById('win-screen');
const winPerfectDodges = document.getElementById('win-perfect-dodges');
const restartButton = document.getElementById('restart-button');
const continueButton = document.getElementById('continue-button');
const startNextStageButton = document.getElementById('start-next-stage-button');
const unlockSecretButton = document.getElementById('unlock-secret-button');
const canvas = document.getElementById('gameCanvas');
const canvasWrapper = document.getElementById('canvas-wrapper');
const moveLeftButton = document.getElementById('move-left-button');
const moveRightButton = document.getElementById('move-right-button');
const ctx = canvas.getContext('2d');
// --- 寶石解謎元素 ---
const largeGemImage = document.getElementById('large-gem-image');
const answerSlots = document.getElementById('answer-slots');
const smallGemOptions = document.getElementById('small-gem-options');
const puzzleFeedback = document.getElementById('puzzle-feedback');
const resetPuzzleButton = document.getElementById('reset-puzzle-button');
const checkPuzzleButton = document.getElementById('check-puzzle-button');
// --- 秘密揭曉元素 ---
const secretQuestion = document.getElementById('secret-question');
const secretReveal = document.getElementById('secret-reveal');
const secretFeedback = document.getElementById('secret-feedback');
const secretChoiceButtons = document.querySelectorAll('.secret-choice');
// --- 遊戲設定 ---
const LANE_COUNT = 3;
let laneWidth;
let gameInterval, timer, obstacleInterval;
let timeLeft;
let perfectDodges = 0;
const perfectDodgeTexts = [];
let keySequence = [];
const cheatCode = "kkkkk";
let currentStage = 0;
let currentStageSettings;
const gameStages = [
{ speed: 2.5, time: 20, spawnRate: 1800 },
{ speed: 3.5, time: 15, spawnRate: 1200 },
{ speed: 4.0, time: 12, spawnRate: 1000 }
];
// --- 寶石解謎設定 ---
const allSmallGems = [
{ id: 1, src: 'https://i.meee.com.tw/FeaxgIn.png' },
{ id: 2, src: 'https://i.meee.com.tw/VgnnNxo.png' },
{ id: 3, src: 'https://i.meee.com.tw/5vu7Qk1.png' },
{ id: 4, src: 'https://i.meee.com.tw/eoel84q.png' },
{ id: 5, src: 'https://i.meee.com.tw/b2uL22E.png' },
{ id: 6, src: 'https://i.meee.com.tw/HeduyDE.png' },
{ id: 7, src: 'https://i.meee.com.tw/2gorePd.png' },
{ id: 8, src: 'https://i.meee.com.tw/HNNEM09.png' },
{ id: 9, src: 'https://i.meee.com.tw/cpw8ccy.png' },
{ id: 10, src: 'https://i.meee.com.tw/Rk8hY7H.png' }
];
const puzzleLevels = [
{
largeGemSrc: 'https://i.meee.com.tw/PU1busV.png',
options: [1, 2, 3],
answer: { 1: 1, 2: 3, 3: 1 },
maxGems: 5
},
{
largeGemSrc: 'https://i.meee.com.tw/JCK7B2S.png',
options: [2, 3, 4, 5, 6, 7],
answer: { 3: 2, 7: 2, 2: 1, 4: 1, 5: 1, 6: 1 },
maxGems: 8
},
{
largeGemSrc: 'https://i.meee.com.tw/wFJquPy.png',
options: [2, 3, 4, 5, 6, 8, 9, 10],
answer: { 8: 3, 10: 3, 5: 6, 9: 1 },
maxGems: 13
}
];
let playerSelection = {};
// --- 玩家設定 ---
const player = {
x: 0, y: 0, width: 100, height: 100, lane: 1, image: new Image()
};
const normalCartSrc = 'https://i.meee.com.tw/w6krwUz.png';
const crashedCartSrc = 'https://i.meee.com.tw/4wSy5uX.png';
player.image.src = normalCartSrc;
player.image.onerror = () => { console.error("礦車圖片載入失敗!"); };
// --- 障礙物設定 ---
const obstacles = [];
const trackTies = [];
const obstacleImage = new Image();
obstacleImage.src = 'https://i.meee.com.tw/L0tV6le.png';
obstacleImage.onerror = () => { console.error("障礙物圖片載入失敗!"); };
let lastTieY = 0;
const TIE_SPACING = 50;
// --- 畫面管理 ---
function showScreen(screenId) {
['start-screen', 'game-screen', 'puzzle-screen', 'intermission-screen', 'final-win-screen'].forEach(id => {
const screen = document.getElementById(id);
if (id === screenId) {
screen.style.display = 'flex';
screen.classList.remove('hidden');
if(id === 'start-screen' || id === 'intermission-screen' || id === 'final-win-screen') {
screen.classList.add('my-auto');
} else {
screen.classList.remove('my-auto');
}
} else {
screen.style.display = 'none';
screen.classList.add('hidden');
}
});
}
// --- 礦車遊戲函式 ---
function resizeCanvas() {
const container = document.getElementById('container');
const controls = document.getElementById('controls');
canvas.width = container.clientWidth;
canvas.height = window.innerHeight * 0.9 - controls.offsetHeight - 20;
canvasWrapper.style.width = `${canvas.width}px`;
canvasWrapper.style.height = `${canvas.height}px`;
laneWidth = canvas.width / LANE_COUNT;
player.y = canvas.height - player.height - 10;
}
function getLaneCenterX(lane) {
return (lane * laneWidth) + (laneWidth / 2);
}
function spawnTrackTies() {
while (lastTieY < canvas.height + TIE_SPACING) {
trackTies.push({ y: lastTieY });
lastTieY += TIE_SPACING;
}
}
function drawTrack() {
ctx.fillStyle = '#57402c';
trackTies.forEach(tie => {
for (let i = 0; i < LANE_COUNT; i++) {
const laneX = getLaneCenterX(i);
const rail1X = laneX - laneWidth * 0.25;
const rail2X = laneX + laneWidth * 0.25;
ctx.fillRect(rail1X, tie.y, rail2X - rail1X, 10);
}
});
const railColor = '#858585', highlightColor = '#b0b0b0', railWidth = 8;
for (let i = 0; i < LANE_COUNT; i++) {
const laneX = getLaneCenterX(i);
const rail1X = laneX - laneWidth * 0.25;
const rail2X = laneX + laneWidth * 0.25;
ctx.fillStyle = railColor;
ctx.fillRect(rail1X - railWidth / 2, 0, railWidth, canvas.height);
ctx.fillRect(rail2X - railWidth / 2, 0, railWidth, canvas.height);
ctx.fillStyle = highlightColor;
ctx.fillRect(rail1X - railWidth / 2, 0, railWidth / 2, canvas.height);
ctx.fillRect(rail2X - railWidth / 2, 0, railWidth / 2, canvas.height);
}
}
function drawPlayer() {
player.x = getLaneCenterX(player.lane) - player.width / 2;
if (player.image.complete && player.image.naturalHeight !== 0) {
ctx.drawImage(player.image, player.x, player.y, player.width, player.height);
} else {
ctx.fillStyle = 'blue';
ctx.fillRect(player.x, player.y, player.width, player.height);
}
}
function drawObstacles() {
obstacles.forEach(obstacle => {
if (obstacleImage.complete && obstacleImage.naturalHeight !== 0) {
ctx.drawImage(obstacleImage, obstacle.x, obstacle.y, obstacle.width, obstacle.height);
} else {
ctx.fillStyle = '#a16207';
ctx.beginPath();
ctx.roundRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height, [10]);
ctx.fill();
}
});
}
function drawUI() {
ctx.fillStyle = 'white';
ctx.font = 'bold 20px "Noto Sans TC"';
ctx.textAlign = 'center';
ctx.fillText(`倒數計時: ${timeLeft.toFixed(1)} 秒`, canvas.width / 2, 30);
ctx.textAlign = 'right';
ctx.fillText(`完美閃避: ${perfectDodges}`, canvas.width - 20, 30);
perfectDodgeTexts.forEach(text => {
ctx.save();
ctx.globalAlpha = text.alpha;
ctx.fillStyle = '#fde047';
ctx.font = 'bold 24px "Noto Sans TC"';
ctx.textAlign = 'center';
ctx.fillText(text.text, text.x, text.y);
ctx.restore();
});
}
function update() {
for (let i = trackTies.length - 1; i >= 0; i--) {
trackTies[i].y += currentStageSettings.speed;
if (trackTies[i].y > canvas.height) {
trackTies.splice(i, 1);
trackTies.unshift({ y: (trackTies[0]?.y || 0) - TIE_SPACING });
}
}
for (let i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].y += currentStageSettings.speed;
if (obstacles[i].y > canvas.height) obstacles.splice(i, 1);
}
for (let i = perfectDodgeTexts.length - 1; i >= 0; i--) {
perfectDodgeTexts[i].y -= 1;
perfectDodgeTexts[i].alpha -= 0.02;
if (perfectDodgeTexts[i].alpha <= 0) perfectDodgeTexts.splice(i, 1);
}
obstacles.forEach(obstacle => {
if (player.lane === obstacle.lane && player.y < obstacle.y + obstacle.height && player.y + player.height > obstacle.y) {
gameOver();
}
});
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawTrack();
drawObstacles();
drawPlayer();
drawUI();
}
function spawnObstacle() {
const lane = Math.floor(Math.random() * LANE_COUNT);
const size = laneWidth * 0.5;
const x = getLaneCenterX(lane) - size / 2;
obstacles.push({ x, y: -size, width: size, height: size, lane, dodged: false });
}
function gameLoop() {
update();
draw();
gameInterval = requestAnimationFrame(gameLoop);
}
function stopGame() {
if (gameInterval) cancelAnimationFrame(gameInterval);
if (timer) clearInterval(timer);
if (obstacleInterval) clearInterval(obstacleInterval);
gameInterval = timer = obstacleInterval = null;
}
function startGame(stageIndex) {
currentStage = stageIndex;
currentStageSettings = gameStages[stageIndex];
player.image.src = normalCartSrc; // Reset to normal cart image
stopGame();
instructionsScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
winScreen.classList.add('hidden');
resizeCanvas();
obstacles.length = 0;
trackTies.length = 0;
perfectDodgeTexts.length = 0;
perfectDodges = 0;
lastTieY = 0;
spawnTrackTies();
player.lane = 1;
timeLeft = currentStageSettings.time;
timer = setInterval(() => {
timeLeft -= 0.1;
if (timeLeft <= 0) {
timeLeft = 0;
winGame();
}
}, 100);
obstacleInterval = setInterval(spawnObstacle, currentStageSettings.spawnRate);
gameLoop();
}
function gameOver() {
stopGame();
player.image.src = crashedCartSrc; // Change to crashed cart image
draw(); // Redraw canvas one last time with the new image
gameOverScreen.classList.remove('hidden');
}
function winGame() {
stopGame();
winPerfectDodges.textContent = `完美閃避: ${perfectDodges} 次`;
winScreen.classList.remove('hidden');
}
function handleMove(direction) {
if (!gameInterval) return;
const oldLane = player.lane;
let newLane = player.lane;
if (direction === 'left') newLane = Math.max(0, player.lane - 1);
else if (direction === 'right') newLane = Math.min(LANE_COUNT - 1, player.lane + 1);
if (oldLane !== newLane) {
player.lane = newLane;
checkPerfectDodge(oldLane);
}
}
function checkPerfectDodge(fromLane) {
const perfectDodgeZoneTop = player.y - player.height / 2;
const perfectDodgeZoneBottom = player.y + player.height;
obstacles.forEach(obstacle => {
if (obstacle.lane === fromLane && !obstacle.dodged) {
if (obstacle.y + obstacle.height > perfectDodgeZoneTop && obstacle.y < perfectDodgeZoneBottom) {
perfectDodges++;
obstacle.dodged = true;
perfectDodgeTexts.push({ text: '完美!', x: getLaneCenterX(fromLane), y: player.y, alpha: 1 });
}
}
});
}
// --- 寶石解謎函式 ---
function showPuzzleScreen() {
showScreen('puzzle-screen');
loadPuzzleLevel(currentStage);
}
function loadPuzzleLevel(levelIndex) {
const level = puzzleLevels[levelIndex];
largeGemImage.src = level.largeGemSrc;
smallGemOptions.innerHTML = '';
level.options.forEach(gemId => {
const gemData = allSmallGems.find(g => g.id === gemId);
if (gemData) {
const gemBtn = document.createElement('button');
gemBtn.className = 'gem-button';
gemBtn.innerHTML = `<img src="${gemData.src}" alt="小寶石 ${gemData.id}" class="h-16 w-16 object-contain">`;
gemBtn.onclick = () => addGemToSelection(gemData);
smallGemOptions.appendChild(gemBtn);
}
});
resetPuzzle();
}
function addGemToSelection(gem) {
const currentTotal = Object.values(playerSelection).reduce((sum, count) => sum + count, 0);
const level = puzzleLevels[currentStage];
if (currentTotal >= level.maxGems) {
puzzleFeedback.textContent = '數量太多了喔!';
puzzleFeedback.className = 'text-center text-xl font-bold min-h-[32px] mb-4 text-yellow-400';
setTimeout(() => {
if(puzzleFeedback.textContent === '數量太多了喔!') {
puzzleFeedback.textContent = '';
}
}, 2000);
return;
}
playerSelection[gem.id] = (playerSelection[gem.id] || 0) + 1;
renderSelection();
}
function removeGemFromSelection(gemId) {
if (playerSelection[gemId]) {
playerSelection[gemId]--;
if (playerSelection[gemId] === 0) {
delete playerSelection[gemId];
}
}
renderSelection();
}
function renderSelection() {
answerSlots.innerHTML = '';
puzzleLevels[currentStage].options.forEach(gemId => {
const gemData = allSmallGems.find(g => g.id === gemId);
if (playerSelection[gemId]) {
const count = playerSelection[gemId];
for (let i = 0; i < count; i++) {
const img = document.createElement('img');
img.src = gemData.src;
img.alt = `[已選擇的小寶石 ${gemData.id}]`;
img.className = 'h-12 w-12 object-contain cursor-pointer';
img.onclick = () => removeGemFromSelection(gemId);
answerSlots.appendChild(img);
}
}
});
}
function resetPuzzle() {
playerSelection = {};
answerSlots.innerHTML = '';
puzzleFeedback.textContent = '';
}
function checkPuzzleAnswer() {
const level = puzzleLevels[currentStage];
if (!level) return;
const answer = level.answer;
let correct = true;
if (Object.keys(playerSelection).length !== Object.keys(answer).length) {
correct = false;
} else {
for (const gemId in answer) {
if (playerSelection[gemId] !== answer[gemId]) {
correct = false;
break;
}
}
}
if (correct) {
puzzleFeedback.textContent = '組合正確!你獲得了大寶石!';
puzzleFeedback.className = 'text-center text-xl font-bold min-h-[32px] mb-4 text-green-400';
setTimeout(() => {
const nextStage = currentStage + 1;
if (nextStage < puzzleLevels.length) {
showScreen('intermission-screen');
} else {
showScreen('final-win-screen');
}
}, 1500);
} else {
puzzleFeedback.textContent = '組合不對喔,再試一次!';
puzzleFeedback.className = 'text-center text-xl font-bold min-h-[32px] mb-4 text-red-500';
}
}
// --- 事件監聽 ---
startButton.addEventListener('click', () => {
showScreen('game-screen');
resizeCanvas();
instructionsScreen.classList.remove('hidden');
});
playGameButton.addEventListener('click', () => startGame(0));
restartButton.addEventListener('click', () => startGame(currentStage));
continueButton.addEventListener('click', showPuzzleScreen);
startNextStageButton.addEventListener('click', () => {
showScreen('game-screen');
startGame(currentStage + 1);
});
resetPuzzleButton.addEventListener('click', resetPuzzle);
checkPuzzleButton.addEventListener('click', checkPuzzleAnswer);
unlockSecretButton.addEventListener('click', () => {
container.style.display = 'none';
secretScreen.style.display = 'flex';
});
secretChoiceButtons.forEach(button => {
button.addEventListener('click', () => {
const choice = button.dataset.choice;
secretFeedback.classList.remove('text-yellow-400', 'text-green-400');
if (choice === 'C') {
secretFeedback.textContent = '';
secretQuestion.style.display = 'none';
secretReveal.style.display = 'block';
} else if (choice === 'A') {
secretFeedback.textContent = '駕駛技術固然重要,但那只是過程喔!';
secretFeedback.classList.add('text-yellow-400');
} else {
secretFeedback.textContent = '閃避只是手段,不是目的呀!';
secretFeedback.classList.add('text-yellow-400');
}
});
});
window.addEventListener('resize', resizeCanvas);
window.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') handleMove('left');
else if (e.key === 'ArrowRight') handleMove('right');
if (gameInterval) {
keySequence.push(e.key);
keySequence = keySequence.slice(-cheatCode.length);
if (keySequence.join('') === cheatCode) {
winGame();
}
}
});
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const clickX = e.clientX - rect.left;
if (clickX < canvas.width / 2) handleMove('left');
else handleMove('right');
});
moveLeftButton.addEventListener('click', () => handleMove('left'));
moveRightButton.addEventListener('click', () => handleMove('right'));
// --- 初始啟動 ---
showScreen('start-screen');
});
</script>
</body>
</html>