Lashtw commited on
Commit
316ba76
·
verified ·
1 Parent(s): af802e1

Upload 2 files

Browse files
Files changed (2) hide show
  1. function.html +141 -10
  2. sequence.html +401 -248
function.html CHANGED
@@ -103,6 +103,69 @@
103
  -ms-overflow-style: none;
104
  scrollbar-width: none;
105
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  </style>
107
  </head>
108
 
@@ -176,12 +239,78 @@
176
  <div>Designed by L.Star</div>
177
  </div>
178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  <script>
180
- // --- Game Constants & State ---
181
  const canvas = document.getElementById('gameCanvas');
182
  const ctx = canvas.getContext('2d');
183
  let width, height;
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  // Formula: y = ax + b
186
  let currentA = 2;
187
  let currentB = 3;
@@ -612,7 +741,7 @@
612
  <div class="flex items-center justify-center gap-2 flex-grow">
613
  <span class="font-tech text-3xl text-cyan-400">y = </span>
614
  <div class="relative w-32">
615
- <input id="ans-input" type="number" class="tech-input w-full p-2 text-3xl rounded-lg" placeholder="?" autofocus>
616
  <div class="absolute inset-0 border-2 border-slate-500/50 rounded-lg pointer-events-none"></div>
617
  </div>
618
  </div>
@@ -746,7 +875,9 @@
746
  </p>
747
  <div class="flex items-center gap-2 mt-4 bg-slate-800/50 p-4 rounded-xl flex-wrap">
748
  <span class="font-tech text-amber-400 text-4xl whitespace-nowrap">x = </span>
749
- <input id="ans-input" type="number" class="tech-input flex-1 min-w-[100px] p-2 rounded text-4xl text-amber-400" placeholder="?" autofocus>
 
 
750
  <button onclick="checkFinalAnswer()" class="px-6 py-3 bg-red-600 hover:bg-red-500 text-white rounded font-bold shadow-[0_0_15px_rgba(239,68,68,0.5)] whitespace-nowrap flex-shrink-0">
751
  投入晶石
752
  </button>
@@ -844,7 +975,7 @@
844
  </p>
845
  <div class="flex items-center justify-center gap-2 text-3xl font-tech mb-6 bg-slate-800 p-4 rounded-lg">
846
  <span>b = </span>
847
- <input id="ans-input" type="number" class="w-24 bg-slate-700 text-cyan-400 text-center rounded border border-slate-500 focus:border-cyan-400 outline-none p-1" placeholder="?" autofocus>
848
  </div>
849
 
850
  ${errorMsg ? `<div class="text-red-400 text-center font-bold mb-4 border-2 border-red-400 border-dashed animate-pulse bg-slate-900/50 p-2 rounded">${errorMsg}</div>` : ''}
@@ -865,7 +996,7 @@
865
  </p>
866
  <div class="flex items-center gap-2 mt-4 bg-slate-800/50 p-4 rounded-xl justify-center flex-wrap">
867
  <span class="font-tech text-amber-400 text-3xl whitespace-nowrap">投入 x = </span>
868
- <input id="test-input-a" type="number" class="tech-input w-24 p-2 rounded text-3xl text-amber-400 text-center" placeholder="1" value="1">
869
  <button onclick="runPhase4TestA()" class="px-6 py-2 bg-amber-600 hover:bg-amber-500 text-white rounded font-bold shadow-lg whitespace-nowrap">
870
  啟動運作
871
  </button>
@@ -888,7 +1019,7 @@
888
  <p class="text-slate-300 mb-4 text-center">請問 <span class="text-amber-400 font-bold">a</span> 是多少?</p>
889
  <div class="flex flex-wrap gap-2 mb-2 items-center justify-center text-3xl font-tech text-amber-400">
890
  <span>a =</span>
891
- <input id="ans-input" type="number" class="tech-input w-24 p-2 rounded text-3xl text-center text-amber-400" placeholder="?" autofocus>
892
  <button onclick="checkPhase4A()" class="w-full md:w-auto px-8 py-2 bg-amber-600 hover:bg-amber-500 text-white rounded-xl font-bold shadow-lg transition-transform hover:scale-105 whitespace-nowrap text-lg font-sans">確認</button>
893
  </div>
894
 
@@ -914,7 +1045,7 @@
914
  </p>
915
  <div class="flex flex-wrap gap-2 mt-6 items-center justify-center text-3xl font-tech text-white">
916
  <span>y =</span>
917
- <input id="ans-input" type="number" class="tech-input w-24 p-2 rounded text-3xl text-center text-white" placeholder="?" autofocus>
918
  <button onclick="checkPhase4Verify()" class="w-full md:w-auto px-8 py-2 bg-green-600 hover:bg-green-500 text-white rounded-xl font-bold shadow-lg transition-transform hover:scale-105 whitespace-nowrap text-lg font-sans">驗證</button>
919
  </div>
920
 
@@ -930,10 +1061,10 @@
930
  <div class="flex items-center justify-center gap-2 text-4xl md:text-4xl font-tech font-bold mb-8 bg-slate-900/80 p-6 rounded-3xl border-2 border-slate-700 w-full max-w-lg mx-auto">
931
  <span class="text-cyan-400">y</span>
932
  <span class="text-slate-500">=</span>
933
- <input id="final-a" type="number" class="w-20 bg-slate-800 text-amber-400 text-center rounded border border-slate-600 focus:border-amber-400 outline-none p-2" placeholder="?">
934
  <span class="text-amber-400">x</span>
935
  <span class="text-slate-500">+</span>
936
- <input id="final-b" type="number" class="w-20 bg-slate-800 text-cyan-400 text-center rounded border border-slate-600 focus:border-cyan-400 outline-none p-2" placeholder="?">
937
  </div>
938
  <button onclick="unlockCore()" class="w-full py-4 bg-gradient-to-r from-amber-600 to-red-600 text-white rounded-xl font-bold text-xl shadow-lg hover:shadow-amber-500/50 transition-all border border-amber-500/30">
939
  解鎖大門 (UNLOCK)
@@ -1052,7 +1183,7 @@
1052
  <div class="flex items-center gap-4 mb-2">
1053
  <span class="text-3xl font-tech text-amber-500">x =</span>
1054
  <div class="relative flex-1">
1055
- <input type="number" id="test-input-verify" class="tech-input w-full p-4 rounded-xl text-3xl font-bold" placeholder="輸入 10" autofocus onkeydown="if(event.key==='Enter') runPhase4VerifyManual()">
1056
  <div class="absolute right-4 top-1/2 -translate-y-1/2 text-slate-500 text-sm">晶石</div>
1057
  </div>
1058
  </div>
 
103
  -ms-overflow-style: none;
104
  scrollbar-width: none;
105
  }
106
+
107
+ /* Virtual Keypad */
108
+ #virtual-keypad {
109
+ position: fixed;
110
+ bottom: 20px;
111
+ left: 50%;
112
+ transform: translateX(-50%) translateY(120%);
113
+ z-index: 1000;
114
+ background: rgba(15, 23, 42, 0.95);
115
+ backdrop-filter: blur(10px);
116
+ -webkit-backdrop-filter: blur(10px);
117
+ border: 1px solid rgba(34, 211, 238, 0.3);
118
+ border-radius: 20px;
119
+ padding: 16px;
120
+ display: grid;
121
+ grid-template-columns: repeat(3, 1fr);
122
+ gap: 12px;
123
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
124
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
125
+ }
126
+
127
+ #virtual-keypad.active {
128
+ transform: translateX(-50%) translateY(0);
129
+ }
130
+
131
+ .keypad-btn {
132
+ width: 60px;
133
+ height: 60px;
134
+ border-radius: 12px;
135
+ background: rgba(30, 41, 59, 0.6);
136
+ border: 1px solid rgba(148, 163, 184, 0.2);
137
+ color: white;
138
+ font-size: 24px;
139
+ font-weight: bold;
140
+ font-family: 'Orbitron', sans-serif;
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ cursor: pointer;
145
+ transition: all 0.1s;
146
+ user-select: none;
147
+ }
148
+
149
+ .keypad-btn:active {
150
+ transform: scale(0.95);
151
+ background: rgba(34, 211, 238, 0.2);
152
+ }
153
+
154
+ .keypad-btn.action {
155
+ background: rgba(15, 23, 42, 0.8);
156
+ border-color: rgba(34, 211, 238, 0.4);
157
+ color: #22d3ee;
158
+ }
159
+
160
+ .keypad-btn.submit {
161
+ background: rgba(6, 182, 212, 0.8);
162
+ color: white;
163
+ grid-column: span 3;
164
+ width: 100%;
165
+ height: 50px;
166
+ font-size: 18px;
167
+ margin-top: 4px;
168
+ }
169
  </style>
