[MF]修改石头剪刀布倒计时和随机逻辑

This commit is contained in:
51hhh 2025-08-26 09:57:09 +08:00
parent 59ba028e01
commit 539eadbaf3

View File

@ -137,6 +137,36 @@
z-index: 3; z-index: 3;
} }
/* --- Start: Countdown specific styles --- */
.countdown-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85); /* Slightly darker for better contrast */
display: flex;
justify-content: center;
align-items: center;
font-size: 8rem; /* Large font for countdown */
font-weight: bold;
color: #00d4ff;
text-shadow: 0 0 30px rgba(0, 212, 255, 0.8);
z-index: 5; /* Above video/canvas but below status bar if needed, adjusted based on existing z-index structure */
border-radius: 15px;
opacity: 0;
transition: opacity 0.3s ease-in-out;
pointer-events: none; /* Allow interaction with elements behind it when not visible */
}
.countdown-overlay.show {
opacity: 1;
/* When visible, it takes pointer events to block interaction with video elements */
pointer-events: auto;
}
/* --- End: Countdown specific styles --- */
/* Control Panel */ /* Control Panel */
.control-panel { .control-panel {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%); background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
@ -354,6 +384,9 @@
<div id="video-container"> <div id="video-container">
<video id="videoFeed" autoplay muted playsinline></video> <video id="videoFeed" autoplay muted playsinline></video>
<canvas id="poseCanvas"></canvas> <canvas id="poseCanvas"></canvas>
<!-- START: Countdown Overlay Element -->
<div id="countdownOverlay" class="countdown-overlay"></div>
<!-- END: Countdown Overlay Element -->
<div class="status-bar" id="statusDisplay">正在初始化系统...</div> <div class="status-bar" id="statusDisplay">正在初始化系统...</div>
</div> </div>
</div> </div>
@ -422,6 +455,9 @@
const resetBtn = document.getElementById('resetBtn'); const resetBtn = document.getElementById('resetBtn');
const importModelBtn = document.getElementById('importModelBtn'); const importModelBtn = document.getElementById('importModelBtn');
const fileImporter = document.getElementById('fileImporter'); const fileImporter = document.getElementById('fileImporter');
// START: Add Countdown Overlay Element
const countdownOverlay = document.getElementById('countdownOverlay');
// END: Add Countdown Overlay Element
let detector; let detector;
let classifier; let classifier;
@ -433,6 +469,9 @@
let currentRound = 0; let currentRound = 0;
let lastPrediction = null; let lastPrediction = null;
let predictionCooldown = false; let predictionCooldown = false;
// START: Add countdown state variable
let isCountingDown = false;
// END: Add countdown state variable
// 手势映射 // 手势映射
const gestureMap = { const gestureMap = {
@ -575,7 +614,10 @@
if (hands && hands.length > 0) { if (hands && hands.length > 0) {
drawHand(hands[0]); drawHand(hands[0]);
if (isModelLoaded && isPlaying && !predictionCooldown) { // START: Modify prediction condition to include isCountingDown
// Only make predictions if game is playing AND not in cooldown AND NOT counting down
if (isModelLoaded && isPlaying && !predictionCooldown && !isCountingDown) {
// END: Modify prediction condition to include isCountingDown
const handTensor = flattenHand(hands[0]); const handTensor = flattenHand(hands[0]);
if (classifier.getNumClasses() > 0) { if (classifier.getNumClasses() > 0) {
@ -587,12 +629,12 @@
const predictedGesture = gestureMap[prediction.label]; const predictedGesture = gestureMap[prediction.label];
if (predictedGesture && prediction.label !== lastPrediction) { if (predictedGesture && prediction.label !== lastPrediction) {
lastPrediction = prediction.label; lastPrediction = prediction.label;
// ORIGINAL playRound call
playRound(predictedGesture); playRound(predictedGesture);
predictionCooldown = true; predictionCooldown = true;
setTimeout(() => { // START: Initiate countdown AFTER a round is played
predictionCooldown = false; startCountdownForNextRound();
lastPrediction = null; // END: Initiate countdown AFTER a round is played
}, 2000);
} }
} }
} else { } else {
@ -653,7 +695,7 @@
// 游戏逻辑 // 游戏逻辑
function playRound(userGesture) { function playRound(userGesture) {
currentRound++; currentRound++; // IMPORTANT: Restore this line
// AI 随机选择 // AI 随机选择
const aiOptions = Object.values(gestureMap); const aiOptions = Object.values(gestureMap);
@ -692,21 +734,69 @@
resultDisplay.innerHTML = `<div class="result-text ${resultClass}">${result}</div>`; resultDisplay.innerHTML = `<div class="result-text ${resultClass}">${result}</div>`;
} }
// 开始游戏 // START: New function for countdown before next round
function startCountdownForNextRound() {
if (!isPlaying) return; // Only run if game is active
isCountingDown = true; // Disable hand detection during countdown
countdownOverlay.textContent = ''; // Clear previous text
countdownOverlay.classList.add('show');
updateStatus('下一回合准备中...');
let count = 3;
const countdownInterval = setInterval(() => {
if (count > 0) {
countdownOverlay.textContent = count;
count--;
} else {
clearInterval(countdownInterval);
countdownOverlay.classList.remove('show');
countdownOverlay.textContent = ''; // Clear "GO!" text immediately
isCountingDown = false; // Enable hand detection again
predictionCooldown = false; // Allow new predictions
lastPrediction = null; // Reset last prediction to allow new gesture
updateStatus('游戏进行中 - 请做出手势');
// Clear previous choices and results for the new round
userChoiceDisplay.textContent = '-';
aiChoiceDisplay.textContent = '-';
resultDisplay.innerHTML = '';
choicesDisplay.style.display = 'flex'; // Ensure choices are visible for new round
}
}, 1000);
}
// END: New function for countdown
// 开始游戏 (Modified to initiate first round countdown)
function startGame() { function startGame() {
isPlaying = true; isPlaying = true;
currentRound = 0; currentRound = 0; // Initialize to 0, playRound will increment it to 1 for the first round.
roundInfo.textContent = '游戏进行中...';
choicesDisplay.style.display = 'none'; // Clear choices and results display immediately when game starts
userChoiceDisplay.textContent = '-';
aiChoiceDisplay.textContent = '-';
resultDisplay.innerHTML = ''; resultDisplay.innerHTML = '';
choicesDisplay.style.display = 'flex'; // Ensure choices are visible when game starts
startBtn.textContent = '游戏中...'; startBtn.textContent = '游戏中...';
startBtn.disabled = true; startBtn.disabled = true;
updateStatus('游戏进行中 - 请做出手势'); resetBtn.disabled = false; // Enable reset once game starts
importModelBtn.disabled = true; // Disable import once game starts
// Start the very first countdown for the first round
startCountdownForNextRound();
// Note: statusDisplay will be updated by startCountdownForNextRound
} }
// 重置游戏 // 重置游戏 (Modified to handle countdown state cleanup)
function resetGame() { function resetGame() {
isPlaying = false; isPlaying = false;
// START: Clean up countdown state on reset
isCountingDown = false;
countdownOverlay.classList.remove('show');
countdownOverlay.textContent = '';
// END: Clean up countdown state on reset
scores = { user: 0, ai: 0 }; scores = { user: 0, ai: 0 };
currentRound = 0; currentRound = 0;
userScoreDisplay.textContent = '0'; userScoreDisplay.textContent = '0';
@ -716,6 +806,8 @@
resultDisplay.innerHTML = ''; resultDisplay.innerHTML = '';
startBtn.textContent = '开始游戏'; startBtn.textContent = '开始游戏';
startBtn.disabled = !isModelLoaded; startBtn.disabled = !isModelLoaded;
resetBtn.disabled = false; // Already enabled, just ensuring
importModelBtn.disabled = false; // Enable import button again
predictionCooldown = false; predictionCooldown = false;
lastPrediction = null; lastPrediction = null;
updateStatus(isModelLoaded ? '准备就绪' : '请导入模型'); updateStatus(isModelLoaded ? '准备就绪' : '请导入模型');