幼儿认知分类小游戏
by SilverPirate44297 lines13.9 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>幼儿认知分类小游戏</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; font-family: "Microsoft Yahei", sans-serif; }
body { background-color: #e6f7ff; padding: 20px; user-select: none; overflow: hidden; }
.container { max-width: 900px; margin: 0 auto; text-align: center; position: relative; z-index: 10; }
h1 { color: #ff6688; font-size: 36px; margin-bottom: 10px; margin-top: 20px; }
.tip-text { font-size: 28px; color: #333; margin-bottom: 30px; font-weight: bold; }
.level-text { color: #ff9900; font-size: 32px; }
.game-board { display: flex; flex-wrap: wrap; justify-content: center; gap: 30px; min-height: 400px; align-items: center; }
.item { width: 140px; height: 140px; cursor: pointer; transition: transform 0.2s ease; position: relative; background: #fff; border-radius: 20px; box-shadow: 0 6px 15px rgba(0,0,0,0.1); display: flex; justify-content: center; align-items: center; font-size: 80px; }
.item.correct-click { transform: scale(1.15); pointer-events: none; }
.item.correct-click { box-shadow: 0 0 25px #ffdd00, 0 0 50px #ffaa00; background: #fffcf0; }
@keyframes shake {
0%,100% { transform: translateX(0); }
25% { transform: translateX(-10px); }
75% { transform: translateX(10px); }
}
.item.wrong-click { animation: shake 0.4s ease; }
.star { position: absolute; top: -15px; right: -15px; font-size: 45px; display: none; animation: pop 0.3s ease; }
.item.correct-click .star { display: block; }
@keyframes pop { 0% { transform: scale(0); } 100% { transform: scale(1); } }
.float-tip { position: fixed; left: 50%; top: 40%; transform: translate(-50%, -50%); font-size: 46px; font-weight: bold; z-index: 50; animation: floatUp 1.2s ease forwards; pointer-events: none; text-shadow: 2px 2px 4px rgba(0,0,0,0.2); }
.tip-good { color: #28b948; }
.tip-bad { color: #ff3333; }
@keyframes floatUp { 0% { opacity: 1; transform: translate(-50%, -50%) scale(1); } 100% { opacity: 0; transform: translate(-50%, -100%) scale(1.2); } }
.modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 999; display: none; }
.modal-box { background: #fff; padding: 50px; border-radius: 30px; text-align: center; box-shadow: 0 10px 30px rgba(0,0,0,0.3); }
.modal-box h2 { font-size: 40px; color: #22bb55; margin-bottom: 30px; }
button { padding: 15px 40px; font-size: 26px; border: none; background: #4285f4; color: white; border-radius: 15px; cursor: pointer; font-weight: bold; transition: 0.2s; }
button:hover { background: #2b6ed9; transform: scale(1.05); }
/* 彩带画布 */
#confettiCanvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 100; }
</style>
</head>
<body>
<!-- 彩带容器 -->
<canvas id="confettiCanvas"></canvas>
<div class="container">
<h1>🎈幼儿认知分类小游戏</h1>
<div class="tip-text" id="levelTip"></div>
<div class="game-board" id="gameBoard"></div>
</div>
<div class="modal" id="passModal">
<div class="modal-box">
<h2 id="modalTitle">🎉太棒啦!通关成功!</h2>
<button id="nextBtn">下一关</button>
</div>
</div>
<script>
// ==== 🔊 音频合成器 ====
let audioCtx;
function initAudio() {
if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
if(audioCtx.state === 'suspended') audioCtx.resume();
}
function playCorrectSound() {
initAudio();
const osc = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
osc.type = 'sine';
osc.frequency.setValueAtTime(880, audioCtx.currentTime);
osc.frequency.exponentialRampToValueAtTime(1760, audioCtx.currentTime + 0.1);
gainNode.gain.setValueAtTime(0.5, audioCtx.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.4);
osc.connect(gainNode); gainNode.connect(audioCtx.destination);
osc.start(); osc.stop(audioCtx.currentTime + 0.4);
}
function playWrongSound() {
initAudio();
const osc = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(150, audioCtx.currentTime);
osc.frequency.linearRampToValueAtTime(100, audioCtx.currentTime + 0.3);
gainNode.gain.setValueAtTime(0.3, audioCtx.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3);
osc.connect(gainNode); gainNode.connect(audioCtx.destination);
osc.start(); osc.stop(audioCtx.currentTime + 0.3);
}
// 🎉 胜利专属音效(欢快的琶音)
function playWinSound() {
initAudio();
const notes = [523.25, 659.25, 783.99, 1046.50]; // C5, E5, G5, C6
notes.forEach((freq, index) => {
setTimeout(() => {
const osc = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
osc.type = 'triangle';
osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
gainNode.gain.setValueAtTime(0.4, audioCtx.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3);
osc.connect(gainNode); gainNode.connect(audioCtx.destination);
osc.start(); osc.stop(audioCtx.currentTime + 0.3);
}, index * 150); // 每个音符间隔0.15秒
});
}
// ==== 🎊 彩带特效逻辑 ====
function createConfetti() {
const canvas = document.getElementById('confettiCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const confettiCount = 200; // 彩带数量
const colors = ['#ff595e', '#ffca3a', '#8ac926', '#1982c4', '#6a4c93'];
let confettis = [];
for (let i = 0; i < confettiCount; i++) {
confettis.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height - canvas.height,
w: Math.random() * 10 + 5,
h: Math.random() * 10 + 5,
color: colors[Math.floor(Math.random() * colors.length)],
speedY: Math.random() * 3 + 2,
speedX: Math.random() * 2 - 1,
rot: Math.random() * 360,
rotSpeed: Math.random() * 5 - 2.5
});
}
function updateConfetti() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
let active = false;
confettis.forEach(c => {
c.y += c.speedY;
c.x += c.speedX;
c.rot += c.rotSpeed;
if (c.y < canvas.height) active = true;
ctx.save();
ctx.translate(c.x, c.y);
ctx.rotate(c.rot * Math.PI / 180);
ctx.fillStyle = c.color;
ctx.fillRect(-c.w / 2, -c.h / 2, c.w, c.h);
ctx.restore();
});
if (active) {
requestAnimationFrame(updateConfetti);
} else {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}
updateConfetti();
}
// ==== 🎮 游戏主逻辑 ====
const pool = {
fruits: ["🍎", "🍌", "🍇", "🍓", "🍉", "🍊", "🍒", "🥝", "🍍", "🍑", "🍐", "🍋", "🥥", "🥭"],
animals: ["🐱", "🐶", "🐰", "🐼", "🐯", "🦁", "🐸", "🐵", "🐷", "🐮", "🐔", "🦊", "🐻", "🐨"],
vehicles: ["🚗", "🚌", "✈️", "🚲", "🚂", "🚀", "🚁", "🚢", "🚕", "🏎️", "🛵", "🚓", "🚑", "🚒"]
};
const levelsConfig = [
{ title: "请点击所有的【水果】🍎", rightType: "fruits", wrongType: "animals" },
{ title: "请点击所有的【动物】🐱", rightType: "animals", wrongType: "vehicles" },
{ title: "请点击所有的【交通工具】🚗", rightType: "vehicles", wrongType: "fruits" }
];
let currentLevel = 0;
let correctCount = 0;
let totalRight = 0;
const gameBoard = document.getElementById("gameBoard");
const levelTip = document.getElementById("levelTip");
const passModal = document.getElementById("passModal");
const nextBtn = document.getElementById("nextBtn");
const modalTitle = document.getElementById("modalTitle");
function shuffle(array) {
let currentIndex = array.length, randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}
return array;
}
function getRandomItems(arr, count) {
let shuffled = shuffle([...arr]);
return shuffled.slice(0, count);
}
function showFloatText(text, type) {
const div = document.createElement("div");
div.innerText = text;
div.className = "float-tip " + type;
document.body.appendChild(div);
setTimeout(()=>div.remove(), 1200);
}
function loadLevel() {
const config = levelsConfig[currentLevel];
// 显示关卡号
levelTip.innerHTML = `<span class="level-text">第 ${currentLevel + 1} 关</span><br>${config.title}`;
gameBoard.innerHTML = "";
correctCount = 0;
const rightItems = getRandomItems(pool[config.rightType], 3).map(e => ({emoji: e, isRight: true}));
const wrongItems = getRandomItems(pool[config.wrongType], 3).map(e => ({emoji: e, isRight: false}));
const currentItems = shuffle([...rightItems, ...wrongItems]);
totalRight = rightItems.length;
passModal.style.display = "none";
currentItems.forEach(item => {
const div = document.createElement("div");
div.className = "item";
div.innerText = item.emoji;
const star = document.createElement("span");
star.innerText = "⭐";
star.className = "star";
div.appendChild(star);
div.onclick = () => {
if(div.classList.contains("correct-click")) return;
if(item.isRight) {
playCorrectSound();
div.classList.add("correct-click");
correctCount++;
showFloatText("太棒啦!", "tip-good");
if(correctCount >= totalRight) {
setTimeout(()=> {
passModal.style.display = "flex";
if(currentLevel === levelsConfig.length - 1) {
// 第三关(最后一关)通关!
modalTitle.innerText = "🎉全部通关!你太厉害了!";
nextBtn.innerText = "再玩一次";
playWinSound(); // 播放胜利音效
createConfetti(); // 播放彩带
} else {
modalTitle.innerText = "🎉太棒啦!通关成功!";
nextBtn.innerText = "进入下一关";
}
}, 600);
}
} else {
playWrongSound();
div.classList.add("wrong-click");
showFloatText("再试一试哦~", "tip-bad");
setTimeout(()=> div.classList.remove("wrong-click"), 400);
}
};
gameBoard.appendChild(div);
});
}
nextBtn.onclick = () => {
if(currentLevel < levelsConfig.length - 1) {
currentLevel++;
} else {
currentLevel = 0; // 重新开始
// 如果是重新开始,清理彩带
const canvas = document.getElementById('confettiCanvas');
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
loadLevel();
};
// 窗口大小改变时调整彩带画布
window.addEventListener('resize', () => {
const canvas = document.getElementById('confettiCanvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
loadLevel();
</script>
</body>
</html>Game Source: 幼儿认知分类小游戏
Creator: SilverPirate44
Libraries: none
Complexity: complex (297 lines, 13.9 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-silverpirate44" to link back to the original. Then publish at arcadelab.ai/publish.