Spaces:
Running
Running
Upload 2 files
Browse files- function.html +141 -10
- 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="
|
| 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 |
-
<
|
|
|
|
|
|
|
| 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="
|
| 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="
|
| 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="
|
| 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="
|
| 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="
|
| 934 |
<span class="text-amber-400">x</span>
|
| 935 |
<span class="text-slate-500">+</span>
|
| 936 |
-
<input id="final-b" type="
|
| 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="
|
| 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
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
class="hover:text-amber-400 pointer-events-auto transition-colors">萬物皆數</a></div>
|
| 328 |
-
</div>
|
| 329 |
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
祭壇在後方</div>
|
| 344 |
-
</div>
|
| 345 |
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
</div>
|
| 352 |
-
|
| 353 |
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
<
|
| 359 |
</div>
|
|
|
|
| 360 |
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 367 |
</div>
|
|
|
|
|
|
|
| 368 |
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
</div>
|
| 387 |
</div>
|
|
|
|
| 388 |
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
</div>
|
| 404 |
</div>
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
</
|
| 424 |
-
<p id="quiz-error" class="text-red-400 mt-2 text-lg h-6 font-bold"></p>
|
| 425 |
</div>
|
| 426 |
-
<
|
| 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 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
</div>
|
| 446 |
</div>
|
|
|
|
| 447 |
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 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 |
-
<
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 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 |
-
<
|
| 509 |
-
|
| 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 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
<
|
| 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
|
| 523 |
-
<input type="
|
| 524 |
class="math-input w-20 h-8 md:w-24 md:h-10 text-base md:text-lg">
|
| 525 |
-
<button id="btn-rit-
|
| 526 |
-
class="px-4 py-2 md:px-6 rounded-lg bg-
|
| 527 |
</div>
|
| 528 |
-
<p id="ritual-msg-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 529 |
</div>
|
|
|
|
| 530 |
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
<
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 545 |
</div>
|
| 546 |
</div>
|
| 547 |
</div>
|
| 548 |
</div>
|
|
|
|
| 549 |
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 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 |
-
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
| 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 |
|