170
  </head>
171
 
 
239
  <div>Designed by L.Star</div>
240
  </div>
241
 
242
+ <!-- Virtual Keypad HTML -->
243
+ <div id="virtual-keypad">
244
+ <div class="keypad-btn" onclick="keypad.input(1)">1</div>
245
+ <div class="keypad-btn" onclick="keypad.input(2)">2</div>
246
+ <div class="keypad-btn" onclick="keypad.input(3)">3</div>
247
+ <div class="keypad-btn" onclick="keypad.input(4)">4</div>
248
+ <div class="keypad-btn" onclick="keypad.input(5)">5</div>
249
+ <div class="keypad-btn" onclick="keypad.input(6)">6</div>
250
+ <div class="keypad-btn" onclick="keypad.input(7)">7</div>
251
+ <div class="keypad-btn" onclick="keypad.input(8)">8</div>
252
+ <div class="keypad-btn" onclick="keypad.input(9)">9</div>
253
+ <div class="keypad-btn action" onclick="keypad.input('-')">-</div>
254
+ <div class="keypad-btn" onclick="keypad.input(0)">0</div>
255
+ <div class="keypad-btn action" onclick="keypad.backspace()">⌫</div>
256
+ <div class="keypad-btn submit" onclick="keypad.close()">完成 (ENTER)</div>
257
+ </div>
258
+
259
  <script>
 
260
  const canvas = document.getElementById('gameCanvas');
261
  const ctx = canvas.getContext('2d');
262
  let width, height;
263
 
264
+ // --- Virtual Keypad System ---
265
+ const keypad = {
266
+ element: null,
267
+ targetInput: null,
268
+ init: function () {
269
+ this.element = document.getElementById('virtual-keypad');
270
+ // Auto-close when clicking outside
271
+ document.addEventListener('click', (e) => {
272
+ if (this.element.classList.contains('active') &&
273
+ !this.element.contains(e.target) &&
274
+ e.target !== this.targetInput) {
275
+ this.close();
276
+ }
277
+ });
278
+ },
279
+ open: function (inputElement) {
280
+ this.targetInput = inputElement;
281
+ this.element.classList.add('active');
282
+
283
+ // Highlight input
284
+ document.querySelectorAll('.tech-input').forEach(el => el.classList.remove('border-amber-400', 'ring-2', 'ring-amber-400'));
285
+ inputElement.classList.add('border-amber-400', 'ring-2', 'ring-amber-400');
286
+ },
287
+ close: function () {
288
+ this.element.classList.remove('active');
289
+ if (this.targetInput) {
290
+ this.targetInput.classList.remove('border-amber-400', 'ring-2', 'ring-amber-400');
291
+ // Trigger change event if needed
292
+ this.targetInput.dispatchEvent(new Event('change'));
293
+ this.targetInput = null;
294
+ }
295
+ },
296
+ input: function (val) {
297
+ if (!this.targetInput) return;
298
+ let currentVal = this.targetInput.value;
299
+ if (val === '-') {
300
+ if (currentVal.startsWith('-')) this.targetInput.value = currentVal.substring(1);
301
+ else this.targetInput.value = '-' + currentVal;
302
+ } else {
303
+ this.targetInput.value = currentVal + val;
304
+ }
305
+ },
306
+ backspace: function () {
307
+ if (!this.targetInput) return;
308
+ this.targetInput.value = this.targetInput.value.slice(0, -1);
309
+ }
310
+ };
311
+ // Initialize immediately
312
+ keypad.init();
313
+
314
  // Formula: y = ax + b
315
  let currentA = 2;
316
  let currentB = 3;
 
741
  <div class="flex items-center justify-center gap-2 flex-grow">
742
  <span class="font-tech text-3xl text-cyan-400">y = </span>
743
  <div class="relative w-32">
744
+ <input id="ans-input" type="text" readonly onclick="keypad.open(this)" class="tech-input w-full p-2 text-3xl rounded-lg" placeholder="?" >
745
  <div class="absolute inset-0 border-2 border-slate-500/50 rounded-lg pointer-events-none"></div>
746
  </div>
747
  </div>
 
875
  </p>
876
  <div class="flex items-center gap-2 mt-4 bg-slate-800/50 p-4 rounded-xl flex-wrap">
877
  <span class="font-tech text-amber-400 text-4xl whitespace-nowrap">x = </span>
878
+ <span class="font-tech text-amber-400 text-4xl whitespace-nowrap">x = </span>
879
+ <input id="ans-input" type="text" readonly onclick="keypad.open(this)" class="tech-input flex-1 min-w-[100px] p-2 rounded text-4xl text-amber-400" placeholder="?">
880
+ <button onclick="checkFinalAnswer()" class="px-6 py-3 bg-red-600 hover:bg-red-500 text-white rounded font-bold shadow-[0_0_15px_rgba(239,68,68,0.5)] whitespace-nowrap flex-shrink-0">
881
  <button onclick="checkFinalAnswer()" class="px-6 py-3 bg-red-600 hover:bg-red-500 text-white rounded font-bold shadow-[0_0_15px_rgba(239,68,68,0.5)] whitespace-nowrap flex-shrink-0">
882
  投入晶石
883
  </button>
 
975
  </p>
976
  <div class="flex items-center justify-center gap-2 text-3xl font-tech mb-6 bg-slate-800 p-4 rounded-lg">
977
  <span>b = </span>
978
+ <input id="ans-input" type="text" readonly onclick="keypad.open(this)" class="w-24 bg-slate-700 text-cyan-400 text-center rounded border border-slate-500 focus:border-cyan-400 outline-none p-1" placeholder="?">
979
  </div>
980
 
981
  ${errorMsg ? `<div class="text-red-400 text-center font-bold mb-4 border-2 border-red-400 border-dashed animate-pulse bg-slate-900/50 p-2 rounded">${errorMsg}</div>` : ''}
 
996
  </p>
997
  <div class="flex items-center gap-2 mt-4 bg-slate-800/50 p-4 rounded-xl justify-center flex-wrap">
998
  <span class="font-tech text-amber-400 text-3xl whitespace-nowrap">投入 x = </span>
999
+ <input id="test-input-a" type="text" readonly onclick="keypad.open(this)" class="tech-input w-24 p-2 rounded text-3xl text-amber-400 text-center" placeholder="1" value="1">
1000
  <button onclick="runPhase4TestA()" class="px-6 py-2 bg-amber-600 hover:bg-amber-500 text-white rounded font-bold shadow-lg whitespace-nowrap">
1001
  啟動運作
1002
  </button>
 
1019
  <p class="text-slate-300 mb-4 text-center">請問 <span class="text-amber-400 font-bold">a</span> 是多少?</p>
1020
  <div class="flex flex-wrap gap-2 mb-2 items-center justify-center text-3xl font-tech text-amber-400">
1021
  <span>a =</span>
1022
+ <input id="ans-input" type="text" readonly onclick="keypad.open(this)" class="tech-input w-24 p-2 rounded text-3xl text-center text-amber-400" placeholder="?">
1023
  <button onclick="checkPhase4A()" class="w-full md:w-auto px-8 py-2 bg-amber-600 hover:bg-amber-500 text-white rounded-xl font-bold shadow-lg transition-transform hover:scale-105 whitespace-nowrap text-lg font-sans">確認</button>
1024
  </div>
1025
 
 
1045
  </p>
1046
  <div class="flex flex-wrap gap-2 mt-6 items-center justify-center text-3xl font-tech text-white">
1047
  <span>y =</span>
