<!DOCTYPE html>

<html lang="zh-HK">

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

  <title>100層樓的家 - 語文探索之旅</title>

  <style>

    * { box-sizing: border-box; user-select: none; }

    body { margin: 0; padding: 0; background: #e0f2fe; font-family: "PingFang HK", "Microsoft JhengHei", sans-serif; overflow: hidden; }

    #header { position: fixed; top: 0; left: 0; width: 100%; height: 50px; background: rgba(255,255,255,0.9); display: flex; justify-content: space-between; align-items: center; padding: 0 16px; font-size: 1.1rem; font-weight: bold; border-bottom: 2px solid #bae6fd; z-index: 100; }

    #game-container { position: relative; width: 100vw; height: calc(100vh - 140px); margin-top: 50px; overflow: hidden; background: #fdf6e2; }

    .floor { position: absolute; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; background-size: cover; background-position: center; transition: transform 0.6s ease; }

    .ladder { position: absolute; right: 25px; bottom: 0; width: 60px; height: 100%; background: repeating-linear-gradient(0deg, #d97706, #d97706 10px, transparent 10px, transparent 40px); border-left: 6px solid #b45309; border-right: 6px solid #b45309; cursor: pointer; }

    #player { position: absolute; bottom: 10px; left: 60px; width: 70px; height: 85px; transition: left 0.15s linear, bottom 0.2s ease; z-index: 20; }

    #player img { width: 100%; height: 100%; object-fit: contain; }

    #touch-controls { position: fixed; bottom: 0; left: 0; width: 100%; height: 90px; background: #ffffff; display: flex; justify-content: space-around; align-items: center; border-top: 2px solid #cbd5e1; z-index: 100; }

    .btn-ctrl { background: #38bdf8; border: none; border-radius: 12px; color: white; font-size: 1.4rem; font-weight: bold; padding: 12px 24px; box-shadow: 0 4px #0284c7; }

    .btn-ctrl:active { transform: translateY(3px); box-shadow: 0 1px #0284c7; }

    .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 200; justify-content: center; align-items: center; }

    .modal-content { background: #fff; width: 90%; max-width: 520px; border-radius: 20px; padding: 20px; text-align: center; border: 4px solid #38bdf8; position: relative; }

    .btn-difficulty { width: 100%; margin: 8px 0; padding: 14px; font-size: 1.15rem; font-weight: bold; border-radius: 12px; border: none; cursor: pointer; color: white; }

    .btn-easy { background: #22c55e; }

    .btn-medium { background: #f59e0b; }

    .btn-hard { background: #ef4444; }

    .question-box { font-size: 1.25rem; font-weight: bold; margin: 15px 0; color: #1e293b; }

    .options-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 15px; }

    .option-card { background: #f1f5f9; border: 3px solid #94a3b8; border-radius: 12px; padding: 15px 10px; font-size: 1.15rem; font-weight: bold; cursor: pointer; }

    .drop-slot { display: inline-block; min-width: 100px; height: 38px; border-bottom: 3px dashed #0284c7; background: #e0f2fe; margin: 0 4px; vertical-align: middle; border-radius: 4px; line-height: 38px; }

    .word-chip { display: inline-block; background: #fed7aa; border: 2px solid #f97316; padding: 6px 14px; border-radius: 20px; margin: 6px; font-size: 1.1rem; cursor: pointer; font-weight: bold; }

    .btn-voice { background: #ef4444; color: white; border: none; border-radius: 50%; width: 64px; height: 64px; font-size: 1.8rem; margin-top: 10px; cursor: pointer; }

    .btn-hint { background: #a855f7; color: white; border: none; border-radius: 20px; padding: 6px 16px; font-size: 0.95rem; margin-top: 10px; cursor: pointer; }

    #hint-text { margin-top: 8px; color: #7e22ce; font-weight: bold; min-height: 24px; }

  </style>

</head>

<body>


  <div id="header">

    <div id="floor-title">第 1 層:雲朵房間</div>

    <div id="stars-display">⭐ 星星:0</div>

  </div>


  <div id="game-container">

    <div id="floor-view" class="floor">

      <div class="ladder" onclick="triggerDoor()"></div>

      <div id="player">

        <img id="avatar-img" src="avatar.png" alt="主角" onerror="this.src='data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 100 100\'><circle cx=\'50\' cy=\'40\' r=\'25\' fill=\'%23f59e0b\'/><rect x=\'30\' y=\'65\' width=\'40\' height=\'35\' rx=\'10\' fill=\'%233b82f6\'/></svg>'">

      </div>

    </div>

  </div>


  <div id="touch-controls">

    <button class="btn-ctrl" onclick="movePlayer(-30)">◀ 左移</button>

    <button class="btn-ctrl" style="background:#22c55e;" onclick="triggerDoor()">登梯 / 挑戰 ▲</button>

    <button class="btn-ctrl" onclick="movePlayer(30)">右移 ▶</button>

  </div>


  <div id="difficulty-modal" class="modal">

    <div class="modal-content">

      <h2>請選擇挑戰難度</h2>

      <button class="btn-difficulty btn-easy" onclick="startChallenge('easy')">⭐ 普通難度(看圖選詞)</button>

      <button class="btn-difficulty btn-medium" onclick="startChallenge('medium')">⭐⭐ 中等難度(填空造句)</button>

      <button class="btn-difficulty btn-hard" onclick="startChallenge('hard')">⭐⭐⭐ 高難度(語音說話)</button>

    </div>

  </div>


  <div id="task-modal" class="modal">

    <div class="modal-content">

      <div id="task-body"></div>

      <button class="btn-hint" onclick="provideHint()">💡 提示我</button>

      <div id="hint-text"></div>

    </div>

  </div>


<script>

  const gameConfig = [

    {

      floor: 1,

      title: "第 1 層:雲朵房間",

      bgImage: "floor_1.jpg",

      sentenceTemplate: "這裏有一張{adj}的床。",

      hintText: "摸上去好似軟綿綿的雲朵咁樣!",

      easy: {

        question: "這裏有一張怎樣的床?",

        options: [

          { label: "柔軟", icon: "☁️", isCorrect: true },

          { label: "堅硬", icon: "🪨", isCorrect: false }

        ]

      },

      medium: {

        templatePrefix: "這裏有一張",

        templateSuffix: "的床。",

        wordBank: ["柔軟", "冰冷", "可怕"],

        correctWord: "柔軟"

      },

      hard: {

        question: "主角來到了一個怎樣的房間?請用粵語講出完整的句子:",

        keywords: ["柔軟", "舒服", "大", "雲"],

        example: "這裏有一張柔軟的床。"

      }

    },

    {

      floor: 2,

      title: "第 2 層:彩虹花園",

      bgImage: "floor_2.jpg",

      sentenceTemplate: "房間裏開滿了{adj}的花朵。",

      hintText: "花朵有好多鮮艷的顏色!",

      easy: {

        question: "房間裏開滿了怎樣的花朵?",

        options: [

          { label: "美麗", icon: "🌸", isCorrect: true },

          { label: "漆黑", icon: "⬛", isCorrect: false }

        ]

      },

      medium: {

        templatePrefix: "房間裏開滿了",

        templateSuffix: "的花朵。",

        wordBank: ["美麗", "寒冷", "吵鬧"],

        correctWord: "美麗"

      },

      hard: {

        question: "請形容這個房間的花朵:",

        keywords: ["美麗", "鮮艷", "五顏六色", "彩虹"],

        example: "房間裏開滿了美麗的花朵。"

      }

    }

  ];


  let currentFloorIndex = 0;

  let playerX = 60;

  let stars = 0;

  let selectedLevel = 'easy';


  function playTone(freq, duration = 0.15) {

    try {

      const ctx = new (window.AudioContext || window.webkitAudioContext)();

      const osc = ctx.createOscillator();

      const gain = ctx.createGain();

      osc.frequency.value = freq;

      osc.connect(gain);

      gain.connect(ctx.destination);

      osc.start();

      gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + duration);

      osc.stop(ctx.currentTime + duration);

    } catch (e) {}

  }


  function speakCantonese(text) {

    if ('speechSynthesis' in window) {

      window.speechSynthesis.cancel();

      const utterance = new SpeechSynthesisUtterance(text);

      utterance.lang = 'zh-HK';

      utterance.rate = 0.9;

      window.speechSynthesis.speak(utterance);

    }

  }


  function movePlayer(offset) {

    const containerWidth = window.innerWidth;

    playerX = Math.max(20, Math.min(containerWidth - 90, playerX + offset));

    document.getElementById('player').style.left = playerX + 'px';

  }


  window.addEventListener('keydown', (e) => {

    if (e.key === 'ArrowLeft') movePlayer(-30);

    if (e.key === 'ArrowRight') movePlayer(30);

    if (e.key === 'ArrowUp' || e.key === 'Enter') triggerDoor();

  });


  function triggerDoor() {

    document.getElementById('difficulty-modal').style.display = 'flex';

  }


  function startChallenge(level) {

    selectedLevel = level;

    document.getElementById('difficulty-modal').style.display = 'none';

    document.getElementById('hint-text').innerText = '';

    const cfg = gameConfig[currentFloorIndex];

    const modal = document.getElementById('task-modal');

    const body = document.getElementById('task-body');


    if (level === 'easy') {

      speakCantonese(cfg.easy.question);

      body.innerHTML = `

        <div class="question-box">🔊 ${cfg.easy.question}</div>

        <div class="options-grid">

          ${cfg.easy.options.map(opt => `

            <div class="option-card" onclick="checkAnswer(${opt.isCorrect})">

              <div style="font-size:2.2rem;">${opt.icon}</div>

              <div>${opt.label}</div>

            </div>

          `).join('')}

        </div>

      `;

    } else if (level === 'medium') {

      speakCantonese(cfg.medium.templatePrefix + "甚麼" + cfg.medium.templateSuffix);

      body.innerHTML = `

        <div class="question-box">${cfg.medium.templatePrefix} <span id="target-slot" class="drop-slot"></span> ${cfg.medium.templateSuffix}</div>

        <div style="margin-top:15px;">

          ${cfg.medium.wordBank.map(w => `<span class="word-chip" onclick="fillWord('${w}', '${cfg.medium.correctWord}')">${w}</span>`).join('')}

        </div>

      `;

    } else if (level === 'hard') {

      speakCantonese(cfg.hard.question);

      body.innerHTML = `

        <div class="question-box">🎤 ${cfg.hard.question}</div>

        <p style="color:#64748b; font-size:0.95rem;">點擊麥克風說出答案,或直接鍵入:</p>

        <button class="btn-voice" onclick="startSpeechRec()">🎙️</button>

        <div style="margin-top:10px;">

          <input type="text" id="manual-input" style="width:75%; padding:8px; font-size:1rem; border-radius:6px; border:1px solid #cbd5e1;" placeholder="語音辨識結果或手動輸入...">

          <button style="padding:8px 12px; border-radius:6px; border:none; background:#38bdf8; color:white; font-weight:bold;" onclick="checkHardAnswer(document.getElementById('manual-input').value)">確定</button>

        </div>

      `;

    }

    modal.style.display = 'flex';

  }


  function fillWord(word, correctWord) {

    document.getElementById('target-slot').innerText = word;

    setTimeout(() => checkAnswer(word === correctWord), 350);

  }


  function startSpeechRec() {

    const SpeechRec = window.SpeechRecognition || window.webkitSpeechRecognition;

    if (!SpeechRec) {

      alert("瀏覽器未支援語音識別,請直接於文字框輸入回答。");

      return;

    }

    const rec = new SpeechRec();

    rec.lang = 'zh-HK';

    rec.onresult = (e) => {

      const text = e.results[0][0].transcript;

      document.getElementById('manual-input').value = text;

      checkHardAnswer(text);

    };

    rec.start();

  }


  function checkHardAnswer(text) {

    const keywords = gameConfig[currentFloorIndex].hard.keywords;

    const isHit = keywords.some(k => text.includes(k));

    checkAnswer(isHit);

  }


  function provideHint() {

    const hint = gameConfig[currentFloorIndex].hintText;

    document.getElementById('hint-text').innerText = "💡 提示:" + hint;

    speakCantonese("提示:" + hint);

  }


  function checkAnswer(isCorrect) {

    if (isCorrect) {

      playTone(523.25); setTimeout(() => playTone(659.25), 100); setTimeout(() => playTone(783.99), 200);

      stars += (selectedLevel === 'hard' ? 3 : (selectedLevel === 'medium' ? 2 : 1));

      document.getElementById('stars-display').innerText = "⭐ 星星:" + stars;

      speakCantonese("答啱咗喇!好叻呀!");

      alert("🎉 答對了!獲得星星!");

      document.getElementById('task-modal').style.display = 'none';

      nextFloor();

    } else {

      playTone(220, 0.25);

      speakCantonese("唔緊要,再試一次啦!或者按提示按鈕。");

      alert("差少少,再試一次或按提示按鈕睇睇!");

    }

  }


  function nextFloor() {

    if (currentFloorIndex < gameConfig.length - 1) {

      currentFloorIndex++;

      const cfg = gameConfig[currentFloorIndex];

      document.getElementById('floor-title').innerText = cfg.title;

      document.getElementById('floor-view').style.backgroundImage = `url('${cfg.bgImage}')`;

      playerX = 60;

      document.getElementById('player').style.left = playerX + 'px';

    } else {

      alert("🏆 太厲害了!你已經完成所有樓層的挑戰,成為描寫小達人!");

    }

  }


  window.onload = () => {

    const firstCfg = gameConfig[0];

    document.getElementById('floor-view').style.backgroundImage = `url('${firstCfg.bgImage}')`;

  };

</script>

</body>

</html>