将以下代码保存为 接单词.txt # 互动英语单词打字游戏实现方案
我将创建一个英语单词从屏幕顶部掉落且有旋转效果的互动打字游戏,包含所有您要求的功能。
## 设计思路
1. 使用HTML Canvas绘制游戏界面和动画
2. JavaScript实现游戏逻辑和控制
3. 单词随机从列表选取并下落
4. 输入框位于底部,有占位提示
5. 单词成功输入或到底部时消失并淡出
6. 每5秒生成新单词
7. 单词下落速度随时间增加
8. 旋转效果通过CSS 3D变换实现
下面是完整的实现代码:
```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>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial Rounded MT Bold', 'Segoe UI', sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
color: white;
min-height: 100vh;
padding: 20px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
}
.header {
text-align: center;
margin-bottom: 20px;
width: 100%;
padding: 15px;
background: rgba(0, 0, 0, 0.4);
border-radius: 15px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(8px);
}
h1 {
font-size: 2.8rem;
margin-bottom: 10px;
text-shadow: 0 4px 8px rgba(0, 0, 0, 0.6);
background: linear-gradient(to right, #ff8a00, #e52e71);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.subtitle {
font-size: 1.2rem;
max-width: 800px;
margin: 0 auto;
color: #ddd;
}
.stats {
display: flex;
justify-content: space-around;
width: 100%;
max-width: 800px;
margin: 15px auto;
padding: 15px;
background: rgba(0, 0, 0, 0.3);
border-radius: 12px;
font-size: 1.2rem;
}
.stat-item {
text-align: center;
padding: 10px;
}
.stat-value {
font-size: 1.8rem;
font-weight: bold;
color: #ffd700;
}
.game-container {
position: relative;
width: 800px;
height: 500px;
background: rgba(0, 0, 50, 0.6);
border-radius: 15px;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
overflow: hidden;
margin: 15px 0 25px;
border: 2px solid #4a76ef;
}
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#gameCanvas {
z-index: 1;
}
#effectsCanvas {
z-index: 2;
pointer-events: none;
}
.input-container {
display: flex;
flex-direction: column;
width: 800px;
padding: 15px;
background: rgba(0, 0, 0, 0.5);
border-radius: 15px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
margin-top: 15px;
}
label {
margin-bottom: 10px;
font-size: 1.3rem;
color: #4df;
}
#wordInput {
width: 100%;
padding: 15px;
font-size: 1.5rem;
border: none;
border-radius: 10px;
background: rgba(255, 255, 255, 0.95);
color: #333;
outline: none;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
#wordInput:focus {
box-shadow: 0 4px 20px rgba(100, 200, 255, 0.6);
transform: translateY(-2px);
}
.controls {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 20px;
width: 800px;
}
button {
padding: 13px 35px;
font-size: 1.2rem;
border: none;
border-radius: 50px;
background: linear-gradient(to right, #3498db, #2ecc71);
color: white;
cursor: pointer;
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
font-weight: bold;
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}
button:active {
transform: translateY(1px);
}
#startBtn {
background: linear-gradient(to right, #2ecc71, #3498db);
}
#resetBtn {
background: linear-gradient(to right, #e74c3c, #f39c12);
}
.instructions {
width: 800px;
background: rgba(0, 0, 0, 0.4);
padding: 20px;
border-radius: 15px;
margin-top: 25px;
font-size: 1.1rem;
line-height: 1.6;
}
.instructions h3 {
color: #ffd700;
margin-bottom: 15px;
text-align: center;
font-size: 1.4rem;
}
.instructions ul {
padding-left: 25px;
}
.instructions li {
margin-bottom: 10px;
}
.word {
position: absolute;
font-size: 28px;
font-weight: bold;
color: white;
text-shadow: 0 0 10px rgba(0, 200, 255, 0.8);
transition: transform 0.2s ease;
cursor: pointer;
padding: 8px 15px;
border-radius: 10px;
background: rgba(0, 50, 150, 0.6);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
@keyframes rotate {
0% { transform: rotateY(0deg) rotateX(0deg); }
100% { transform: rotateY(360deg) rotateX(15deg); }
}
.fade-out {
animation: fadeOut 0.5s forwards;
}
@keyframes fadeOut {
from { opacity: 1; transform: scale(1); }
to { opacity: 0; transform: scale(0.5); }
}
.hitEffect {
position: absolute;
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(255, 215, 0, 0.8) 0%, transparent 70%);
border-radius: 50%;
animation: expand 0.8s forwards;
pointer-events: none;
}
@keyframes expand {
0% { transform: scale(0.1); opacity: 1; }
100% { transform: scale(3); opacity: 0; }
}
.level-indicator {
position: absolute;
top: 20px;
right: 20px;
padding: 8px 15px;
background: rgba(0, 0, 0, 0.6);
border-radius: 20px;
font-size: 1.2rem;
color: #ffd700;
z-index: 10;
border: 2px solid #3498db;
}
.notification {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 15px 30px;
border-radius: 10px;
font-size: 1.3rem;
z-index: 1000;
opacity: 0;
transition: opacity 0.3s;
}
.notification.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="header">
<h1>英语单词打字游戏</h1>
<p class="subtitle">输入底部文本框中显示的单词来"接住"下落的单词 - 提高你的打字速度和词汇量!</p>
</div>
<div class="stats">
<div class="stat-item">
<div>得分</div>
<div id="score" class="stat-value">0</div>
</div>
<div class="stat-item">
<div>正确单词</div>
<div id="correctCount" class="stat-value">0</div>
</div>
<div class="stat-item">
<div>速度等级</div>
<div id="speedLevel" class="stat-value">1</div>
</div>
<div class="stat-item">
<div>剩余时间</div>
<div id="timer" class="stat-value">60</div>
</div>
</div>
<div class="game-container">
<canvas id="gameCanvas"></canvas>
<canvas id="effectsCanvas"></canvas>
<div class="level-indicator">等级: <span id="levelDisplay">1</span></div>
</div>
<div class="input-container">
<label for="wordInput">输入下方显示的单词:</label>
<input type="text" id="wordInput" placeholder="在这里输入单词..." autocomplete="off">
</div>
<div class="controls">
<button id="startBtn">开始游戏</button>
<button id="resetBtn">重新开始</button>
</div>
<div class="instructions">
<h3>游戏说明</h3>
<ul>
<li>单词会从屏幕顶部随机位置掉落并有旋转效果</li>
<li>在底部输入框中输入当前显示的单词来"接住"它</li>
<li>每次正确输入单词可以获得<span style="color:#ffd700;">10分</span></li>
<li>单词到达底部或输入错误会<span style="color:#ff6b6b;">减少生命值</span></li>
<li>每隔5秒会生成一个新单词</li>
<li>单词掉落速度会随时间增加(每30秒升一级)</li>
<li>游戏时间60秒,尽可能获得高分!</li>
</ul>
</div>
<div class="notification" id="notification"></div>
<script>
// 游戏配置
const config = {
wordList: [
"apple", "banana", "computer", "keyboard", "programming",
"javascript", "html", "css", "developer", "algorithm",
"variable", "function", "object", "array", "string",
"integer", "boolean", "loop", "condition", "syntax",
"framework", "library", "database", "network", "animation"
],
initialSpeed: 2,
speedIncreaseRate: 0.25,
spawnInterval: 5000, // 5秒
gameDuration: 60000, // 60秒
maxWords: 8, // 最大同时显示的单词数
basePoints: 10,
lives: 5
};
// 游戏状态
const gameState = {
active: false,
score: 0,
correctCount: 0,
speed: config.initialSpeed,
speedLevel: 1,
timeLeft: config.gameDuration / 1000,
lives: config.lives,
words: [],
fallingObjects: [],
currentTargetWord: "",
effects: [],
lastSpawnTime: 0,
startTime: 0
};
// DOM元素
const elements = {
gameCanvas: document.getElementById('gameCanvas'),
effectsCanvas: document.getElementById('effectsCanvas'),
wordInput: document.getElementById('wordInput'),
scoreDisplay: document.getElementById('score'),
correctCountDisplay: document.getElementById('correctCount'),
speedLevelDisplay: document.getElementById('speedLevel'),
timerDisplay: document.getElementById('timer'),
levelDisplay: document.getElementById('levelDisplay'),
startBtn: document.getElementById('startBtn'),
resetBtn: document.getElementById('resetBtn'),
notification: document.getElementById('notification')
};
// 获取Canvas上下文
const gameCtx = elements.gameCanvas.getContext('2d');
const effectsCtx = elements.effectsCanvas.getContext('2d');
// 初始化Canvas大小
function initCanvas() {
const container = document.querySelector('.game-container');
elements.gameCanvas.width = container.clientWidth;
elements.gameCanvas.height = container.clientHeight;
elements.effectsCanvas.width = container.clientWidth;
elements.effectsCanvas.height = container.clientHeight;
}
// 随机选择单词
function getRandomWord() {
return config.wordList[Math.floor(Math.random() * config.wordList.length)];
}
// 生成新单词
function spawnWord() {
if (!gameState.active || gameState.fallingObjects.length >= config.maxWords) return;
const word = getRandomWord();
const x = Math.random() * (elements.gameCanvas.width - 150);
gameState.fallingObjects.push({
word: word,
x: x,
y: -50,
speed: gameState.speed,
width: 100,
height: 50,
rotation: Math.random() * Math.PI * 2,
rotationSpeed: (Math.random() - 0.5) * 0.1,
opacity: 1
});
gameState.lastSpawnTime = Date.now();
}
// 设置目标单词显示
function setTargetWord() {
if (gameState.fallingObjects.length > 0) {
const randomObj = gameState.fallingObjects[
Math.floor(Math.random() * gameState.fallingObjects.length)
];
gameState.currentTargetWord = randomObj.word;
elements.wordInput.placeholder = `输入: ${randomObj.word}`;
}
}
// 更新游戏状态
function update() {
if (!gameState.active) return;
const currentTime = Date.now();
const elapsed = currentTime - gameState.startTime;
// 更新时间
gameState.timeLeft = Math.max(0, Math.floor((config.gameDuration - elapsed) / 1000));
elements.timerDisplay.textContent = gameState.timeLeft;
// 更新速度等级
const newSpeedLevel = Math.floor(elapsed / 30000) + 1;
if (newSpeedLevel > gameState.speedLevel) {
gameState.speedLevel = newSpeedLevel;
gameState.speed = config.initialSpeed + (gameState.speedLevel - 1) * config.speedIncreaseRate;
elements.speedLevelDisplay.textContent = gameState.speedLevel;
elements.levelDisplay.textContent = gameState.speedLevel;
showNotification(`速度提升到等级 ${gameState.speedLevel}!`);
}
// 生成新单词
if (currentTime - gameState.lastSpawnTime > config.spawnInterval) {
spawnWord();
}
// 更新所有下落单词
for (let i = gameState.fallingObjects.length - 1; i >= 0; i--) {
const obj = gameState.fallingObjects[i];
// 更新位置
obj.y += obj.speed;
obj.rotation += obj.rotationSpeed;
// 检查是否到达底部
if (obj.y > elements.gameCanvas.height) {
gameState.fallingObjects.splice(i, 1);
gameState.lives--;
showNotification(`错过 ${obj.word}! 生命值减少`);
if (gameState.lives <= 0) {
endGame();
}
continue;
}
}
// 重新设置目标单词
if (!gameState.currentTargetWord && gameState.fallingObjects.length > 0) {
setTargetWord();
}
// 检查游戏结束
if (elapsed >= config.gameDuration || gameState.lives <= 0) {
endGame();
}
}
// 渲染游戏
function render() {
// 清除画布
gameCtx.clearRect(0, 0, elements.gameCanvas.width, elements.gameCanvas.height);
effectsCtx.clearRect(0, 0, elements.effectsCanvas.width, elements.effectsCanvas.height);
// 绘制背景
gameCtx.fillStyle = 'rgba(10, 20, 50, 0.6)';
gameCtx.fillRect(0, 0, elements.game