1048
+ <input id="ans-input" type="text" readonly onclick="keypad.open(this)" class="tech-input w-24 p-2 rounded text-3xl text-center text-white" placeholder="?">
1049
  <button onclick="checkPhase4Verify()" class="w-full md:w-auto px-8 py-2 bg-green-600 hover:bg-green-500 text-white rounded-xl font-bold shadow-lg transition-transform hover:scale-105 whitespace-nowrap text-lg font-sans">驗證</button>
1050
  </div>
1051
 
 
1061
  <div class="flex items-center justify-center gap-2 text-4xl md:text-4xl font-tech font-bold mb-8 bg-slate-900/80 p-6 rounded-3xl border-2 border-slate-700 w-full max-w-lg mx-auto">
1062
  <span class="text-cyan-400">y</span>
1063
  <span class="text-slate-500">=</span>
1064
+ <input id="final-a" type="text" readonly onclick="keypad.open(this)" class="w-20 bg-slate-800 text-amber-400 text-center rounded border border-slate-600 focus:border-amber-400 outline-none p-2" placeholder="?">
1065
  <span class="text-amber-400">x</span>
1066
  <span class="text-slate-500">+</span>
1067
+ <input id="final-b" type="text" readonly onclick="keypad.open(this)" class="w-20 bg-slate-800 text-cyan-400 text-center rounded border border-slate-600 focus:border-cyan-400 outline-none p-2" placeholder="?">
1068
  </div>
1069
  <button onclick="unlockCore()" class="w-full py-4 bg-gradient-to-r from-amber-600 to-red-600 text-white rounded-xl font-bold text-xl shadow-lg hover:shadow-amber-500/50 transition-all border border-amber-500/30">
1070
  解鎖大門 (UNLOCK)
 
1183
  <div class="flex items-center gap-4 mb-2">
1184
  <span class="text-3xl font-tech text-amber-500">x =</span>
1185
  <div class="relative flex-1">
1186
+ <input type="text" readonly onclick="keypad.open(this)" id="test-input-verify" class="tech-input w-full p-4 rounded-xl text-3xl font-bold" placeholder="輸入 10">
1187
  <div class="absolute right-4 top-1/2 -translate-y-1/2 text-slate-500 text-sm">晶石</div>
1188
  </div>
1189
  </div>
sequence.html CHANGED
@@ -287,6 +287,69 @@
287
  #altar-hint {
288
  animation: pulse 1s infinite;
289
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  </style>
291
  </head>
292
 
@@ -321,294 +384,303 @@
321
  </div>
322
 
323
  <!-- Credits Footer -->
324
- <div class="fixed bottom-1 right-2 text-right text-[10px] text-slate-500/50 pointer-events-none z-50 font-sans">
325
- <div>遊戲設計:新竹縣精華國中 藍星宇老師</div>
326
- <div>臉書社團:<a href="https://www.facebook.com/groups/1554372228718393" target="_blank"
327
- class="hover:text-amber-400 pointer-events-auto transition-colors">萬物皆數</a></div>
328
- </div>
329
 
330
- <!-- Story Hint Overlay -->
331
- <div id="story-hint"
332
- class="absolute top-1/3 left-1/2 transform -translate-x-1/2 glass-panel px-6 py-4 rounded-xl hidden text-center pointer-events-none border border-yellow-400/50 shadow-[0_0_30px_rgba(250,204,21,0.3)] z-40">
333
- <p id="story-hint-title" class="text-yellow-300 font-bold text-xl mb-1">階梯竟然消失了!</p>
334
- <p id="story-hint-desc" class="text-white text-base">是不是需要什麼儀式才能再次出現...</p>
335
- </div>
 
 
 
 
 
 
 
 
 
 
336
 
337
- <!-- Guide Arrow -->
338
- <div id="guide-arrow"
339
- class="absolute top-[30%] right-[20%] hidden z-30 pointer-events-none flex items-center gap-2">
340
- <div class="text-6xl text-yellow-400 drop-shadow-[0_0_15px_rgba(250,204,21,0.8)]">⬅️</div>
341
- <div
342
- class="text-xl font-bold text-yellow-300 bg-slate-900/60 px-3 py-1 rounded border border-yellow-400/50">
343
- 祭壇在後方</div>
344
- </div>
345
 
346
- <!-- Altar Dive Hint -->
347
- <div id="altar-hint"
348
- class="absolute top-[60%] left-1/2 transform -translate-x-1/2 hidden z-30 pointer-events-none flex flex-col items-center">
349
- <div class="glass-panel px-4 py-2 rounded-xl border border-red-400 bg-red-900/80">
350
- <p id="altar-hint-text" class="text-2xl font-black text-white">🔥 連點兩下跳躍,下墜打破祭壇!</p>
351
- </div>
352
- </div>
353
 
354
- <!-- Tutorial Overlay -->
355
- <div id="ui-tutorial" class="absolute top-24 w-full text-center pointer-events-none hidden z-30">
356
- <h2 id="tutorial-text"
357
- class="text-3xl md:text-4xl font-black text-yellow-400 drop-shadow-xl tracking-wider">教學模式</h2>
358
- <div id="tutorial-subtext" class="tutorial-hint hidden">提示訊息</div>
359
  </div>
 
360
 
361
- <!-- Mobile Controls -->
362
- <div id="mobile-controls" class="hidden">
363
- <div id="joystick-zone" class="control-zone">
364
- <div id="joystick-knob"></div>
365
- </div>
366
- <div id="btn-jump" class="control-zone select-none">跳躍</div>
 
 
 
 
 
367
  </div>
 
 
368
 
369
- <!-- Start Screen -->
370
- <div id="screen-start" class="absolute inset-0 flex flex-col items-center justify-center z-50">
371
- <h1
372
- class="text-5xl md:text-7xl font-black mb-4 text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-orange-600 drop-shadow-[0_0_15px_rgba(245,158,11,0.5)]">
373
- 數列峽谷</h1>
374
- <p class="text-slate-300 mb-8 text-lg">操作模式選擇</p>
375
- <div class="flex flex-col md:flex-row gap-6 w-full max-w-2xl px-4">
376
- <button onclick="selectDevice('mobile')"
377
- class="flex-1 glass-panel p-6 rounded-2xl hover:bg-slate-800 transition-all border border-slate-700 hover:border-amber-400 group">
378
- <div class="text-4xl mb-4">📱</div>
379
- <h3 class="text-xl font-bold text-amber-100 group-hover:text-amber-400">平板/觸控</h3>
380
- </button>
381
- <button onclick="selectDevice('desktop')"
382
- class="flex-1 glass-panel p-6 rounded-2xl hover:bg-slate-800 transition-all border border-slate-700 hover:border-orange-400 group">
383
- <div class="text-4xl mb-4">⌨️</div>
384
- <h3 class="text-xl font-bold text-orange-100 group-hover:text-orange-400">電腦/鍵盤</h3>
385
- </button>
386
- </div>
387
  </div>
 
388
 
389
- <!-- Quiz Screen -->
390
- <div id="screen-quiz"
391
- class="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/95 backdrop-blur-md z-50 hidden overflow-y-auto py-8">
392
- <div class="glass-panel p-6 md:p-8 rounded-2xl w-[95%] max-w-2xl border-t-4 border-amber-500 my-auto">
393
- <h2 class="text-2xl md:text-3xl font-bold text-amber-400 mb-4">✨ 數列觀念檢測</h2>
394
- <div class="bg-slate-800/50 p-4 md:p-6 rounded-lg mb-6 text-left space-y-4 border border-slate-700">
395
- <p class="text-lg md:text-xl text-slate-200"><strong
396
- class="text-amber-400 text-xl md:text-2xl">公差</strong> 的意思是:<span
397
- class="border-b-2 border-amber-500">後項 - 前項</span> (固定差距)。</p>
398
- <div class="pl-4 border-l-4 border-slate-600">
399
- <p class="text-base md:text-lg text-slate-300 font-bold mb-2">範例:首項 2,公差 3</p>
400
- <p class="text-lg md:text-xl font-mono text-cyan-300 leading-relaxed">➜ 2, 5, 8, 11...</p>
401
- <p class="text-base md:text-lg font-mono text-slate-400 leading-relaxed">(2, 2+3, 2+3+3,
402
- 2+3+3+3...)</p>
403
- </div>
404
  </div>
