1436 lines
42 KiB
HTML
1436 lines
42 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>数字乐园</title>
|
||
|
||
<!-- 引入后端集成脚本 -->
|
||
<script src="../../js/apiService.js"></script>
|
||
<script src="../../js/dataManager.js"></script>
|
||
<script src="../../js/userManager.js"></script>
|
||
<script src="../../js/accessTracker.js"></script>
|
||
<script src="../../js/gameTracker.js"></script>
|
||
<script src="../../js/gameDataLogger.js"></script>
|
||
<style>
|
||
/* 全局样式 */
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: "Comic Neue", cursive;
|
||
background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
position: relative;
|
||
}
|
||
|
||
/* 气球装饰 */
|
||
.balloon {
|
||
position: absolute;
|
||
width: 80px;
|
||
height: 100px;
|
||
background: radial-gradient(circle at 30% 30%, #ff9a9e, #fad0c4);
|
||
border-radius: 50%;
|
||
box-shadow: inset -10px -10px 10px rgba(0, 0, 0, 0.1);
|
||
animation: float 15s infinite ease-in-out;
|
||
z-index: -1;
|
||
}
|
||
|
||
.balloon::after {
|
||
content: "";
|
||
position: absolute;
|
||
bottom: -15px;
|
||
left: 50%;
|
||
width: 2px;
|
||
height: 30px;
|
||
background: #ff9a9e;
|
||
transform: translateX(-50%);
|
||
}
|
||
|
||
/* 鲜花装饰 */
|
||
.flower {
|
||
position: absolute;
|
||
width: 60px;
|
||
height: 60px;
|
||
background: radial-gradient(
|
||
circle at center,
|
||
#ffe66d 30%,
|
||
#ff9a9e 100%
|
||
);
|
||
border-radius: 50%;
|
||
animation: sway 8s infinite ease-in-out;
|
||
z-index: -1;
|
||
}
|
||
|
||
.flower::before {
|
||
content: "";
|
||
position: absolute;
|
||
bottom: -20px;
|
||
left: 50%;
|
||
width: 3px;
|
||
height: 40px;
|
||
background: #74b9ff;
|
||
transform: translateX(-50%);
|
||
}
|
||
|
||
@keyframes float {
|
||
0%,
|
||
100% {
|
||
transform: translateY(0) rotate(0deg);
|
||
}
|
||
|
||
50% {
|
||
transform: translateY(-50px) rotate(5deg);
|
||
}
|
||
}
|
||
|
||
@keyframes sway {
|
||
0%,
|
||
100% {
|
||
transform: translateX(0) rotate(0deg);
|
||
}
|
||
|
||
50% {
|
||
transform: translateX(20px) rotate(10deg);
|
||
}
|
||
}
|
||
|
||
/* 主容器样式 */
|
||
.main-container {
|
||
width: 90%;
|
||
max-width: 1000px;
|
||
height: 90vh;
|
||
position: relative;
|
||
overflow: hidden;
|
||
background: rgba(255, 255, 255, 0.8);
|
||
border-radius: 40px;
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
||
border: 8px solid #ffe66d;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.main-container:hover {
|
||
transform: scale(1.02);
|
||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
/* 开始菜单样式 */
|
||
.start-menu {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 30px;
|
||
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
|
||
z-index: 10;
|
||
transition: all 0.5s ease;
|
||
}
|
||
|
||
.start-title {
|
||
font-size: 5rem;
|
||
color: #ff6b6b;
|
||
text-shadow: 5px 5px 0 #ffe66d;
|
||
margin-bottom: 50px;
|
||
animation: bounce 2s infinite;
|
||
}
|
||
|
||
@keyframes bounce {
|
||
0%,
|
||
100% {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
25% {
|
||
transform: translateY(-2px);
|
||
animation-timing-function: ease-in-out;
|
||
}
|
||
|
||
50% {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
75% {
|
||
transform: translateY(2px);
|
||
animation-timing-function: ease-in-out;
|
||
}
|
||
}
|
||
|
||
.start-button {
|
||
width: 200px;
|
||
height: 200px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(145deg, #ff9a9e, #ff6b6b);
|
||
border: 5px solid #ffe66d;
|
||
color: white;
|
||
font-size: 2.5rem;
|
||
cursor: pointer;
|
||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3),
|
||
inset 0 0 20px rgba(255, 255, 255, 0.5);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
transition: all 0.3s;
|
||
animation: pulse 2s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% {
|
||
transform: scale(1);
|
||
}
|
||
|
||
50% {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
100% {
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
.start-button:hover {
|
||
transform: scale(1.1);
|
||
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
.start-button::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: -50%;
|
||
left: -50%;
|
||
width: 200%;
|
||
height: 200%;
|
||
background: radial-gradient(
|
||
circle,
|
||
rgba(255, 255, 255, 0.8) 0%,
|
||
rgba(255, 255, 255, 0) 70%
|
||
);
|
||
transform: scale(0);
|
||
transition: transform 0.5s;
|
||
}
|
||
|
||
.start-button:active::before {
|
||
transform: scale(1);
|
||
}
|
||
|
||
/* 游戏界面样式 */
|
||
.game-screen {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: none;
|
||
flex-direction: column;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 30px;
|
||
z-index: 5;
|
||
padding: 20px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.game-header {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding: 0 10px;
|
||
}
|
||
|
||
.progress-container {
|
||
width: 60%;
|
||
height: 30px;
|
||
background-color: #f1f1f1;
|
||
border-radius: 15px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.progress-bar {
|
||
height: 100%;
|
||
width: 0%;
|
||
background: linear-gradient(90deg, #74b9ff, #0984e3);
|
||
border-radius: 15px;
|
||
transition: width 0.5s;
|
||
}
|
||
|
||
.back-button {
|
||
width: 60px;
|
||
height: 60px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(145deg, #ff7675, #d63031);
|
||
border: none;
|
||
color: white;
|
||
font-size: 1.5rem;
|
||
cursor: pointer;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.back-button:hover {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.game-content {
|
||
width: 100%;
|
||
flex-grow: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
padding: 10px 0;
|
||
}
|
||
|
||
.game-image {
|
||
width: 90%;
|
||
max-width: 500px;
|
||
height: auto;
|
||
max-height: 300px;
|
||
object-fit: contain;
|
||
margin: 20px 0;
|
||
border-radius: 20px;
|
||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
|
||
transition: all 0.3s;
|
||
animation: pulse 2s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0%,
|
||
100% {
|
||
transform: scale(1);
|
||
}
|
||
|
||
50% {
|
||
transform: scale(1.05);
|
||
}
|
||
}
|
||
|
||
.number-options {
|
||
display: flex;
|
||
justify-content: center;
|
||
flex-wrap: wrap;
|
||
gap: 15px;
|
||
width: 100%;
|
||
max-width: 600px;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.number-btn {
|
||
width: 100px;
|
||
height: 100px;
|
||
border-radius: 50%;
|
||
color: white;
|
||
font-size: 3rem;
|
||
border: none;
|
||
cursor: pointer;
|
||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
|
||
transition: all 0.3s;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.number-btn[data-number="1"] {
|
||
background: linear-gradient(145deg, #74b9ff, #0984e3);
|
||
}
|
||
|
||
.number-btn[data-number="2"] {
|
||
background: linear-gradient(145deg, #ff7675, #d63031);
|
||
}
|
||
|
||
.number-btn[data-number="3"] {
|
||
background: linear-gradient(145deg, #55efc4, #00b894);
|
||
}
|
||
|
||
.number-btn[data-number="4"] {
|
||
background: linear-gradient(145deg, #a29bfe, #6c5ce7);
|
||
}
|
||
|
||
.number-btn[data-number="5"] {
|
||
background: linear-gradient(145deg, #ffeaa7, #fdcb6e);
|
||
}
|
||
|
||
.number-btn:hover {
|
||
transform: scale(1.1);
|
||
box-shadow: 0 15px 25px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.number-btn::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 5px;
|
||
height: 5px;
|
||
background: rgba(255, 255, 255, 0.5);
|
||
opacity: 0;
|
||
border-radius: 100%;
|
||
transform: scale(1, 1) translate(-50%, -50%);
|
||
transform-origin: 50% 50%;
|
||
}
|
||
|
||
.number-btn:focus:not(:active)::after {
|
||
animation: ripple 1s ease-out;
|
||
}
|
||
|
||
@keyframes ripple {
|
||
0% {
|
||
transform: scale(0, 0);
|
||
opacity: 0.5;
|
||
}
|
||
|
||
100% {
|
||
transform: scale(20, 20);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
.feedback {
|
||
height: 80px;
|
||
width: 80px;
|
||
margin-top: 20px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 4rem;
|
||
opacity: 0;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.correct {
|
||
color: #00b894;
|
||
animation: correct-feedback 0.5s;
|
||
}
|
||
|
||
.incorrect {
|
||
color: #d63031;
|
||
animation: incorrect-feedback 0.5s;
|
||
}
|
||
|
||
@keyframes correct-feedback {
|
||
0% {
|
||
transform: scale(0);
|
||
opacity: 0;
|
||
}
|
||
|
||
50% {
|
||
transform: scale(1.5);
|
||
opacity: 1;
|
||
}
|
||
|
||
100% {
|
||
transform: scale(1);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
@keyframes incorrect-feedback {
|
||
0%,
|
||
100% {
|
||
transform: translateX(0);
|
||
}
|
||
|
||
20%,
|
||
60% {
|
||
transform: translateX(-10px);
|
||
}
|
||
|
||
40%,
|
||
80% {
|
||
transform: translateX(10px);
|
||
}
|
||
}
|
||
|
||
/* 胜利界面样式 */
|
||
.victory-screen {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: none;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
border-radius: 30px;
|
||
z-index: 20;
|
||
}
|
||
|
||
.victory-content {
|
||
text-align: center;
|
||
color: white;
|
||
}
|
||
|
||
.victory-icon {
|
||
font-size: 10rem;
|
||
margin-bottom: 30px;
|
||
color: #ffe66d;
|
||
text-shadow: 0 0 20px #ff9f43;
|
||
animation: victory-glow 2s infinite;
|
||
}
|
||
|
||
@keyframes victory-glow {
|
||
0%,
|
||
100% {
|
||
transform: scale(1);
|
||
text-shadow: 0 0 20px #ff9f43;
|
||
}
|
||
|
||
50% {
|
||
transform: scale(1.2);
|
||
text-shadow: 0 0 40px #ff9f43;
|
||
}
|
||
}
|
||
|
||
.victory-button {
|
||
width: 150px;
|
||
height: 150px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(145deg, #00b894, #55efc4);
|
||
border: none;
|
||
color: white;
|
||
font-size: 2rem;
|
||
cursor: pointer;
|
||
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-top: 50px;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.victory-button:hover {
|
||
transform: scale(1.1);
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
/* 粒子特效 */
|
||
.particles {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
pointer-events: none;
|
||
z-index: 30;
|
||
}
|
||
|
||
.particle {
|
||
position: absolute;
|
||
width: 10px;
|
||
height: 10px;
|
||
border-radius: 50%;
|
||
background-color: #ffe66d;
|
||
opacity: 0;
|
||
}
|
||
|
||
/* 音量开关按钮样式 */
|
||
.sound-toggle {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(145deg, #74b9ff, #0984e3);
|
||
border: 3px solid #ffe66d;
|
||
color: white;
|
||
font-size: 2.5rem;
|
||
cursor: pointer;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.sound-toggle:hover {
|
||
transform: scale(1.1);
|
||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.start-title {
|
||
font-size: 3rem;
|
||
}
|
||
|
||
.start-button {
|
||
width: 150px;
|
||
height: 150px;
|
||
}
|
||
|
||
.game-image {
|
||
width: 90%;
|
||
height: auto;
|
||
max-height: 250px;
|
||
}
|
||
|
||
.number-btn {
|
||
width: 70px;
|
||
height: 70px;
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.sound-toggle {
|
||
width: 60px;
|
||
height: 60px;
|
||
font-size: 2rem;
|
||
}
|
||
}
|
||
</style>
|
||
<script>
|
||
// 添加随机气球
|
||
function createBalloons() {
|
||
const colors = ["#ff9a9e", "#74b9ff", "#ffe66d", "#a29bfe", "#55efc4"];
|
||
for (let i = 0; i < 8; i++) {
|
||
const balloon = document.createElement("div");
|
||
balloon.className = "balloon";
|
||
balloon.style.left = Math.random() * 100 + "%";
|
||
balloon.style.top = Math.random() * 100 + "%";
|
||
balloon.style.width = Math.random() * 40 + 60 + "px";
|
||
balloon.style.height = Math.random() * 60 + 80 + "px";
|
||
balloon.style.background = `radial-gradient(circle at 30% 30%, ${
|
||
colors[i % colors.length]
|
||
}, ${colors[(i + 1) % colors.length]})`;
|
||
balloon.style.animationDuration = Math.random() * 10 + 10 + "s";
|
||
document.body.appendChild(balloon);
|
||
}
|
||
}
|
||
|
||
// 添加随机鲜花
|
||
function createFlowers() {
|
||
const colors = ["#ffe66d", "#ff9a9e", "#74b9ff", "#a29bfe", "#55efc4"];
|
||
for (let i = 0; i < 6; i++) {
|
||
const flower = document.createElement("div");
|
||
flower.className = "flower";
|
||
flower.style.left = Math.random() * 100 + "%";
|
||
flower.style.top = Math.random() * 100 + "%";
|
||
flower.style.width = Math.random() * 30 + 50 + "px";
|
||
flower.style.height = Math.random() * 30 + 50 + "px";
|
||
flower.style.background = `radial-gradient(circle at center, ${
|
||
colors[i % colors.length]
|
||
} 30%, ${colors[(i + 2) % colors.length]} 100%)`;
|
||
flower.style.animationDuration = Math.random() * 5 + 8 + "s";
|
||
document.body.appendChild(flower);
|
||
}
|
||
}
|
||
|
||
// 页面加载后创建装饰
|
||
window.onload = function () {
|
||
createBalloons();
|
||
createFlowers();
|
||
};
|
||
</script>
|
||
</head>
|
||
|
||
<body>
|
||
<audio src="" controls id="audioPlayer" style="display: none"></audio>
|
||
<audio
|
||
src="MP3/背景音1.mp3"
|
||
id="bgMusic"
|
||
loop
|
||
style="display: none"
|
||
></audio>
|
||
<div class="main-container">
|
||
<!-- 开始菜单 -->
|
||
<div class="start-menu">
|
||
<h1 class="start-title">数字乐园</h1>
|
||
<div
|
||
style="
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 20px;
|
||
width: 100%;
|
||
margin-top: 20px;
|
||
"
|
||
>
|
||
<button
|
||
class="start-button"
|
||
id="numberButton"
|
||
style="display: flex; flex-direction: column; align-items: center"
|
||
>
|
||
<span style="font-size: 3rem; margin-bottom: 10px">🔢</span>
|
||
<span style="font-size: 1.2rem">数字学习</span>
|
||
</button>
|
||
<button
|
||
class="start-button"
|
||
id="audioGameButton"
|
||
style="display: flex; flex-direction: column; align-items: center"
|
||
>
|
||
<span style="font-size: 3rem; margin-bottom: 10px">👂</span>
|
||
<span style="font-size: 1.2rem">听音识数</span>
|
||
</button>
|
||
<button
|
||
class="start-button"
|
||
id="pictureGameButton"
|
||
style="display: flex; flex-direction: column; align-items: center"
|
||
>
|
||
<span style="font-size: 3rem; margin-bottom: 10px">👀</span>
|
||
<span style="font-size: 1.2rem">看图识数</span>
|
||
</button>
|
||
</div>
|
||
<button class="sound-toggle" id="soundToggle" style="margin-top: 30px">
|
||
<span class="sound-icon">🔊</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 游戏界面 -->
|
||
<div class="game-screen" id="gameScreen">
|
||
<div class="game-header">
|
||
<button class="back-button" id="backButton">←</button>
|
||
<div class="progress-container">
|
||
<div class="progress-bar" id="progressBar"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="game-content">
|
||
<img
|
||
class="game-image"
|
||
id="gameImage"
|
||
src="img/1/1.png"
|
||
alt="数字图片"
|
||
/>
|
||
|
||
<div class="number-options">
|
||
<button class="number-btn" data-number="1">1</button>
|
||
<button class="number-btn" data-number="2">2</button>
|
||
<button class="number-btn" data-number="3">3</button>
|
||
<button class="number-btn" data-number="4">4</button>
|
||
<button class="number-btn" data-number="5">5</button>
|
||
</div>
|
||
|
||
<div class="feedback" id="feedback"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 胜利界面 -->
|
||
<div class="victory-screen" id="victoryScreen">
|
||
<div class="victory-content">
|
||
<div class="victory-icon">★</div>
|
||
<button class="victory-button" id="victoryButton">↻</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 粒子特效容器 -->
|
||
<div class="particles" id="particles"></div>
|
||
</div>
|
||
|
||
<script>
|
||
async function speak2(text, vcn = "x4_lingyouyou", speed = 50) {
|
||
try {
|
||
const params = new URLSearchParams();
|
||
params.append("text", text);
|
||
params.append("vcn", vcn);
|
||
params.append("speed", speed);
|
||
|
||
const response = await fetch(
|
||
"http://rgclass.iflysse.com:8200/text2audio",
|
||
{
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||
body: params,
|
||
}
|
||
);
|
||
|
||
if (!response.ok) throw new Error(`请求失败: ${response.status}`);
|
||
|
||
const audioPath = await response.text();
|
||
const audioUrl = `http://rgclass.iflysse.com:8200${audioPath.trim()}`;
|
||
|
||
const audioPlayer = document.querySelector("#audioPlayer");
|
||
audioPlayer.src = audioUrl;
|
||
setTimeout(() => {
|
||
audioPlayer.load();
|
||
audioPlayer.play();
|
||
}, 200);
|
||
} catch (error) {
|
||
console.error("请求出错:", error);
|
||
}
|
||
}
|
||
// 游戏数据
|
||
const questions = [
|
||
{ image: "img/1/1.png", answer: 1 },
|
||
{ image: "img/2/1.png", answer: 2 },
|
||
{ image: "img/3/1.png", answer: 3 },
|
||
{ image: "img/4/1.png", answer: 4 },
|
||
{ image: "img/5/1.png", answer: 5 },
|
||
{ image: "img/1/2.png", answer: 1 },
|
||
{ image: "img/2/2.png", answer: 2 },
|
||
{ image: "img/3/2.png", answer: 3 },
|
||
{ image: "img/4/2.png", answer: 4 },
|
||
{ image: "img/5/2.png", answer: 5 },
|
||
];
|
||
|
||
// 游戏模式
|
||
let gameMode = "picture"; // 'picture'或'audio'
|
||
|
||
// 游戏状态
|
||
let currentQuestion = 0;
|
||
let correctAnswers = 0;
|
||
const totalQuestions = 5; // 需要答对的题目数量
|
||
let gameStarted = false;
|
||
let timer; // 倒计时计时器
|
||
|
||
// DOM元素
|
||
const startMenu = document.querySelector(".start-menu");
|
||
const gameScreen = document.getElementById("gameScreen");
|
||
const victoryScreen = document.getElementById("victoryScreen");
|
||
const startButton = document.getElementById("startButton");
|
||
const backButton = document.getElementById("backButton");
|
||
const victoryButton = document.getElementById("victoryButton");
|
||
const gameImage = document.getElementById("gameImage");
|
||
const feedback = document.getElementById("feedback");
|
||
const progressBar = document.getElementById("progressBar");
|
||
const particlesContainer = document.getElementById("particles");
|
||
|
||
// 事件监听
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
console.log("DOM fully loaded");
|
||
|
||
// 确保按钮存在
|
||
const numberButton = document.getElementById("numberButton");
|
||
if (numberButton) {
|
||
numberButton.addEventListener("click", function () {
|
||
// 创建数字语音学习界面
|
||
const voiceScreen = document.createElement("div");
|
||
voiceScreen.className = "start-menu";
|
||
voiceScreen.style.position = "absolute";
|
||
voiceScreen.innerHTML = `
|
||
<h1 class="start-title">数字语音</h1>
|
||
<div class="number-options" style="margin-top: 30px;">
|
||
<button class="number-btn" data-number="1">1</button>
|
||
<button class="number-btn" data-number="2">2</button>
|
||
<button class="number-btn" data-number="3">3</button>
|
||
<button class="number-btn" data-number="4">4</button>
|
||
<button class="number-btn" data-number="5">5</button>
|
||
</div>
|
||
<button class="start-button" style="margin-top: 30px;" id="backToMain">返回</button>
|
||
`;
|
||
|
||
document.querySelector(".main-container").appendChild(voiceScreen);
|
||
|
||
// 数字按钮点击事件
|
||
voiceScreen.querySelectorAll(".number-btn").forEach((btn) => {
|
||
btn.addEventListener("click", function () {
|
||
const number = parseInt(this.dataset.number);
|
||
speak2(`这是数字${number}`);
|
||
});
|
||
});
|
||
|
||
// 返回按钮事件
|
||
voiceScreen
|
||
.querySelector("#backToMain")
|
||
.addEventListener("click", function () {
|
||
voiceScreen.remove();
|
||
});
|
||
});
|
||
}
|
||
|
||
const audioGameButton = document.getElementById("audioGameButton");
|
||
if (audioGameButton) {
|
||
audioGameButton.addEventListener("click", () => initGame("audio"));
|
||
}
|
||
|
||
const pictureGameButton = document.getElementById("pictureGameButton");
|
||
if (pictureGameButton) {
|
||
pictureGameButton.addEventListener("click", () =>
|
||
initGame("picture")
|
||
);
|
||
}
|
||
|
||
const voiceButton = document.getElementById("voiceButton");
|
||
if (voiceButton) {
|
||
voiceButton.addEventListener("click", function () {
|
||
// 创建数字语音学习界面
|
||
const voiceScreen = document.createElement("div");
|
||
voiceScreen.className = "start-menu";
|
||
voiceScreen.style.position = "absolute";
|
||
voiceScreen.innerHTML = `
|
||
<h1 class="start-title">数字语音</h1>
|
||
<div class="number-options" style="margin-top: 30px;">
|
||
<button class="number-btn" data-number="1">1</button>
|
||
<button class="number-btn" data-number="2">2</button>
|
||
<button class="number-btn" data-number="3">3</button>
|
||
<button class="number-btn" data-number="4">4</button>
|
||
<button class="number-btn" data-number="5">5</button>
|
||
</div>
|
||
<button class="start-button" style="margin-top: 30px;" id="backToMain">返回</button>
|
||
`;
|
||
|
||
document.querySelector(".main-container").appendChild(voiceScreen);
|
||
|
||
// 数字按钮点击事件
|
||
voiceScreen.querySelectorAll(".number-btn").forEach((btn) => {
|
||
btn.addEventListener("click", function () {
|
||
const number = parseInt(this.dataset.number);
|
||
speak2(`这是数字${number}`);
|
||
});
|
||
});
|
||
|
||
// 返回按钮事件
|
||
voiceScreen
|
||
.querySelector("#backToMain")
|
||
.addEventListener("click", function () {
|
||
voiceScreen.remove();
|
||
});
|
||
});
|
||
}
|
||
|
||
if (backButton) {
|
||
backButton.addEventListener("click", backToMenu);
|
||
backButton.disabled = false;
|
||
}
|
||
|
||
if (victoryButton) {
|
||
victoryButton.addEventListener("click", backToMenu);
|
||
victoryButton.disabled = false;
|
||
}
|
||
|
||
// 数字按钮事件监听
|
||
document.querySelectorAll(".number-btn").forEach((btn) => {
|
||
btn.addEventListener("click", function () {
|
||
if (!this.disabled) {
|
||
checkAnswer(parseInt(this.dataset.number));
|
||
}
|
||
});
|
||
});
|
||
|
||
// 初始隐藏游戏和胜利界面
|
||
gameScreen.style.display = "none";
|
||
victoryScreen.style.display = "none";
|
||
|
||
// 显示开始菜单
|
||
startMenu.style.display = "flex";
|
||
startMenu.style.opacity = "1";
|
||
startMenu.style.pointerEvents = "auto";
|
||
});
|
||
|
||
// 音效控制
|
||
const soundToggle = document.getElementById("soundToggle");
|
||
let isSoundOn = true;
|
||
|
||
soundToggle.addEventListener("click", function () {
|
||
isSoundOn = !isSoundOn;
|
||
const soundIcon = this.querySelector(".sound-icon");
|
||
soundIcon.textContent = isSoundOn ? "🔊" : "🔇";
|
||
|
||
// 控制所有音频元素
|
||
document.querySelectorAll("audio").forEach((audio) => {
|
||
audio.muted = !isSoundOn;
|
||
});
|
||
|
||
// 播放音效状态提示
|
||
if (isSoundOn) {
|
||
speak2("音效已开启");
|
||
}
|
||
|
||
// 添加动画效果
|
||
this.style.transform = "scale(1.2)";
|
||
setTimeout(() => {
|
||
this.style.transform = "scale(1)";
|
||
}, 200);
|
||
});
|
||
|
||
// 初始化游戏
|
||
function initGame(mode = "picture") {
|
||
gameMode = mode;
|
||
currentQuestion = 0;
|
||
correctAnswers = 0;
|
||
gameStarted = true;
|
||
progressBar.style.width = "0%";
|
||
|
||
// 开始游戏跟踪
|
||
if (window.gameTracker) {
|
||
window.gameTracker.startGame(3, {
|
||
// 识数小精灵游戏ID
|
||
gameType: "number_recognition",
|
||
mode: mode,
|
||
totalQuestions: totalQuestions,
|
||
});
|
||
}
|
||
|
||
// 根据模式播放不同的背景音乐
|
||
const bgMusic = document.getElementById("bgMusic");
|
||
bgMusic.volume = 0.3;
|
||
bgMusic.muted = !isSoundOn;
|
||
|
||
if (mode === "picture") {
|
||
bgMusic.src = "MP3/背景音1.mp3";
|
||
speak2("小朋友,请观察图片并选择对应的数字");
|
||
} else if (mode === "audio") {
|
||
bgMusic.src = "MP3/背景音2.mp3";
|
||
speak2("小朋友,请听声音并选择对应的数字");
|
||
} else {
|
||
bgMusic.src = "MP3/背景音3.mp3";
|
||
}
|
||
|
||
bgMusic.play().catch((e) => console.log("自动播放被阻止:", e));
|
||
|
||
// 随机排序问题
|
||
shuffleArray(questions);
|
||
|
||
// 停止所有按钮的晃动效果
|
||
const numberButtons = document.querySelectorAll(".number-btn");
|
||
const audioButtons = document.querySelectorAll(".audio-btn");
|
||
const pictureButtons = document.querySelectorAll(".picture-btn");
|
||
|
||
numberButtons.forEach((btn) => {
|
||
btn.style.animation = "none";
|
||
});
|
||
audioButtons.forEach((btn) => {
|
||
btn.style.animation = "none";
|
||
});
|
||
pictureButtons.forEach((btn) => {
|
||
btn.style.animation = "none";
|
||
});
|
||
|
||
// 加载第一个问题
|
||
loadQuestion(currentQuestion);
|
||
|
||
// 显示游戏界面
|
||
startMenu.style.opacity = "0";
|
||
startMenu.style.pointerEvents = "none";
|
||
|
||
setTimeout(() => {
|
||
startMenu.style.display = "none";
|
||
gameScreen.style.display = "flex";
|
||
}, 500);
|
||
}
|
||
if (gameMode === "picture") {
|
||
speak2("小朋友,请观察图片并选择对应的数字");
|
||
} else {
|
||
speak2("小朋友,请听声音并选择对应的数字");
|
||
}
|
||
// 加载问题
|
||
function loadQuestion(index) {
|
||
if (index >= questions.length) {
|
||
shuffleArray(questions);
|
||
currentQuestion = 0;
|
||
}
|
||
|
||
// 重置错误计数器
|
||
window.errorCount = 0;
|
||
|
||
if (gameMode === "picture") {
|
||
gameImage.src = questions[index].image;
|
||
gameImage.style.display = "block";
|
||
} else {
|
||
gameImage.style.display = "none";
|
||
const correctNumber = questions[currentQuestion].answer;
|
||
speak2(`请找出数字${correctNumber}`);
|
||
}
|
||
|
||
feedback.style.opacity = "0";
|
||
feedback.textContent = "";
|
||
|
||
// 恢复所有数字按钮状态
|
||
const numberButtons = document.querySelectorAll(".number-btn");
|
||
numberButtons.forEach((btn) => {
|
||
btn.disabled = false;
|
||
btn.style.opacity = "1";
|
||
btn.style.cursor = "pointer";
|
||
btn.style.boxShadow = "0 10px 20px rgba(0, 0, 0, 0.2)";
|
||
});
|
||
|
||
// 清除之前的倒计时
|
||
if (timer) clearTimeout(timer);
|
||
|
||
// 设置5秒倒计时
|
||
timer = setTimeout(() => {
|
||
const correctNumber = questions[currentQuestion].answer;
|
||
const correctBtn = document.querySelector(
|
||
`.number-btn[data-number="${correctNumber}"]`
|
||
);
|
||
if (correctBtn) {
|
||
correctBtn.style.boxShadow = "0 0 20px 10px rgba(0, 255, 0, 0.5)";
|
||
correctBtn.style.transition = "box-shadow 2s ease-in-out";
|
||
|
||
// 添加晃动动画
|
||
correctBtn.style.animation = "bounce 0.5s infinite";
|
||
|
||
// 播放语音提示
|
||
if (gameMode === "picture") {
|
||
speak2("小朋友,选择正确的数字吧");
|
||
} else {
|
||
speak2(`请找出数字${correctNumber}`);
|
||
}
|
||
}
|
||
}, 5000);
|
||
}
|
||
|
||
// 检查答案
|
||
function checkAnswer(selectedNumber) {
|
||
if (!gameStarted) return;
|
||
|
||
// 清除倒计时
|
||
if (timer) clearTimeout(timer);
|
||
|
||
// 错误计数
|
||
if (typeof window.errorCount === "undefined") {
|
||
window.errorCount = 0;
|
||
}
|
||
|
||
const correctNumber = questions[currentQuestion].answer;
|
||
const isCorrect = selectedNumber === correctNumber;
|
||
|
||
// 详细数据打印
|
||
console.log("🎯 识数小精灵游戏 - 用户选择记录");
|
||
console.log("📊 问题信息:", {
|
||
问题编号: currentQuestion + 1,
|
||
问题内容: questions[currentQuestion].question || "未知问题",
|
||
正确答案: correctNumber,
|
||
用户选择: selectedNumber,
|
||
是否正确: isCorrect ? "✅ 正确" : "❌ 错误",
|
||
错误次数: window.errorCount,
|
||
});
|
||
console.log("📈 游戏进度:", {
|
||
当前得分: correctAnswers,
|
||
总问题数: totalQuestions,
|
||
完成进度: `${((correctAnswers / totalQuestions) * 100).toFixed(1)}%`,
|
||
});
|
||
console.log("⏰ 时间信息:", {
|
||
选择时间: new Date().toLocaleString("zh-CN"),
|
||
游戏时长: window.gameTracker
|
||
? window.gameTracker.getCurrentPlayTime() + "秒"
|
||
: "未知",
|
||
});
|
||
|
||
// 记录游戏尝试
|
||
if (window.gameTracker) {
|
||
window.gameTracker.recordAttempt();
|
||
}
|
||
|
||
if (isCorrect) {
|
||
// 正确答案处理
|
||
speak2("你太棒啦");
|
||
feedback.textContent = "✓";
|
||
feedback.className = "feedback correct";
|
||
feedback.style.opacity = "1";
|
||
|
||
// 移除正确按钮的晃动效果
|
||
const correctBtn = document.querySelector(
|
||
`.number-btn[data-number="${correctNumber}"]`
|
||
);
|
||
if (correctBtn) correctBtn.style.animation = "none";
|
||
|
||
// 禁用所有数字按钮
|
||
document.querySelectorAll(".number-btn").forEach((btn) => {
|
||
btn.disabled = true;
|
||
btn.style.opacity = "0.5";
|
||
btn.style.cursor = "not-allowed";
|
||
});
|
||
|
||
correctAnswers++;
|
||
progressBar.style.width = `${
|
||
(correctAnswers / totalQuestions) * 100
|
||
}%`;
|
||
createParticles(); // 正确答案时显示特效
|
||
|
||
// 记录正确答案
|
||
if (window.gameTracker) {
|
||
window.gameTracker.recordCorrect(10, {
|
||
question: questions[currentQuestion].question || "未知问题",
|
||
selected: selectedNumber,
|
||
correct: correctNumber,
|
||
questionNumber: currentQuestion + 1,
|
||
totalQuestions: totalQuestions,
|
||
errorCount: window.errorCount,
|
||
});
|
||
}
|
||
|
||
// 检查是否胜利
|
||
if (correctAnswers >= totalQuestions) {
|
||
showVictory();
|
||
} else {
|
||
// 延迟加载下一题
|
||
setTimeout(() => {
|
||
particlesContainer.innerHTML = ""; // 清除特效
|
||
currentQuestion++;
|
||
loadQuestion(currentQuestion);
|
||
}, 4000); // 延长到4秒
|
||
}
|
||
} else {
|
||
// 错误答案处理
|
||
speak2("答错了我们再想一想");
|
||
feedback.textContent = "✗";
|
||
feedback.className = "feedback incorrect";
|
||
feedback.style.opacity = "1";
|
||
|
||
// 增加错误计数
|
||
window.errorCount++;
|
||
|
||
// 记录错误答案
|
||
if (window.gameTracker) {
|
||
window.gameTracker.recordIncorrect(0, {
|
||
question: questions[currentQuestion].question || "未知问题",
|
||
selected: selectedNumber,
|
||
correct: correctNumber,
|
||
questionNumber: currentQuestion + 1,
|
||
totalQuestions: totalQuestions,
|
||
errorCount: window.errorCount,
|
||
});
|
||
}
|
||
|
||
// 禁用错误数字按钮
|
||
const numberButtons = document.querySelectorAll(".number-btn");
|
||
numberButtons.forEach((btn) => {
|
||
if (parseInt(btn.textContent) === selectedNumber) {
|
||
btn.disabled = true;
|
||
btn.style.opacity = "0.5";
|
||
btn.style.cursor = "not-allowed";
|
||
}
|
||
});
|
||
|
||
// 清除之前的计时器
|
||
if (timer) clearTimeout(timer);
|
||
|
||
// 如果错误达到2次,立即显示提示
|
||
if (window.errorCount >= 2) {
|
||
const correctNumber = questions[currentQuestion].answer;
|
||
const correctBtn = document.querySelector(
|
||
`.number-btn[data-number="${correctNumber}"]`
|
||
);
|
||
if (correctBtn) {
|
||
correctBtn.style.boxShadow = "0 0 20px 10px rgba(0, 255, 0, 0.5)";
|
||
correctBtn.style.transition = "box-shadow 2s ease-in-out";
|
||
correctBtn.style.animation = "bounce 0.5s infinite";
|
||
speak2("小朋友,正确的数字是" + correctNumber);
|
||
}
|
||
} else {
|
||
// 设置5秒后显示正确答案提示
|
||
timer = setTimeout(() => {
|
||
const correctNumber = questions[currentQuestion].answer;
|
||
const correctBtn = document.querySelector(
|
||
`.number-btn[data-number="${correctNumber}"]`
|
||
);
|
||
if (correctBtn) {
|
||
correctBtn.style.boxShadow =
|
||
"0 0 20px 10px rgba(0, 255, 0, 0.5)";
|
||
correctBtn.style.transition = "box-shadow 2s ease-in-out";
|
||
correctBtn.style.animation = "bounce 0.5s infinite";
|
||
speak2("小朋友,正确的数字是" + correctNumber);
|
||
}
|
||
}, 5000);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 显示胜利界面
|
||
function showVictory() {
|
||
speak2("小朋友你通关了你太厉害了");
|
||
gameScreen.style.display = "none";
|
||
victoryScreen.style.display = "flex";
|
||
|
||
// 根据游戏模式播放不同的胜利音效
|
||
const victorySound = document.createElement("audio");
|
||
if (isSoundOn) {
|
||
if (gameMode === "picture") {
|
||
victorySound.src = "MP3/最终胜利2.mp3";
|
||
} else {
|
||
victorySound.src = "MP3/胜利1.mp3";
|
||
}
|
||
// 受音量开关控制
|
||
const soundToggle = document.getElementById("soundToggle");
|
||
victorySound.muted = soundToggle.dataset.state === "off";
|
||
victorySound.play();
|
||
}
|
||
|
||
createParticles();
|
||
gameStarted = false;
|
||
}
|
||
|
||
// 返回菜单
|
||
function backToMenu() {
|
||
gameScreen.style.display = "none";
|
||
victoryScreen.style.display = "none";
|
||
startMenu.style.display = "flex";
|
||
startMenu.style.opacity = "1";
|
||
startMenu.style.pointerEvents = "auto";
|
||
|
||
// 清除粒子效果
|
||
particlesContainer.innerHTML = "";
|
||
|
||
// 暂停背景音乐
|
||
document.getElementById("bgMusic").pause();
|
||
|
||
// 重置游戏状态
|
||
gameStarted = false;
|
||
currentQuestion = 0;
|
||
correctAnswers = 0;
|
||
progressBar.style.width = "0%";
|
||
|
||
// 停止所有按钮的晃动效果
|
||
const numberButtons = document.querySelectorAll(".number-btn");
|
||
const audioButtons = document.querySelectorAll(".audio-btn");
|
||
const pictureButtons = document.querySelectorAll(".picture-btn");
|
||
|
||
numberButtons.forEach((btn) => {
|
||
btn.style.animation = "none";
|
||
});
|
||
audioButtons.forEach((btn) => {
|
||
btn.style.animation = "none";
|
||
});
|
||
pictureButtons.forEach((btn) => {
|
||
btn.style.animation = "none";
|
||
});
|
||
}
|
||
|
||
setTimeout(() => {
|
||
startMenu.style.opacity = "1";
|
||
startMenu.style.pointerEvents = "auto";
|
||
}, 100);
|
||
|
||
gameStarted = false;
|
||
|
||
// 重新开始游戏
|
||
function restartGame() {
|
||
victoryScreen.style.display = "none";
|
||
initGame();
|
||
}
|
||
|
||
// 数组随机排序
|
||
function shuffleArray(array) {
|
||
for (let i = array.length - 1; i > 0; i--) {
|
||
const j = Math.floor(Math.random() * (i + 1));
|
||
[array[i], array[j]] = [array[j], array[i]];
|
||
}
|
||
return array;
|
||
}
|
||
|
||
// 创建粒子特效
|
||
function createParticles() {
|
||
particlesContainer.innerHTML = "";
|
||
|
||
for (let i = 0; i < 50; i++) {
|
||
const particle = document.createElement("div");
|
||
particle.className = "particle";
|
||
|
||
// 随机位置
|
||
const x = Math.random() * 100;
|
||
const y = Math.random() * 100;
|
||
|
||
// 随机大小
|
||
const size = Math.random() * 10 + 5;
|
||
|
||
// 随机颜色
|
||
const hue = Math.random() * 60 + 30; // 黄色到橙色
|
||
particle.style.backgroundColor = `hsl(${hue}, 100%, 50%)`;
|
||
|
||
// 设置样式
|
||
particle.style.width = `${size}px`;
|
||
particle.style.height = `${size}px`;
|
||
particle.style.left = `${x}%`;
|
||
particle.style.top = `${y}%`;
|
||
|
||
// 动画
|
||
const duration = Math.random() * 3 + 2;
|
||
const delay = Math.random() * 2;
|
||
|
||
particle.style.animation = `float ${duration}s ease-in-out ${delay}s infinite`;
|
||
|
||
particlesContainer.appendChild(particle);
|
||
}
|
||
}
|
||
|
||
// 添加粒子动画关键帧
|
||
const style = document.createElement("style");
|
||
style.type = "text/css";
|
||
style.innerHTML = `
|
||
@keyframes float {
|
||
0% {
|
||
transform: translateY(0) rotate(0deg);
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
transform: translateY(-100vh) rotate(360deg);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
`;
|
||
document.head.appendChild(style);
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|
||
<style>
|
||
/* 悬浮提示样式 */
|
||
.tooltip {
|
||
position: absolute;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
color: white;
|
||
padding: 10px 15px;
|
||
border-radius: 10px;
|
||
font-size: 1.2rem;
|
||
max-width: 200px;
|
||
text-align: center;
|
||
z-index: 100;
|
||
pointer-events: none;
|
||
opacity: 0;
|
||
transition: opacity 0.3s;
|
||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||
}
|
||
</style>
|
||
|
||
<div class="tooltip" id="tooltip">
|
||
// ... existing code ...
|
||
<script>
|
||
// 悬浮提示功能
|
||
const tooltips = {
|
||
numberButton: "学习数字1-5的发音和写法",
|
||
audioGameButton: "听数字发音并选择正确答案",
|
||
pictureGameButton: "观察图片并选择对应的数字",
|
||
};
|
||
|
||
function showTooltip(buttonId, text) {
|
||
const button = document.getElementById(buttonId);
|
||
const tooltip = document.getElementById("tooltip");
|
||
|
||
const rect = button.getBoundingClientRect();
|
||
tooltip.textContent = text;
|
||
tooltip.style.left = `${
|
||
rect.left + rect.width / 2 - tooltip.offsetWidth / 2
|
||
}px`;
|
||
tooltip.style.top = `${rect.top - tooltip.offsetHeight - 10}px`;
|
||
tooltip.style.opacity = "1";
|
||
|
||
if (isSoundOn) {
|
||
speak2(text);
|
||
}
|
||
}
|
||
|
||
function hideTooltip() {
|
||
document.getElementById("tooltip").style.opacity = "0";
|
||
}
|
||
|
||
// 为菜单按钮添加悬浮事件
|
||
document.getElementById("numberButton").onmouseover = () =>
|
||
showTooltip("numberButton", tooltips.numberButton);
|
||
document.getElementById("numberButton").onmouseout = hideTooltip;
|
||
document.getElementById("audioGameButton").onmouseover = () =>
|
||
showTooltip("audioGameButton", tooltips.audioGameButton);
|
||
document.getElementById("audioGameButton").onmouseout = hideTooltip;
|
||
document.getElementById("pictureGameButton").onmouseover = () =>
|
||
showTooltip("pictureGameButton", tooltips.pictureGameButton);
|
||
document.getElementById("pictureGameButton").onmouseout = hideTooltip;
|
||
</script>
|
||
</div>
|