Files
RGKT/rg-09112127/html/play/比大小.html
2025-10-10 19:44:14 +08:00

710 lines
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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/virtualTeacher.js"></script>
<script src="../../js/gameVirtualTeacher.js"></script>
<!-- 引入体感交互脚本 -->
<script src="../../js/directBodySensation.js"></script>
<style>
:root {
--primary: #ff9aa2;
--secondary: #ffb7b2;
--accent: #ffdac1;
--correct: #b5ead7;
--wrong: #ff9aa2;
--button: #70a1ff;
--text: #5e5346;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Comic Sans MS", "Marker Felt", "微软雅黑", sans-serif;
background-color: #f9f7f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-image: radial-gradient(circle, #f5f5f5 10%, transparent 10%);
background-size: 30px 30px;
overflow: hidden;
}
.game-container {
width: 80%;
background-color: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
text-align: center;
position: relative;
overflow: hidden;
border: 5px solid #ffdac1;
}
h1 {
color: #ff6b6b;
margin-bottom: 30px;
font-size: 5rem;
text-shadow: 3px 3px 0 #ffdac1;
letter-spacing: 2px;
}
.game-area {
display: flex;
justify-content: space-around;
margin: 30px 0;
}
.math-card {
width: 45%;
padding: 20px;
background-color: #f0f8ff;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
position: relative;
transition: all 0.3s ease;
}
.math-card:hover,
.math-card.active {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
}
.math-card::before {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
border: 3px dashed #ffb7b2;
border-radius: 20px;
z-index: -1;
opacity: 0.5;
}
.equation {
font-size: 5rem;
margin: 20px 0;
color: #5e5346;
font-weight: bold;
}
.select-btn {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: var(--button);
color: white;
border: none;
font-size: 2rem;
font-weight: bold;
cursor: pointer;
box-shadow: 0 5px 0 #4a6baf;
transition: all 0.2s ease;
margin-top: 10px;
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
}
.select-btn:hover {
background-color: #5d8eff;
transform: scale(1.05);
}
.select-btn:active {
transform: translateY(5px);
box-shadow: 0 2px 0 #4a6baf;
}
.message {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
background-color: white;
padding: 30px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
z-index: 100;
text-align: center;
max-width: 80%;
transition: all 0.3s ease;
border: 5px solid;
}
.message.show {
transform: translate(-50%, -50%) scale(1);
}
.message.correct {
border-color: #b5ead7;
background-color: #e8f8f3;
}
.message.wrong {
border-color: #ff9aa2;
background-color: #ffeef0;
}
.message h2 {
font-size: 3rem;
margin-bottom: 15px;
}
.message p {
font-size: 2rem;
margin-bottom: 20px;
}
.message-btn {
padding: 10px 20px;
border-radius: 50px;
border: none;
background-color: var(--button);
color: white;
font-size: 2rem;
cursor: pointer;
transition: all 0.2s ease;
}
.message-btn:hover {
background-color: #5d8eff;
transform: scale(1.05);
}
/* 体感交互视频样式 */
.body-sensation-container {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(255, 255, 255, 0.95);
border-radius: 15px;
padding: 20px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
z-index: 1000;
max-width: 600px;
}
.body-video-feed {
position: relative;
width: 500px;
height: 350px;
border-radius: 10px;
overflow: hidden;
margin-bottom: 15px;
}
.body-video-feed img {
width: 100%;
height: 100%;
object-fit: cover;
}
.body-status-overlay {
position: absolute;
top: 15px;
left: 15px;
right: 15px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 15px;
border-radius: 8px;
font-size: 14px;
line-height: 1.3;
}
.body-instruction {
text-align: center;
font-size: 18px;
color: #333;
font-weight: 500;
padding: 8px;
}
/* 体感交互容器样式用于directBodySensation.js */
.box-body {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(255, 255, 255, 0.95);
border-radius: 15px;
padding: 20px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
z-index: 2000;
max-width: 500px;
text-align: center;
}
.box-body img {
max-width: 100%;
height: auto;
border-radius: 10px;
margin: 10px 0;
}
.box-body div {
margin: 10px 0;
padding: 5px;
}
.confetti {
position: absolute;
width: 15px;
height: 15px;
background-color: var(--primary);
opacity: 0;
z-index: 90;
}
@keyframes confetti-fall {
0% {
transform: translateY(-100vh) rotate(0deg);
opacity: 1;
}
100% {
transform: translateY(100vh) rotate(360deg);
opacity: 0;
}
}
@keyframes jump {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-30px);
}
}
@media (max-width: 600px) {
.game-area {
flex-direction: column;
align-items: center;
}
.math-card {
width: 90%;
margin-bottom: 20px;
}
h1 {
font-size: 5rem;
}
.equation {
font-size: 5rem;
}
}
</style>
</head>
<body>
<div class="game-container">
<h1>比大小(选择大的)</h1>
<div class="game-area">
<div class="math-card" id="leftCard">
<div class="equation" id="leftEquation">1+1</div>
<button class="select-btn" id="leftBtn">选择</button>
</div>
<div class="math-card" id="rightCard">
<div class="equation" id="rightEquation">2+2</div>
<button class="select-btn" id="rightBtn">选择</button>
</div>
</div>
</div>
<div class="message" id="message">
<h2 id="messageTitle">标题</h2>
<p id="messageText">内容</p>
<button class="message-btn" id="messageBtn">继续</button>
</div>
<script>
// DOM元素
const leftEquation = document.getElementById("leftEquation");
const rightEquation = document.getElementById("rightEquation");
const leftBtn = document.getElementById("leftBtn");
const rightBtn = document.getElementById("rightBtn");
const message = document.getElementById("message");
const messageTitle = document.getElementById("messageTitle");
const messageText = document.getElementById("messageText");
const messageBtn = document.getElementById("messageBtn");
// 体感交互元素
const bodySensationContainer = document.getElementById(
"bodySensationContainer"
);
const bodyVideoFeed = document.getElementById("bodyVideoFeed");
const bodyConnectionStatus = document.getElementById(
"bodyConnectionStatus"
);
const bodyHandStatus = document.getElementById("bodyHandStatus");
const bodyInstruction = document.getElementById("bodyInstruction");
// 游戏状态
let leftValue = 0;
let rightValue = 0;
let correctAnswer = "";
let score = 0;
let correctCount = 0;
let totalQuestions = 0;
let gameStarted = false;
let gameId = 2; // 比大小游戏ID
// 体感交互控制函数
function showBodyInteraction() {
if (bodySensationContainer) {
bodySensationContainer.style.display = "block";
}
// 启动体感交互系统
if (typeof showBody === "function") {
showBody();
}
}
function hideBodyInteraction() {
if (bodySensationContainer) {
bodySensationContainer.style.display = "none";
}
}
function updateBodyInstruction(text) {
if (bodyInstruction) {
bodyInstruction.textContent = text;
}
}
// 生成5以内的加减法
function generateEquation() {
const operations = ["+", "-"];
const op = operations[Math.floor(Math.random() * operations.length)];
let a, b, result;
do {
a = Math.floor(Math.random() * 5) + 1; // 1-5
b = Math.floor(Math.random() * 5) + 1; // 1-5
if (op === "+") {
result = a + b;
} else {
result = a - b;
// 确保结果不小于0
if (result < 0) {
[a, b] = [b, a]; // 交换a和b
result = a - b;
}
}
} while (result > 5); // 确保结果不超过5
return {
equation: `${a}${op}${b}`,
value: result,
};
}
// 生成新题目
function generateNewQuestion(type) {
// 清除默认样式
document.querySelectorAll(".math-card")[0].className = "math-card";
document.querySelectorAll(".math-card")[1].className = "math-card";
if (type == "init") {
// 初始化游戏状态
score = 0;
correctCount = 0;
totalQuestions = 0;
gameStarted = true;
// 虚拟老师游戏开始
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher.gameStart("比大小游戏");
}
// 开始游戏跟踪
if (window.gameTracker) {
window.gameTracker.startGame(gameId, {
gameType: "compare_size",
difficulty: "easy",
});
}
// 打开窗口
iframePostMessage();
}
const left = generateEquation();
const right = generateEquation();
leftEquation.textContent = left.equation;
rightEquation.textContent = right.equation;
leftValue = left.value;
rightValue = right.value;
// 显示体感交互视频
showBodyInteraction();
// 更新体感交互提示文本
updateBodyInstruction(
`请举起左手选择${left.equation}或举起右手选择${right.equation}`
);
correctAnswer =
leftValue > rightValue
? "left"
: rightValue > leftValue
? "right"
: "equal";
}
// 显示消息
function showMessage(isCorrect, text) {
message.className = "message " + (isCorrect ? "correct" : "wrong");
messageTitle.textContent = isCorrect ? "太棒了!" : "再试一次";
messageText.textContent = text;
message.classList.add("show");
if (isCorrect) {
createConfetti();
}
}
// 创建彩色纸屑效果
function createConfetti() {
const colors = [
"#FF9AA2",
"#FFB7B2",
"#FFDAC1",
"#E2F0CB",
"#B5EAD7",
"#C7CEEA",
];
for (let i = 0; i < 50; i++) {
const confetti = document.createElement("div");
confetti.className = "confetti";
confetti.style.left = `${Math.random() * 100}%`;
confetti.style.backgroundColor =
colors[Math.floor(Math.random() * colors.length)];
confetti.style.width = `${Math.random() * 10 + 5}px`;
confetti.style.height = `${Math.random() * 10 + 5}px`;
confetti.style.animation = `confetti-fall ${
Math.random() * 2 + 2
}s linear forwards`;
confetti.style.animationDelay = `${Math.random() * 0.5}s`;
document.body.appendChild(confetti);
setTimeout(() => {
confetti.remove();
}, 3000);
}
}
// 检查答案
function checkAnswer(selectedSide) {
console.log(
"checkAnswer message",
document.getElementById("message"),
document.getElementById("message").classList.contains("show")
);
if (document.getElementById("message").classList.contains("show")) {
return;
}
// 隐藏体感交互按钮
hideBodyInteraction();
let isCorrect = false;
let message = "";
document.querySelectorAll(".math-card")[
selectedSide == "left" ? 0 : 1
].className = "math-card active";
if (correctAnswer === "equal") {
isCorrect = true;
message = "两边一样大!";
} else if (selectedSide === correctAnswer) {
isCorrect = true;
message = `对了!${leftValue} ${
selectedSide === "left" ? ">" : "<"
} ${rightValue}`;
} else {
isCorrect = false;
message = `不对哦!${leftValue} ${
correctAnswer === "left" ? ">" : "<"
} ${rightValue}`;
}
// 虚拟老师反馈
if (window.gameVirtualTeacher) {
// 立即停止当前语音
window.gameVirtualTeacher.stopAllSpeech();
// 延迟一点再播放反馈语音
setTimeout(() => {
if (isCorrect) {
window.gameVirtualTeacher.recordCorrect();
} else {
window.gameVirtualTeacher.recordIncorrect();
}
}, 300);
}
// 详细数据打印
console.log("🎯 比大小游戏 - 用户点击记录");
console.log("📊 问题信息:", {
问题内容: `${leftValue} vs ${rightValue}`,
左侧值: leftValue,
右侧值: rightValue,
正确答案: correctAnswer,
用户选择: selectedSide,
是否正确: isCorrect ? "✅ 正确" : "❌ 错误",
});
console.log("📈 游戏进度:", {
当前得分: score,
正确次数: correctCount,
总问题数: totalQuestions + 1,
正确率:
totalQuestions > 0
? `${((correctCount / (totalQuestions + 1)) * 100).toFixed(1)}%`
: "0%",
});
console.log("⏰ 时间信息:", {
回答时间: new Date().toLocaleString("zh-CN"),
游戏时长: window.gameTracker
? window.gameTracker.getCurrentPlayTime() + "秒"
: "未知",
});
// 记录游戏结果
if (gameStarted && window.gameTracker) {
totalQuestions++;
if (isCorrect) {
correctCount++;
score += 10;
window.gameTracker.recordCorrect(10, {
question: `${leftValue} vs ${rightValue}`,
selected: selectedSide,
correct: correctAnswer,
leftValue: leftValue,
rightValue: rightValue,
questionNumber: totalQuestions,
});
} else {
window.gameTracker.recordIncorrect(0, {
question: `${leftValue} vs ${rightValue}`,
selected: selectedSide,
correct: correctAnswer,
leftValue: leftValue,
rightValue: rightValue,
questionNumber: totalQuestions,
});
}
}
showMessage(isCorrect, message);
}
// 事件监听
leftBtn.addEventListener("click", (event) => checkAnswer("left"));
rightBtn.addEventListener("click", (event) => checkAnswer("right"));
messageBtn.addEventListener("click", () => {
message.classList.remove("show");
generateNewQuestion("continue");
});
// 页面加载完成后初始化
document.addEventListener("DOMContentLoaded", function () {
// 初始化虚拟老师
if (window.gameVirtualTeacher) {
window.gameVirtualTeacher
.init({
intro: "欢迎来到比大小游戏!我会帮你比较数字的大小,准备好了吗?",
})
.then(() => {
console.log("🦉 比大小游戏虚拟老师初始化成功");
// 延迟播放游戏介绍,避免与访问跟踪语音冲突
setTimeout(() => {
window.gameVirtualTeacher.speak(
"欢迎来到比大小游戏!我会帮你比较数字的大小,准备好了吗?"
);
}, 1000);
})
.catch((error) => {
console.error("❌ 虚拟老师初始化失败:", error);
});
}
// 初始化后端集成
Promise.all([window.userManager.init(), window.dataManager.init()])
.then(() => {
console.log("后端集成初始化完成");
// 初始化游戏
generateNewQuestion("init");
})
.catch((error) => {
console.error("后端集成初始化失败:", error);
// 即使后端初始化失败,也可以开始游戏
generateNewQuestion("init");
});
});
// 网页间相互通信
window.addEventListener("message", function (event) {
// 检查消息来源是否可信
if (event.origin !== "http://localhost") return;
const message = event.data;
console.log("iframe 接收到的数据:", message);
if (message.type == "语音识别") {
} else if (message.type == "体感识别") {
if (message.data.indexOf("左手") !== -1) {
checkAnswer("left");
} else if (message.data.indexOf("右手") !== -1) {
checkAnswer("right");
} else if (message.data.indexOf("双手") !== -1) {
messageBtn.click();
}
}
});
function iframePostMessage() {
const message = { type: "体感识别", status: "request" };
window.parent.postMessage(message, "http://localhost"); // 替换为目标域名
}
// 页面销毁时,关闭体感采集
window.onbeforeunload = function (event) {
iframePostMessage();
};
</script>
</body>
</html>