405
- <div class="mb-6">
406
- <p class="text-lg md:text-xl mb-4 font-bold">請問:若首項是 <span id="quiz-start-val"
407
- class="text-amber-400 text-2xl md:text-3xl mx-1">?</span>,公差是 <span id="quiz-diff-val"
408
- class="text-amber-400 text-2xl md:text-3xl mx-1">?</span></p>
409
- <p class="mb-2 text-slate-300">數列的前四項會是什麼?</p>
410
- <div class="flex justify-center items-center gap-2 md:gap-4 flex-wrap">
411
- <input type="number" id="quiz-1"
412
- class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
413
- <span class="text-slate-500 font-bold text-xl">,</span>
414
- <input type="number" id="quiz-2"
415
- class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
416
- <span class="text-slate-500 font-bold text-xl">,</span>
417
- <input type="number" id="quiz-3"
418
- class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
419
- <span class="text-slate-500 font-bold text-xl">,</span>
420
- <input type="number" id="quiz-4"
421
- class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
422
- <span class="text-slate-500 font-bold text-xl">...</span>
423
- </div>
424
- <p id="quiz-error" class="text-red-400 mt-2 text-lg h-6 font-bold"></p>
425
  </div>
426
- <button onclick="checkQuiz()"
427
- class="w-full py-3 md:py-4 rounded-xl bg-gradient-to-r from-amber-600 to-orange-600 hover:from-amber-500 hover:to-orange-500 text-white font-bold text-xl md:text-2xl transition-all shadow-lg active:scale-95 border border-amber-400/30">送出答案
428
- (SUBMIT)</button>
429
  </div>
 
 
 
430
  </div>
 
431
 
432
- <!-- Mission Screen -->
433
- <div id="screen-mission"
434
- class="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/90 backdrop-blur-md z-50 hidden">
435
- <div class="glass-panel p-6 md:p-8 rounded-2xl text-center border-t-4 border-amber-500 w-[90%] max-w-lg">
436
- <h3 class="text-amber-300 tracking-widest mb-4">任務開始</h3>
437
- <h1 class="text-3xl md:text-4xl font-bold mb-6 text-white">尋找 <span id="mission-highlight"
438
- class="text-amber-400 drop-shadow-md"></span></h1>
439
- <p class="text-slate-300 mb-6 leading-relaxed text-sm md:text-base">
440
- 地板會依照規律生成。<br>只要符合此規律的數字都是安全的。<br>蒐集完數字後,需要<span
441
- class="text-yellow-400 font-bold border-b border-yellow-400">建造階梯</span>才能進入城堡。</p>
442
- <button onclick="confirmMission()"
443
- class="w-full py-3 md:py-4 rounded-xl bg-amber-600 hover:bg-amber-500 text-white font-bold text-xl shadow-[0_0_15px_rgba(245,158,11,0.4)] transition-all active:scale-95">出發
444
- (START)</button>
445
- </div>
446
  </div>
 
447
 
448
- <!-- Ritual UI -->
449
- <div id="screen-ritual"
450
- class="absolute inset-0 hidden z-40 pointer-events-auto flex flex-col items-center justify-end pb-4 md:pb-10 fade-in pointer-events-none">
451
- <div class="flex-1 w-full pointer-events-none"><!-- Spacer for canvas --></div>
452
- <div
453
- class="ritual-content-wrapper pointer-events-auto w-[95%] max-w-[600px] bg-slate-900/80 backdrop-blur-md rounded-t-2xl p-4 border-t border-amber-500/50 max-h-[50vh] overflow-y-auto">
454
- <div id="ritual-step-1" class="transition-all duration-500 mb-4 w-full flex justify-center">
455
- <button onclick="triggerRitualAnimation()"
456
- class="btn-magic px-8 py-3 md:px-10 md:py-4 rounded-full bg-gradient-to-r from-amber-500 to-orange-600 text-white font-bold text-lg md:text-xl border-4 border-white/20 shadow-[0_0_20px_rgba(245,158,11,0.6)] hover:scale-105 transition-transform">✨
457
- 施展分身術</button>
458
- </div>
459
- <!-- Steps Container -->
460
- <div class="w-full flex flex-col items-center gap-4">
461
- <div id="ritual-step-2"
462
- class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden border border-amber-500 transition-all">
463
- <div class="original-content">
464
- <h3 class="text-base md:text-lg font-bold text-amber-400 mb-2">步驟 1:觀察長方形邊長</h3>
465
- <div class="flex flex-wrap gap-2 justify-center items-center">
466
- <div
467
- class="bg-slate-800/50 p-2 rounded-lg flex items-center gap-1 md:gap-2 border border-slate-600">
468
- <span
469
- class="text-amber-300 font-bold text-xs md:text-sm whitespace-nowrap">寬度</span>
470
- <input type="number" id="rit-start"
471
- class="math-input w-12 h-8 md:w-14 md:h-10 text-base md:text-lg"
472
- placeholder="">
473
- <span class="text-white">+</span>
474
- <input type="number" id="rit-end"
475
- class="math-input w-12 h-8 md:w-14 md:h-10 text-base md:text-lg"
476
- placeholder="末">
477
- </div>
478
- <div
479
- class="bg-slate-800/50 p-2 rounded-lg flex items-center gap-1 md:gap-2 border border-slate-600">
480
- <span
481
- class="text-yellow-300 font-bold text-xs md:text-sm whitespace-nowrap">項數</span>
482
- <input type="number" id="rit-n"
483
- class="math-input w-12 h-8 md:w-14 md:h-10 text-base md:text-lg"
484
- placeholder="n">
485
- </div>
486
- <button id="btn-rit-2" onclick="checkRitualDim()"
487
- class="px-4 py-2 md:px-6 rounded-lg bg-amber-600 hover:bg-amber-500 text-white font-bold shadow-lg text-sm md:text-base whitespace-nowrap">確認</button>
488
  </div>
489
- <p id="ritual-msg-1" class="text-red-400 mt-1 text-xs md:text-sm h-4 text-center"></p>
490
- </div>
491
- <div class="summary-content hidden">
492
- <span class="text-green-400 font-bold text-sm">✅ 步驟 1 完成</span>
493
- <span class="text-slate-300 text-xs md:text-sm ml-2" id="summary-dim"></span>
494
- </div>
495
- </div>
496
-
497
- <div id="ritual-step-3"
498
- class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden border border-green-500 transition-all">
499
- <div class="original-content">
500
- <h3 class="text-base md:text-lg font-bold text-green-400 mb-2">步驟 2:計算長方形總數</h3>
501
- <div class="flex flex-wrap items-center justify-center gap-2 md:gap-3">
502
- <span class="text-xs md:text-sm text-slate-300">總磚塊數 (寬×高) = </span>
503
- <input type="number" id="rit-total"
504
- class="math-input w-20 h-8 md:w-24 md:h-10 text-base md:text-lg">
505
- <button id="btn-rit-3" onclick="checkRitualTotal()"
506
- class="px-4 py-2 md:px-6 rounded-lg bg-green-600 hover:bg-green-500 text-white font-bold shadow-lg text-sm md:text-base">確認</button>
507
  </div>
508
- <p id="ritual-msg-2" class="text-red-400 mt-1 text-xs md:text-sm h-4 text-center"></p>
509
- </div>
510
- <div class="summary-content hidden">
511
- <span class="text-green-400 font-bold text-sm">✅ 步驟 2 完成</span>
512
- <span class="text-slate-300 text-xs md:text-sm ml-2" id="summary-total"></span>
513
  </div>
 
514
  </div>
 
 
 
 
 
515
 
516
- <div id="ritual-step-4"
517
- class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden border border-yellow-500 transition-all">
518
- <h3 class="text-base md:text-lg font-bold text-yellow-400 mb-2">步驟 3:求原本階梯總和</h3>
519
- <p class="text-slate-300 mb-2 text-center text-xs">原本階梯是長方形<span
520
- class="text-amber-400 font-bold">一半</span></p>
521
  <div class="flex flex-wrap items-center justify-center gap-2 md:gap-3">
522
- <span class="text-xs md:text-sm font-bold text-amber-300">階梯 = </span>
523
- <input type="number" id="rit-final"
524
  class="math-input w-20 h-8 md:w-24 md:h-10 text-base md:text-lg">
