Files
RGKT/rg-09112127/html/play/比大小.html

710 lines
21 KiB
HTML
Raw Permalink Normal View History

2025-10-10 19:44:14 +08:00
<!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>