Spaces:
Running
Running
Upload 41 files
Browse files- .gitattributes +1 -0
- achievements.js +43 -18
- ding.mp3 +3 -0
- index.html +4 -6
- spring.js +1 -4
.gitattributes
CHANGED
|
@@ -43,3 +43,4 @@ valley.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
| 43 |
tower.jpg filter=lfs diff=lfs merge=lfs -text
|
| 44 |
tower.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 45 |
Theme.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 43 |
tower.jpg filter=lfs diff=lfs merge=lfs -text
|
| 44 |
tower.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 45 |
Theme.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
ding.mp3 filter=lfs diff=lfs merge=lfs -text
|
achievements.js
CHANGED
|
@@ -147,17 +147,15 @@ class AchievementSystem {
|
|
| 147 |
icon = '🔮';
|
| 148 |
break;
|
| 149 |
}
|
| 150 |
-
|
| 151 |
-
// 卡片內容
|
| 152 |
card.innerHTML = `
|
| 153 |
-
<div class="achievement-icon">${icon}</div>
|
| 154 |
-
<h3 class="achievement-title">${achievement.title}</h3>
|
| 155 |
-
<p class="achievement-description">${achievement.description}</p>
|
| 156 |
${isUnlocked && userProgress.unlockedAt ?
|
| 157 |
-
`<div class="achievement-unlock-time">解鎖於: ${userProgress.unlockedAt}</div>` : ''}
|
| 158 |
-
${!isUnlocked ? '<div class="lock-icon">🔒</div>' : ''}
|
| 159 |
-
`;
|
| 160 |
-
|
| 161 |
this.achievementsGrid.appendChild(card);
|
| 162 |
});
|
| 163 |
}
|
|
@@ -254,10 +252,28 @@ class AchievementSystem {
|
|
| 254 |
|
| 255 |
// 顯示成就解鎖通知
|
| 256 |
this.showAchievementToast(achievement);
|
| 257 |
-
|
| 258 |
-
|
|
|
|
| 259 |
}
|
| 260 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
// 顯示成就解鎖通知
|
| 262 |
showAchievementToast(achievement) {
|
| 263 |
console.log(`顯示成就解鎖通知: ${achievement.title}`);
|
|
@@ -274,8 +290,7 @@ class AchievementSystem {
|
|
| 274 |
if (!this.isProcessingToast) {
|
| 275 |
this.processToastQueue();
|
| 276 |
}
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
// 處理通知佇列
|
| 280 |
async processToastQueue() {
|
| 281 |
if (this.toastQueue.length === 0) {
|
|
@@ -313,13 +328,23 @@ class AchievementSystem {
|
|
| 313 |
</div>
|
| 314 |
`;
|
| 315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
// 添加到通知容器
|
| 317 |
this.toastContainer.appendChild(toast);
|
| 318 |
-
|
| 319 |
-
// 等待
|
| 320 |
-
await new Promise(resolve =>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
toast.remove();
|
| 322 |
-
|
| 323 |
// 處理下一個通知
|
| 324 |
this.processToastQueue();
|
| 325 |
}
|
|
|
|
| 147 |
icon = '🔮';
|
| 148 |
break;
|
| 149 |
}
|
| 150 |
+
// 卡片內容
|
|
|
|
| 151 |
card.innerHTML = `
|
| 152 |
+
<div class=\"achievement-icon\">${icon}</div>
|
| 153 |
+
<h3 class=\"achievement-title\">${achievement.title}</h3>
|
| 154 |
+
<p class=\"achievement-description\">${isUnlocked || achievement.type !== \'secret\' ? achievement.description : \'??????????????????\'}</p>
|
| 155 |
${isUnlocked && userProgress.unlockedAt ?
|
| 156 |
+
`<div class=\"achievement-unlock-time\">解鎖於: ${userProgress.unlockedAt}</div>` : \'\'}
|
| 157 |
+
${!isUnlocked ? \'<div class=\"lock-icon\">🔒</div>\' : \'\'}
|
| 158 |
+
`;
|
|
|
|
| 159 |
this.achievementsGrid.appendChild(card);
|
| 160 |
});
|
| 161 |
}
|
|
|
|
| 252 |
|
| 253 |
// 顯示成就解鎖通知
|
| 254 |
this.showAchievementToast(achievement);
|
| 255 |
+
console.log(`成就 \"${achievement.title}\" 已解鎖!`);
|
| 256 |
+
// 將解鎖的成就添加到待處理佇列
|
| 257 |
+
this.addPendingAchievement(achievement.id);
|
| 258 |
}
|
| 259 |
+
|
| 260 |
+
// 將成就添加到待處理佇列
|
| 261 |
+
addPendingAchievement(achievementId) {
|
| 262 |
+
let pendingAchievements = JSON.parse(localStorage.getItem(\'pendingAchievements\')) || [];
|
| 263 |
+
if (!pendingAchievements.includes(achievementId)) {
|
| 264 |
+
pendingAchievements.push(achievementId);
|
| 265 |
+
localStorage.setItem(\'pendingAchievements\', JSON.stringify(pendingAchievements));
|
| 266 |
+
console.log(`成就 ${achievementId} 已添加到待處理佇列`);
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
// 獲取並清除待處理成就
|
| 271 |
+
getAndClearPendingAchievements() {
|
| 272 |
+
const pendingAchievements = JSON.parse(localStorage.getItem(\'pendingAchievements\')) || [];
|
| 273 |
+
localStorage.removeItem(\'pendingAchievements\');
|
| 274 |
+
return pendingAchievements;
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
// 顯示成就解鎖通知
|
| 278 |
showAchievementToast(achievement) {
|
| 279 |
console.log(`顯示成就解鎖通知: ${achievement.title}`);
|
|
|
|
| 290 |
if (!this.isProcessingToast) {
|
| 291 |
this.processToastQueue();
|
| 292 |
}
|
| 293 |
+
}
|
|
|
|
| 294 |
// 處理通知佇列
|
| 295 |
async processToastQueue() {
|
| 296 |
if (this.toastQueue.length === 0) {
|
|
|
|
| 328 |
</div>
|
| 329 |
`;
|
| 330 |
|
| 331 |
+
// 播放音效
|
| 332 |
+
const audio = new Audio(\'ding.mp3\');
|
| 333 |
+
audio.play().catch(e => console.error(\'播放音效失敗:\', e));
|
| 334 |
+
|
| 335 |
// 添加到通知容器
|
| 336 |
this.toastContainer.appendChild(toast);
|
| 337 |
+
|
| 338 |
+
// 等待用戶點擊確認
|
| 339 |
+
await new Promise(resolve => {
|
| 340 |
+
const confirmButton = document.createElement(\'button\');
|
| 341 |
+
confirmButton.textContent = \'確認\';
|
| 342 |
+
confirmButton.className = \'toast-confirm-button\';
|
| 343 |
+
toast.appendChild(confirmButton);
|
| 344 |
+
confirmButton.addEventListener(\'click\', resolve);
|
| 345 |
+
});
|
| 346 |
toast.remove();
|
| 347 |
+
|
| 348 |
// 處理下一個通知
|
| 349 |
this.processToastQueue();
|
| 350 |
}
|
ding.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:14bdf79b72e46b09655caad520da1bc082a3b141ccaded506de670b13e879670
|
| 3 |
+
size 102920
|
index.html
CHANGED
|
@@ -7,11 +7,9 @@
|
|
| 7 |
<link rel="stylesheet" href="style.css">
|
| 8 |
</head>
|
| 9 |
<body class="home-page">
|
| 10 |
-
<!-- 音效元素 -->
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
</audio>
|
| 14 |
-
|
| 15 |
<div class="game-container">
|
| 16 |
<h1 class="game-title">《數學魔法王國:平方之旅》</h1>
|
| 17 |
|
|
@@ -24,7 +22,7 @@
|
|
| 24 |
|
| 25 |
<!-- 音樂來源註記 -->
|
| 26 |
<div class="music-credit">
|
| 27 |
-
<p>背景音樂:由Suno
|
| 28 |
<button id="toggle-bgm" class="small-btn">音樂開/關</button>
|
| 29 |
</div>
|
| 30 |
</div>
|
|
|
|
| 7 |
<link rel="stylesheet" href="style.css">
|
| 8 |
</head>
|
| 9 |
<body class="home-page">
|
| 10 |
+
<!-- 音效元素 -- <audio id=\"bgm\" loop>
|
| 11 |
+
<source src=\"Theme.mp3\" type=\"audio/mpeg\">
|
| 12 |
+
</audio>
|
|
|
|
|
|
|
| 13 |
<div class="game-container">
|
| 14 |
<h1 class="game-title">《數學魔法王國:平方之旅》</h1>
|
| 15 |
|
|
|
|
| 22 |
|
| 23 |
<!-- 音樂來源註記 -->
|
| 24 |
<div class="music-credit">
|
| 25 |
+
<p>背景音樂:由Suno製作</p>
|
| 26 |
<button id="toggle-bgm" class="small-btn">音樂開/關</button>
|
| 27 |
</div>
|
| 28 |
</div>
|
spring.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
| 1 |
-
document.addEventListener('DOMContentLoaded', function() {
|
| 2 |
-
// 預先載入成就系統
|
| 3 |
-
loadAchievementSystem();
|
| 4 |
-
|
| 5 |
// 檢查是否有玩家資料
|
| 6 |
const currentPlayerId = localStorage.getItem('currentPlayerId');
|
| 7 |
const playerName = localStorage.getItem('playerName');
|
|
|
|
| 1 |
+
document.addEventListener(\'DOMContentLoaded\', function() {
|
|
|
|
|
|
|
|
|
|
| 2 |
// 檢查是否有玩家資料
|
| 3 |
const currentPlayerId = localStorage.getItem('currentPlayerId');
|
| 4 |
const playerName = localStorage.getItem('playerName');
|