525
- <button id="btn-rit-4" onclick="checkRitualFinal()"
526
- class="px-4 py-2 md:px-6 rounded-lg bg-amber-600 hover:bg-amber-500 text-white font-bold shadow-lg text-sm md:text-base">完成</button>
527
  </div>
528
- <p id="ritual-msg-3" class="text-red-400 mt-1 text-xs md:text-sm h-4 text-center"></p>
 
 
 
 
529
  </div>
 
530
 
531
- <div id="ritual-step-5" class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden text-center">
532
- <h3
533
- class="text-xl md:text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-yellow-300 to-red-400 mb-2">
534
- 計算完成!</h3>
535
- <p
536
- class="text-base md:text-lg font-black text-yellow-400 mt-2 mb-4 leading-relaxed bg-slate-800 p-2 rounded">
537
- 階梯已生成!快爬上去升起旗幟吧!
538
- </p>
539
- <div class="flex gap-4 justify-center">
540
- <button onclick="finishRitualAndBuild()"
541
- class="px-6 py-2 md:px-8 md:py-3 rounded-lg bg-green-600 hover:bg-green-500 font-bold text-white text-lg md:text-xl shadow-lg animate-bounce">
542
- 前往城堡
543
- </button>
544
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  </div>
546
  </div>
547
  </div>
548
  </div>
 
549
 
550
- <!-- Review Screen (Level Clear) -->
551
- <div id="screen-review"
552
- class="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/95 backdrop-blur-md z-50 hidden overflow-y-auto">
553
- <div
554
- class="glass-panel p-8 rounded-2xl max-w-2xl w-[95%] border-t-4 border-amber-500 text-center my-10 max-h-[90vh] overflow-y-auto">
555
- <h2 class="text-5xl font-black text-amber-400 mb-4 drop-shadow-[0_0_15px_rgba(245,158,11,0.5)]">🏆
556
- 關卡完成!</h2>
557
-
558
- <div class="mb-6">
559
- <span class="text-slate-300 text-xl block mb-1">最終得分</span>
560
- <span id="final-score" class="text-6xl font-black text-amber-300 drop-shadow-md">0</span>
561
- </div>
562
 
563
- <!-- Mock Message for Low Score -->
564
- <div id="mock-msg"
565
- class="hidden mb-6 bg-slate-800 border border-slate-600 p-4 rounded-xl transform rotate-[-2deg]">
566
- <p class="text-4xl">🤪 <span class="text-slate-300 font-bold">太弱了吧,加油好嗎</span></p>
567
- </div>
568
 
569
- <div class="bg-slate-800/80 p-6 rounded-xl text-left space-y-5 mb-8 border border-slate-600">
570
- <h3 class="text-2xl font-bold text-amber-400 border-b border-slate-600 pb-2">📜 本關核心回顧 (Concept
571
- Review)</h3>
572
- <div>
573
- <p class="text-amber-300 font-bold text-xl">1. 等差數列 (Arithmetic Sequence)</p>
574
- <p class="text-slate-300 text-lg">相鄰兩項的差都相等,這個差稱為<span class="text-white font-bold">「公差」</span>。
575
- </p>
576
- </div>
577
- <div>
578
- <p class="text-amber-300 font-bold text-xl">2. 公差公式</p>
579
- <p class="text-slate-300 text-lg font-mono bg-slate-900 p-2 rounded inline-block text-cyan-200">
580
- 公差 = 後項 - 前項
581
- </p>
582
- </div>
583
- <div>
584
- <p class="text-amber-300 font-bold text-xl">3. 等差級數和 (Sum)</p>
585
- <p class="text-slate-300 text-lg">透過圖形拼貼,我們發現總和是長方形面積的一半:</p>
586
- <p
587
- class="text-amber-400 font-bold font-mono bg-slate-900 p-3 rounded mt-2 text-center text-xl border border-slate-600">
588
- 總和 = (首項 + 末項) × 項數 ÷ 2
589
- </p>
590
- </div>
591
  </div>
592
-
593
- <a href="index.html"
594
- class="w-full py-4 rounded-xl bg-gradient-to-r from-amber-600 to-orange-600 hover:from-amber-500 hover:to-orange-500 text-white font-bold text-2xl transition-all shadow-lg block active:scale-95">
595
- 回到 Math City
596
- </a>
597
  </div>
 
 
 
 
 
598
  </div>
 
599
 
600
- <!-- Game Over -->
601
- <div id="screen-gameover"
602
- class="absolute inset-0 flex flex-col items-center justify-center bg-black/80 backdrop-blur-md z-50 hidden">
603
- <h2 class="text-5xl font-bold text-red-500 mb-4">任務失敗</h2>
604
- <p class="text-slate-300 mb-8">計算錯誤或失足墜落</p>
605
- <div class="flex gap-4">
606
- <button onclick="resetGame()"
607
- class="px-8 py-3 rounded-lg bg-white text-slate-900 font-bold hover:bg-slate-200">再試一次</button>
608
- <a href="index.html" class="px-8 py-3 rounded-lg bg-indigo-600 font-bold">回到 Math City</a>
609
- </div>
610
  </div>
611
  </div>
 
612
 
613
  <script>
614
  // --- Core Variables ---
@@ -772,12 +844,93 @@
772
 
773
  // --- Init ---
774
  function resize() {
 
775
  width = canvas.width = window.innerWidth;
776
  height = canvas.height = window.innerHeight;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
  }
778
  window.addEventListener('resize', resize);
779
  resize();
780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  function selectDevice(type) {
782
  if (audioCtx.state === 'suspended') audioCtx.resume();
783
 
 
287
  #altar-hint {
288
  animation: pulse 1s infinite;
289
  }
290
+
291
+ /* Virtual Keypad */
292
+ #virtual-keypad {
293
+ position: fixed;
294
+ bottom: 20px;
295
+ left: 50%;
296
+ transform: translateX(-50%) translateY(120%);
297
+ z-index: 1000;
298
+ background: rgba(15, 23, 42, 0.95);
299
+ backdrop-filter: blur(10px);
300
+ -webkit-backdrop-filter: blur(10px);
301
+ border: 1px solid rgba(245, 158, 11, 0.3);
302
+ border-radius: 20px;
303
+ padding: 16px;
304
+ display: grid;
305
+ grid-template-columns: repeat(3, 1fr);
306
+ gap: 12px;
307
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
308
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
309
+ }
310
+
311
+ #virtual-keypad.active {
312
+ transform: translateX(-50%) translateY(0);
313
+ }
314
+
315
+ .keypad-btn {
316
+ width: 60px;
317
+ height: 60px;
318
+ border-radius: 12px;
319
+ background: rgba(30, 41, 59, 0.6);
320
+ border: 1px solid rgba(148, 163, 184, 0.2);
321
+ color: white;
322
+ font-size: 24px;
323
+ font-weight: bold;
324
+ font-family: 'Noto Sans TC', sans-serif;
325
+ display: flex;
326
+ align-items: center;
327
+ justify-content: center;
328
+ cursor: pointer;
329
+ transition: all 0.1s;
330
+ user-select: none;
331
+ }
332
+
333
+ .keypad-btn:active {
334
+ transform: scale(0.95);
335
+ background: rgba(245, 158, 11, 0.2);
336
+ }
337
+
338
+ .keypad-btn.action {
339
+ background: rgba(15, 23, 42, 0.8);
340
+ border-color: rgba(245, 158, 11, 0.4);
341
+ color: #f59e0b;
342
+ }
343
+
344
+ .keypad-btn.submit {
345
+ background: rgba(234, 88, 12, 0.8);
346
+ color: white;
347
+ grid-column: span 3;
348
+ width: 100%;
349
+ height: 50px;
350
+ font-size: 18px;
351
+ margin-top: 4px;
352
+ }
353
  </style>
354
  </head>
355
 
 
384
  </div>
385
 
386
  <!-- Credits Footer -->
387
+ <div>臉書社團:<a href="https://www.facebook.com/groups/1554372228718393" target="_blank"
388
+ class="hover:text-amber-400 pointer-events-auto transition-colors">萬物皆數</a></div>
389
+ </div>
 
 
390
 
391
+ <!-- Virtual Keypad HTML -->
392
+ <div id="virtual-keypad">
393
+ <div class="keypad-btn" onclick="keypad.input(1)">1</div>
394
+ <div class="keypad-btn" onclick="keypad.input(2)">2</div>
395
+ <div class="keypad-btn" onclick="keypad.input(3)">3</div>
396
+ <div class="keypad-btn" onclick="keypad.input(4)">4</div>
397
+ <div class="keypad-btn" onclick="keypad.input(5)">5</div>
398
+ <div class="keypad-btn" onclick="keypad.input(6)">6</div>
399
+ <div class="keypad-btn" onclick="keypad.input(7)">7</div>
400
+ <div class="keypad-btn" onclick="keypad.input(8)">8</div>
401
+ <div class="keypad-btn" onclick="keypad.input(9)">9</div>
402
+ <div class="keypad-btn action" onclick="keypad.input('-')">-</div>
403
+ <div class="keypad-btn" onclick="keypad.input(0)">0</div>
404
+ <div class="keypad-btn action" onclick="keypad.backspace()">⌫</div>
405
+ <div class="keypad-btn submit" onclick="keypad.close()">完成 (ENTER)</div>
406
+ </div>
407
 
408
+ <!-- Story Hint Overlay -->
409
+ <div id="story-hint"
410
+ class="absolute top-1/3 left-1/2 transform -translate-x-1/2 glass-panel px-6 py-4 rounded-xl hidden text-center pointer-events-none border border-yellow-400/50 shadow-[0_0_30px_rgba(250,204,21,0.3)] z-40">
411
+ <p id="story-hint-title" class="text-yellow-300 font-bold text-xl mb-1">階梯竟然消失了!</p>
412
+ <p id="story-hint-desc" class="text-white text-base">是不是需要什麼儀式才能再次出現...</p>
413
+ </div>
 
 
414
 
415
+ <!-- Guide Arrow -->
416
+ <div id="guide-arrow"
417
+ class="absolute top-[30%] right-[20%] hidden z-30 pointer-events-none flex items-center gap-2">
418
+ <div class="text-6xl text-yellow-400 drop-shadow-[0_0_15px_rgba(250,204,21,0.8)]">⬅️</div>
419
+ <div class="text-xl font-bold text-yellow-300 bg-slate-900/60 px-3 py-1 rounded border border-yellow-400/50">
420
+ 祭壇在後方</div>
421
+ </div>
422
 
423
+ <!-- Altar Dive Hint -->
424
+ <div id="altar-hint"
425
+ class="absolute top-[60%] left-1/2 transform -translate-x-1/2 hidden z-30 pointer-events-none flex flex-col items-center">
426
+ <div class="glass-panel px-4 py-2 rounded-xl border border-red-400 bg-red-900/80">
427
+ <p id="altar-hint-text" class="text-2xl font-black text-white">🔥 連點兩下跳躍,下墜打破祭壇!</p>
428
  </div>
429
+ </div>
430
 
431
+ <!-- Tutorial Overlay -->
432
+ <div id="ui-tutorial" class="absolute top-24 w-full text-center pointer-events-none hidden z-30">
433
+ <h2 id="tutorial-text" class="text-3xl md:text-4xl font-black text-yellow-400 drop-shadow-xl tracking-wider">
434
+ 教學模式</h2>
435
+ <div id="tutorial-subtext" class="tutorial-hint hidden">提示訊息</div>
436
+ </div>
437
+
438
+ <!-- Mobile Controls -->
439
+ <div id="mobile-controls" class="hidden">
440
+ <div id="joystick-zone" class="control-zone">
441
+ <div id="joystick-knob"></div>
442
  </div>
443
+ <div id="btn-jump" class="control-zone select-none">跳躍</div>
444
+ </div>
445
 
446
+ <!-- Start Screen -->
447
+ <div id="screen-start" class="absolute inset-0 flex flex-col items-center justify-center z-50">
448
+ <h1
449
+ class="text-5xl md:text-7xl font-black mb-4 text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-orange-600 drop-shadow-[0_0_15px_rgba(245,158,11,0.5)]">
450
+ 數列峽谷</h1>
451
+ <p class="text-slate-300 mb-8 text-lg">操作模式選擇</p>
452
+ <div class="flex flex-col md:flex-row gap-6 w-full max-w-2xl px-4">
453
+ <button onclick="selectDevice('mobile')"
454
+ class="flex-1 glass-panel p-6 rounded-2xl hover:bg-slate-800 transition-all border border-slate-700 hover:border-amber-400 group">
455
+ <div class="text-4xl mb-4">📱</div>
456
+ <h3 class="text-xl font-bold text-amber-100 group-hover:text-amber-400">平板/觸控</h3>
457
+ </button>
458
+ <button onclick="selectDevice('desktop')"
459
+ class="flex-1 glass-panel p-6 rounded-2xl hover:bg-slate-800 transition-all border border-slate-700 hover:border-orange-400 group">
460
+ <div class="text-4xl mb-4">⌨️</div>
461
+ <h3 class="text-xl font-bold text-orange-100 group-hover:text-orange-400">電腦/鍵盤</h3>
462
+ </button>
 
463
  </div>
464
+ </div>
465
 
466
+ <!-- Quiz Screen -->
467
+ <div id="screen-quiz"
468
+ class="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/95 backdrop-blur-md z-50 hidden overflow-y-auto py-8">
469
+ <div class="glass-panel p-6 md:p-8 rounded-2xl w-[95%] max-w-2xl border-t-4 border-amber-500 my-auto">
470
+ <h2 class="text-2xl md:text-3xl font-bold text-amber-400 mb-4">✨ 數列觀念檢測</h2>
471
+ <div class="bg-slate-800/50 p-4 md:p-6 rounded-lg mb-6 text-left space-y-4 border border-slate-700">
472
+ <p class="text-lg md:text-xl text-slate-200"><strong
473
+ class="text-amber-400 text-xl md:text-2xl">公差</strong> 的意思是:<span
474
+ class="border-b-2 border-amber-500">後項 - 前項</span> (固定差距)。</p>
475
+ <div class="pl-4 border-l-4 border-slate-600">
476
+ <p class="text-base md:text-lg text-slate-300 font-bold mb-2">範例:首項 2,公差 3</p>
477
+ <p class="text-lg md:text-xl font-mono text-cyan-300 leading-relaxed">➜ 2, 5, 8, 11...</p>
478
+ <p class="text-base md:text-lg font-mono text-slate-400 leading-relaxed">(2, 2+3, 2+3+3,
479
+ 2+3+3+3...)</p>
 
480
  </div>
481
+ </div>
482
+ <div class="mb-6">
483
+ <p class="text-lg md:text-xl mb-4 font-bold">請問:若首項��� <span id="quiz-start-val"
484
+ class="text-amber-400 text-2xl md:text-3xl mx-1">?</span>,公差是 <span id="quiz-diff-val"
485
+ class="text-amber-400 text-2xl md:text-3xl mx-1">?</span></p>
486
+ <p class="mb-2 text-slate-300">數列的前四項會是什麼?</p>
487
+ <div class="flex justify-center items-center gap-2 md:gap-4 flex-wrap">
488
+ <input type="text" readonly onclick="keypad.open(this)" id="quiz-1"
489
+ class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
490
+ <span class="text-slate-500 font-bold text-xl">,</span>
491
+ <input type="text" readonly onclick="keypad.open(this)" id="quiz-2"
492
+ class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
493
+ <span class="text-slate-500 font-bold text-xl">,</span>
494
+ <input type="text" readonly onclick="keypad.open(this)" id="quiz-3"
495
+ class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
496
+ <span class="text-slate-500 font-bold text-xl">,</span>
497
+ <input type="text" readonly onclick="keypad.open(this)" id="quiz-4"
498
+ class="math-input w-16 h-12 md:w-24 md:h-16 text-xl md:text-2xl" placeholder="?">
499
+ <span class="text-slate-500 font-bold text-xl">...</span>
 
500
  </div>
501
+ <p id="quiz-error" class="text-red-400 mt-2 text-lg h-6 font-bold"></p>
 
 
502
  </div>
503
+ <button onclick="checkQuiz()"
504
+ class="w-full py-3 md:py-4 rounded-xl bg-gradient-to-r from-amber-600 to-orange-600 hover:from-amber-500 hover:to-orange-500 text-white font-bold text-xl md:text-2xl transition-all shadow-lg active:scale-95 border border-amber-400/30">送出答案
505
+ (SUBMIT)</button>
506
  </div>
507
+ </div>
508
 
509
+ <!-- Mission Screen -->
510
+ <div id="screen-mission"
511
+ class="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/90 backdrop-blur-md z-50 hidden">
512
+ <div class="glass-panel p-6 md:p-8 rounded-2xl text-center border-t-4 border-amber-500 w-[90%] max-w-lg">
513
+ <h3 class="text-amber-300 tracking-widest mb-4">任務開始</h3>
514
+ <h1 class="text-3xl md:text-4xl font-bold mb-6 text-white">尋找 <span id="mission-highlight"
515
+ class="text-amber-400 drop-shadow-md"></span></h1>
516
+ <p class="text-slate-300 mb-6 leading-relaxed text-sm md:text-base">
517
+ 地板會依照規律生成。<br>只要符合此規律的數字都是安全的。<br>蒐集完數字後,需要<span
518
+ class="text-yellow-400 font-bold border-b border-yellow-400">建造階梯</span>才能進入城堡。</p>
519
+ <button onclick="confirmMission()"
520
+ class="w-full py-3 md:py-4 rounded-xl bg-amber-600 hover:bg-amber-500 text-white font-bold text-xl shadow-[0_0_15px_rgba(245,158,11,0.4)] transition-all active:scale-95">出發
521
+ (START)</button>
 
522
  </div>
523
+ </div>
524
 
525
+ <!-- Ritual UI -->
526
+ <div id="screen-ritual"
527
+ class="absolute inset-0 hidden z-40 pointer-events-auto flex flex-col items-center justify-end pb-4 md:pb-10 fade-in pointer-events-none">
528
+ <div class="flex-1 w-full pointer-events-none"><!-- Spacer for canvas --></div>
529
+ <div
530
+ class="ritual-content-wrapper pointer-events-auto w-[95%] max-w-[600px] bg-slate-900/80 backdrop-blur-md rounded-t-2xl p-4 border-t border-amber-500/50 max-h-[50vh] overflow-y-auto">
531
+ <div id="ritual-step-1" class="transition-all duration-500 mb-4 w-full flex justify-center">
532
+ <button onclick="triggerRitualAnimation()"
533
+ class="btn-magic px-8 py-3 md:px-10 md:py-4 rounded-full bg-gradient-to-r from-amber-500 to-orange-600 text-white font-bold text-lg md:text-xl border-4 border-white/20 shadow-[0_0_20px_rgba(245,158,11,0.6)] hover:scale-105 transition-transform">✨
534
+ 施展分身術</button>
535
+ </div>
536
+ <!-- Steps Container -->
537
+ <div class="w-full flex flex-col items-center gap-4">
538
+ <div id="ritual-step-2"
539
+ class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden border border-amber-500 transition-all">
540
+ <div class="original-content">
541
+ <h3 class="text-base md:text-lg font-bold text-amber-400 mb-2">步驟 1:觀察長方形邊長</h3>
542
+ <div class="flex flex-wrap gap-2 justify-center items-center">
543
+ <div
544
+ class="bg-slate-800/50 p-2 rounded-lg flex items-center gap-1 md:gap-2 border border-slate-600">
545
+ <span class="text-amber-300 font-bold text-xs md:text-sm whitespace-nowrap">寬度</span>
546
+ <input type="text" readonly onclick="keypad.open(this)" id="rit-start"
547
+ class="math-input w-12 h-8 md:w-14 md:h-10 text-base md:text-lg" placeholder="">
548
+ <span class="text-white">+</span>
549
+ <input type="text" readonly onclick="keypad.open(this)" id="rit-end"
550
+ class="math-input w-12 h-8 md:w-14 md:h-10 text-base md:text-lg" placeholder="末">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  </div>
552
+ <div
553
+ class="bg-slate-800/50 p-2 rounded-lg flex items-center gap-1 md:gap-2 border border-slate-600">
554
+ <span class="text-yellow-300 font-bold text-xs md:text-sm whitespace-nowrap">項數</span>
555
+ <input type="text" readonly onclick="keypad.open(this)" id="rit-n"
556
+ class="math-input w-12 h-8 md:w-14 md:h-10 text-base md:text-lg" placeholder="n">
 
 
 
 
 
 
 
 
 
 
 
 
 
557
  </div>
558
+ <button id="btn-rit-2" onclick="checkRitualDim()"
559
+ class="px-4 py-2 md:px-6 rounded-lg bg-amber-600 hover:bg-amber-500 text-white font-bold shadow-lg text-sm md:text-base whitespace-nowrap">確認</button>
 
 
 
560
  </div>
561
+ <p id="ritual-msg-1" class="text-red-400 mt-1 text-xs md:text-sm h-4 text-center"></p>
562
  </div>
563
+ <div class="summary-content hidden">
564
+ <span class="text-green-400 font-bold text-sm">✅ 步驟 1 完成</span>
565
+ <span class="text-slate-300 text-xs md:text-sm ml-2" id="summary-dim"></span>
566
+ </div>
567
+ </div>
568
 
569
+ <div id="ritual-step-3"
570
+ class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden border border-green-500 transition-all">
571
+ <div class="original-content">
572
+ <h3 class="text-base md:text-lg font-bold text-green-400 mb-2">步驟 2:計算長方形總數</h3>
 
573
  <div class="flex flex-wrap items-center justify-center gap-2 md:gap-3">
574
+ <span class="text-xs md:text-sm text-slate-300">總磚塊數 (寬×高) = </span>
575
+ <input type="text" readonly onclick="keypad.open(this)" id="rit-total"
576
  class="math-input w-20 h-8 md:w-24 md:h-10 text-base md:text-lg">
577
+ <button id="btn-rit-3" onclick="checkRitualTotal()"
578
+ class="px-4 py-2 md:px-6 rounded-lg bg-green-600 hover:bg-green-500 text-white font-bold shadow-lg text-sm md:text-base">確認</button>
579
  </div>
580
+ <p id="ritual-msg-2" class="text-red-400 mt-1 text-xs md:text-sm h-4 text-center"></p>
581
+ </div>
582
+ <div class="summary-content hidden">
583
+ <span class="text-green-400 font-bold text-sm">✅ 步驟 2 完成</span>
584
+ <span class="text-slate-300 text-xs md:text-sm ml-2" id="summary-total"></span>
585
  </div>
586
+ </div>
587
 
588
+ <div id="ritual-step-4"
589
+ class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden border border-yellow-500 transition-all">
590
+ <h3 class="text-base md:text-lg font-bold text-yellow-400 mb-2">步驟 3:求原本階梯總和</h3>
591
+ <p class="text-slate-300 mb-2 text-center text-xs">原本階梯是長方形的 <span
592
+ class="text-amber-400 font-bold">一半</span></p>
593
+ <div class="flex flex-wrap items-center justify-center gap-2 md:gap-3">
594
+ <span class="text-xs md:text-sm font-bold text-amber-300">階梯總和 = </span>
595
+ <input type="text" readonly onclick="keypad.open(this)" id="rit-final"
596
+ class="math-input w-20 h-8 md:w-24 md:h-10 text-base md:text-lg">
597
+ <button id="btn-rit-4" onclick="checkRitualFinal()"
598
+ class="px-4 py-2 md:px-6 rounded-lg bg-amber-600 hover:bg-amber-500 text-white font-bold shadow-lg text-sm md:text-base">完成</button>
599
+ </div>
600
+ <p id="ritual-msg-3" class="text-red-400 mt-1 text-xs md:text-sm h-4 text-center"></p>
601
+ </div>
602
+
603
+ <div id="ritual-step-5" class="glass-panel p-3 md:p-4 rounded-2xl w-full hidden text-center">
604
+ <h3
605
+ class="text-xl md:text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-yellow-300 to-red-400 mb-2">
606
+ 計算完成!</h3>
607
+ <p
608
+ class="text-base md:text-lg font-black text-yellow-400 mt-2 mb-4 leading-relaxed bg-slate-800 p-2 rounded">
609
+ 階梯已生成!快爬上去升起旗幟吧!
610
+ </p>
611
+ <div class="flex gap-4 justify-center">
612
+ <button onclick="finishRitualAndBuild()"
613
+ class="px-6 py-2 md:px-8 md:py-3 rounded-lg bg-green-600 hover:bg-green-500 font-bold text-white text-lg md:text-xl shadow-lg animate-bounce">
614
+ 前往城堡
615
+ </button>
616
  </div>
617
  </div>
618
  </div>
619
  </div>
620
+ </div>
621
 
622
+ <!-- Review Screen (Level Clear) -->
623
+ <div id="screen-review"
624
+ class="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/95 backdrop-blur-md z-50 hidden overflow-y-auto">
625
+ <div
626
+ class="glass-panel p-8 rounded-2xl max-w-2xl w-[95%] border-t-4 border-amber-500 text-center my-10 max-h-[90vh] overflow-y-auto">
627
+ <h2 class="text-5xl font-black text-amber-400 mb-4 drop-shadow-[0_0_15px_rgba(245,158,11,0.5)]">🏆
628
+ 關卡完成!</h2>
629
+
630
+ <div class="mb-6">
631
+ <span class="text-slate-300 text-xl block mb-1">最終得分</span>
632
+ <span id="final-score" class="text-6xl font-black text-amber-300 drop-shadow-md">0</span>
633
+ </div>
634
 
635
+ <!-- Mock Message for Low Score -->
636
+ <div id="mock-msg"
637
+ class="hidden mb-6 bg-slate-800 border border-slate-600 p-4 rounded-xl transform rotate-[-2deg]">
638
+ <p class="text-4xl">🤪 <span class="text-slate-300 font-bold">太弱了吧,加油好嗎</span></p>
639
+ </div>
640
 
641
+ <div class="bg-slate-800/80 p-6 rounded-xl text-left space-y-5 mb-8 border border-slate-600">
642
+ <h3 class="text-2xl font-bold text-amber-400 border-b border-slate-600 pb-2">📜 本關核心回顧 (Concept
643
+ Review)</h3>
644
+ <div>
645
+ <p class="text-amber-300 font-bold text-xl">1. 等差數列 (Arithmetic Sequence)</p>
646
+ <p class="text-slate-300 text-lg">相鄰兩項的差都相等,這個差稱為<span class="text-white font-bold">「公差」</span>。
647
+ </p>
648
+ </div>
649
+ <div>
650
+ <p class="text-amber-300 font-bold text-xl">2. 公差公式</p>
651
+ <p class="text-slate-300 text-lg font-mono bg-slate-900 p-2 rounded inline-block text-cyan-200">
652
+ 公差 = 後項 - 前項
653
+ </p>
654
+ </div>
655
+ <div>
656
+ <p class="text-amber-300 font-bold text-xl">3. 等差級數和 (Sum)</p>
657
+ <p class="text-slate-300 text-lg">透過圖形拼貼,我們發現總和是長方形面積的一半:</p>
658
+ <p
659
+ class="text-amber-400 font-bold font-mono bg-slate-900 p-3 rounded mt-2 text-center text-xl border border-slate-600">
660
+ 總和 = (首項 + 末項) × 項數 ÷ 2
661
+ </p>
 
662
  </div>
 
 
 
 
 
663
  </div>
664
+
665
+ <a href="index.html"
666
+ class="w-full py-4 rounded-xl bg-gradient-to-r from-amber-600 to-orange-600 hover:from-amber-500 hover:to-orange-500 text-white font-bold text-2xl transition-all shadow-lg block active:scale-95">
667
+ 回到 Math City
668
+ </a>
669
  </div>
670
+ </div>
671
 
672
+ <!-- Game Over -->
673
+ <div id="screen-gameover"
674
+ class="absolute inset-0 flex flex-col items-center justify-center bg-black/80 backdrop-blur-md z-50 hidden">
675
+ <h2 class="text-5xl font-bold text-red-500 mb-4">任務失敗</h2>
676
+ <p class="text-slate-300 mb-8">計算錯誤或失足墜落</p>
677
+ <div class="flex gap-4">
678
+ <button onclick="resetGame()"
679
+ class="px-8 py-3 rounded-lg bg-white text-slate-900 font-bold hover:bg-slate-200">再試一次</button>
680
+ <a href="index.html" class="px-8 py-3 rounded-lg bg-indigo-600 font-bold">回到 Math City</a>
 
681
  </div>
682
  </div>
683
+ </div>
684
 
685
  <script>
686
  // --- Core Variables ---
 
844
 
845
  // --- Init ---
846
  function resize() {
847
+ const oldHeight = height;
848
  width = canvas.width = window.innerWidth;
849
  height = canvas.height = window.innerHeight;
850
+
851
+ // Resize Logic for Bottom Anchoring
852
+ if (oldHeight && oldHeight !== height) {
853
+ const deltaY = height - oldHeight;
854
+ // Shift Player
855
+ player.y += deltaY;
856
+ player.prevY += deltaY; // Important for collision physics logic
857
+
858
+ // Shift Camera (to avoid quick jumps)
859
+ cameraY += deltaY;
860
+
861
+ // Shift Platforms
862
+ platforms.forEach(p => p.y += deltaY);
863
+
864
+ // Shift CHeckpoints
865
+ checkpoints.forEach(p => p.y += deltaY);
866
+
867
+ // Shift Tutorial Objects
868
+ tutorialObjects.forEach(o => o.y += deltaY);
869
+
870
+ // Shift Level Objects (Flags, Castle)
871
+ levelObjects.forEach(o => o.y += deltaY);
872
+
873
+ // Shift Particles
874
+ particles.forEach(p => p.y += deltaY);
875
+
876
+ // Shift Gravity Zone
877
+ if (gravityZone) gravityZone.y += deltaY;
878
+ }
879
  }
880
  window.addEventListener('resize', resize);
881
  resize();
882
 
883
+ // --- Virtual Keypad System (Reused from Function Game) ---
884
+ const keypad = {
885
+ element: null,
886
+ targetInput: null,
887
+ init: function () {
888
+ this.element = document.getElementById('virtual-keypad');
889
+ // Auto-close when clicking outside
890
+ document.addEventListener('click', (e) => {
891
+ if (this.element.classList.contains('active') &&
892
+ !this.element.contains(e.target) &&
893
+ e.target !== this.targetInput &&
894
+ !e.target.classList.contains('keypad-btn')) { /* Fix for clicking buttons */
895
+ this.close();
896
+ }
897
+ });
898
+ },
899
+ open: function (inputElement) {
900
+ this.targetInput = inputElement;
901
+ this.element.classList.add('active');
902
+
903
+ // Highlight input
904
+ document.querySelectorAll('.math-input').forEach(el => el.classList.remove('border-amber-400', 'ring-2', 'ring-amber-400'));
905
+ inputElement.classList.add('border-amber-400', 'ring-2', 'ring-amber-400');
906
+ },
907
+ close: function () {
908
+ this.element.classList.remove('active');
909
+ if (this.targetInput) {
910
+ this.targetInput.classList.remove('border-amber-400', 'ring-2', 'ring-amber-400');
911
+ // Trigger change event if needed
912
+ this.targetInput.dispatchEvent(new Event('change'));
913
+ this.targetInput = null;
914
+ }
915
+ },
916
+ input: function (val) {
917
+ if (!this.targetInput) return;
918
+ let currentVal = this.targetInput.value;
919
+ if (val === '-') {
920
+ if (currentVal.startsWith('-')) this.targetInput.value = currentVal.substring(1);
921
+ else this.targetInput.value = '-' + currentVal;
922
+ } else {
923
+ this.targetInput.value = currentVal + val;
924
+ }
925
+ },
926
+ backspace: function () {
927
+ if (!this.targetInput) return;
928
+ this.targetInput.value = this.targetInput.value.slice(0, -1);
929
+ }
930
+ };
931
+ // Initialize immediately
932
+ keypad.init();
933
+
934
  function selectDevice(type) {
935
  if (audioCtx.state === 'suspended') audioCtx.resume();
936