

特点:
蛇有表情变化 - 开心、舔嘴唇、惊讶、死亡时的表情
各种搞笑食物 - 汉堡、披萨、奶茶、辣条等
夸张的视觉效果 - 吃到食物时屏幕震动、爆炸效果
逗逼的死亡动画 - 蛇会翻白眼、弹出搞笑文字
积分系统 - 吃不同食物得分不同
速度加快 - 越来越快增加挑战
搞笑的音效提示(用 emoji 和动画模拟)
排行榜[mw
<!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>
@import url('https://fonts.googleapis.cn/css2?family=Noto+Sans+SC:wght@400;700;900&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Noto Sans SC', sans-serif;
min-height: 100vh;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
}
/* 背景装饰 */
.bg-decoration {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 0;
}
.star {
position: absolute;
background: white;
border-radius: 50%;
animation: twinkle 2s infinite;
}
@keyframes twinkle {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
/* 标题 */
.title {
font-size: 3rem;
font-weight: 900;
background: linear-gradient(45deg, #ff6b6b, #feca57, #48dbfb, #ff9ff3);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: 0 0 30px rgba(255, 107, 107, 0.5);
margin-bottom: 10px;
animation: bounce 1s ease infinite;
z-index: 10;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.subtitle {
color: #feca57;
font-size: 1.2rem;
margin-bottom: 20px;
z-index: 10;
}
/* 游戏容器 */
.game-wrapper {
position: relative;
z-index: 10;
}
.game-info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 750px;
margin-bottom: 15px;
padding: 0 10px;
}
.score-display {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 10px 25px;
border-radius: 50px;
color: white;
font-weight: 700;
font-size: 1.3rem;
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
display: flex;
align-items: center;
gap: 10px;
}
.score-display span {
font-size: 1.5rem;
}
.high-score {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
padding: 10px 20px;
border-radius: 50px;
color: white;
font-weight: 700;
font-size: 1rem;
box-shadow: 0 5px 20px rgba(245, 87, 108, 0.4);
}
.game-container {
position: relative;
background: linear-gradient(145deg, #1e3a5f 0%, #0d1b2a 100%);
border-radius: 20px;
padding: 15px;
box-shadow:
0 0 0 4px rgba(255, 255, 255, 0.1),
0 20px 60px rgba(0, 0, 0, 0.5),
inset 0 0 60px rgba(72, 219, 251, 0.1);
}
#gameCanvas {
display: block;
border-radius: 12px;
background: linear-gradient(180deg, #0a1628 0%, #1a2f4a 100%);
}
/* 屏幕震动效果 */
.shake {
animation: shake 0.3s ease-in-out;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10px) rotate(-1deg); }
75% { transform: translateX(10px) rotate(1deg); }
}
/* 开始/结束界面 */
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 100;
backdrop-filter: blur(10px);
}
.overlay.hidden {
display: none;
}
.overlay-title {
font-size: 2.5rem;
font-weight: 900;
margin-bottom: 20px;
text-align: center;
}
.start-title {
background: linear-gradient(45deg, #ff6b6b, #feca57);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.gameover-title {
background: linear-gradient(45deg, #ff4757, #ff6b81);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
animation: pulse 0.5s ease infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.final-score {
font-size: 1.5rem;
color: #feca57;
margin-bottom: 10px;
}
.death-message {
font-size: 1.2rem;
color: #ff6b6b;
margin-bottom: 20px;
font-weight: 700;
}
.start-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
padding: 15px 50px;
font-size: 1.3rem;
font-weight: 700;
color: white;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
font-family: inherit;
}
.start-btn:hover {
transform: translateY(-5px) scale(1.05);
box-shadow: 0 15px 40px rgba(102, 126, 234, 0.6);
}
.start-btn:active {
transform: translateY(0) scale(0.98);
}
.instructions {
color: #a0a0a0;
font-size: 0.9rem;
margin-top: 20px;
text-align: center;
line-height: 1.6;
}
.instructions kbd {
background: #333;
padding: 3px 8px;
border-radius: 5px;
font-family: inherit;
}
/* 表情气泡 */
.emoji-bubble {
position: fixed;
font-size: 3rem;
pointer-events: none;
animation: floatUp 1s ease-out forwards;
z-index: 1000;
}
@keyframes floatUp {
0% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; transform: translateY(-100px) scale(1.5); }
}
/* 控制提示 */
.controls-hint {
display: flex;
gap: 15px;
margin-top: 15px;
flex-wrap: wrap;
justify-content: center;
z-index: 10;
}
.control-key {
background: rgba(255, 255, 255, 0.1);
padding: 8px 15px;
border-radius: 10px;
color: #888;
font-size: 0.85rem;
display: flex;
align-items: center;
gap: 8px;
}
.control-key kbd {
background: #333;
padding: 5px 10px;
border-radius: 5px;
color: white;
font-family: inherit;
}
/* 速度指示器 */
.speed-indicator {
position: absolute;
top: -30px;
right: 0;
background: linear-gradient(135deg, #ff6b6b, #ee5a24);
padding: 5px 15px;
border-radius: 20px;
color: white;
font-size: 0.8rem;
font-weight: 700;
opacity: 0;
transition: opacity 0.3s;
}
.speed-indicator.visible {
opacity: 1;
}
/* 连击提示 */
.combo-popup {
position: absolute;
font-size: 2rem;
font-weight: 900;
color: #feca57;
text-shadow: 0 0 20px rgba(254, 202, 87, 0.8);
pointer-events: none;
animation: comboAnim 0.8s ease-out forwards;
z-index: 50;
}
@keyframes comboAnim {
0% { opacity: 1; transform: scale(0.5); }
50% { transform: scale(1.2); }
100% { opacity: 0; transform: scale(1) translateY(-50px); }
}
/* 响应式 */
@media (max-width: 650px) {
.title { font-size: 2rem; }
.subtitle { font-size: 1rem; }
.score-display { padding: 8px 15px; font-size: 1rem; }
.high-score { padding: 8px 12px; font-size: 0.85rem; }
.game-container { padding: 10px; }
.controls-hint { display: none; }
}
</style>
</head>
<body>
<!-- 背景装饰 -->
<div class="bg-decoration" id="bgDecoration"></div>
<h1 class="title">🐍 逗逼贪吃蛇 🐍</h1>
<p class="subtitle" id="subtitle">笑死人不偿命版</p>
<div class="game-wrapper">
<div class="game-info">
<div class="score-display">
🎯 得分: <span id="score">0</span>
</div>
<div class="high-score">
👑 最高: <span id="highScore">0</span>
</div>
</div>
<div class="game-container" id="gameContainer">
<div class="speed-indicator" id="speedIndicator">🚀 加速中!</div>
<canvas id="gameCanvas" width="600" height="450"></canvas>
<!-- 开始界面 -->
<div class="overlay" id="startOverlay">
<div class="overlay-title start-title">🐍 贪吃蛇来啦!</div>
<button class="start-btn" id="startBtn">开始游戏</button>
<div class="instructions">
<p>用 <kbd>↑</kbd> <kbd>↓</kbd> <kbd>←</kbd> <kbd>→</kbd> 或 <kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> 控制方向</p>
<p style="margin-top: 8px;">吃遍天下美食,成为蛇中之王!</p>
</div>
</div>
<!-- 结束界面 -->
<div class="overlay hidden" id="gameoverOverlay">
<div class="overlay-title gameover-title">💀 被撑死了!</div>
<div class="final-score" id="finalScore">本局得分: 0</div>
<div class="death-message" id="deathMessage">死因: 撞墙了</div>
<button class="start-btn" id="restartBtn">再战一局</button>
</div>
</div>
<div class="controls-hint">
<div class="control-key"><kbd>↑↓←→</kbd> 或 <kbd>WASD</kbd> 移动</div>
<div class="control-key"><kbd>Space</kbd> 暂停</div>
<div class="control-key"><kbd>R</kbd> 重新开始</div>
</div>
</div>
<script>
// 游戏配置
const CELL_SIZE = 18;
const GRID_WIDTH = 40;
const GRID_HEIGHT = 28;
const INITIAL_SPEED = 150;
const SPEED_INCREMENT = 3;
const MIN_SPEED = 50;
// 食物类型和表情
const FOOD_TYPES = [
{ emoji: '🍎', name: '苹果', points: 10, color: '#ff6b6b' },
{ emoji: '🍕', name: '披萨', points: 15, color: '#feca57' },
{ emoji: '🍔', name: '汉堡', points: 20, color: '#ff9f43' },
{ emoji: '🍦', name: '冰淇淋', points: 15, color: '#ee5a24' },
{ emoji: '🍩', name: '甜甜圈', points: 15, color: '#f368e0' },
{ emoji: '🍖', name: '猪排', points: 25, color: '#ff9ff3' },
{ emoji: '🍜', name: '拉面', points: 20, color: '#ffeaa7' },
{ emoji: '🍱', name: '便当', points: 30, color: '#d63031' },
{ emoji: '🦐', name: '大虾', points: 35, color: '#ff7675' },
{ emoji: '🍰', name: '蛋糕', points: 25, color: '#fab1a0' },
{ emoji: '🥩', name: '牛排', points: 40, color: '#a29bfe' },
{ emoji: '🍟', name: '薯条', points: 12, color: '#fdcb6e' },
{ emoji: '☕', name: '咖啡', points: 10, color: '#6c5ce7' },
{ emoji: '🍺', name: '啤酒', points: 15, color: '#ffeaa7' },
{ emoji: '🍖', name: '烤串', points: 20, color: '#d63031' }
];
// 蛇的表情
const SNAKE_FACES = {
happy: ['(^_^)', '(◠‿◠)', '(。◕‿◕。)', '(●ᴗ●)'],
eating: ['(亝ω亝)', '(♥‿♥)', '(●´ω`●)', '(✧ω✧)'],
scared: ['(°ロ°)', '(⊙_⊙)', '(°o°)', '(⊙﹏⊙)'],
dead: ['×_×', '(T_T)', '(╥﹏╥)', '×_×'],
cool: ['(¬‿¬)', '(͠◉͟ʖ͡◉)', '(ಠ_ಠ)', '( •_•)']
};
// 死亡原因
const DEATH_MESSAGES = [
'死因: 撞墙了(墙壁有意见)',
'死因: 咬到自己了(自恋过度)',
'死因: 吃太饱了撑死',
'死因: 撞到尾巴(追尾全责)',
'死因: 刹车失灵',
'死因: 方向感迷失',
'死因: 吃到炸弹💣',
'死因: 蛇生艰难'
];
// 游戏状态
let canvas, ctx;
let snake = [];
let food = null;
let direction = { x: 1, y: 0 };
let nextDirection = { x: 1, y: 0 };
let score = 0;
let highScore = localStorage.getItem('snakeHighScore') || 0;
let gameLoop = null;
let gameSpeed = INITIAL_SPEED;
let isGameRunning = false;
let isPaused = false;
let combo = 0;
let lastEmoji = '';
let currentFace = 'happy';
// DOM元素
const scoreEl = document.getElementById('score');
const highScoreEl = document.getElementById('highScore');
const startOverlay = document.getElementById('startOverlay');
const gameoverOverlay = document.getElementById('gameoverOverlay');
const finalScoreEl = document.getElementById('finalScore');
const deathMessageEl = document.getElementById('deathMessage');
const gameContainer = document.getElementById('gameContainer');
const speedIndicator = document.getElementById('speedIndicator');
const subtitleEl = document.getElementById('subtitle');
// 初始化
function init() {
canvas = document.getElementById('gameCanvas');
ctx = canvas.getContext('2d');
canvas.width = GRID_WIDTH * CELL_SIZE;
canvas.height = GRID_HEIGHT * CELL_SIZE;
highScoreEl.textContent = highScore;
// 创建背景星星
createStars();
// 事件监听
document.getElementById('startBtn').addEventListener('click', startGame);
document.getElementById('restartBtn').addEventListener('click', startGame);
document.addEventListener('keydown', handleKeydown);
// 触摸控制
setupTouchControls();
// 随机字幕
randomSubtitle();
setInterval(randomSubtitle, 5000);
}
// 创建背景星星
function createStars() {
const bg = document.getElementById('bgDecoration');
for (let i = 0; i < 50; i++) {
const star = document.createElement('div');
star.className = 'star';
star.style.left = Math.random() * 100 + '%';
star.style.top = Math.random() * 100 + '%';
star.style.width = star.style.height = Math.random() * 3 + 1 + 'px';
star.style.animationDelay = Math.random() * 2 + 's';
bg.appendChild(star);
}
}
// 随机字幕
const subtitles = [
'笑死人不偿命版',
'一口一个小朋友',
'蛇蛇过山车',
'吃到停不下来',
'越吃越饿版',
'疯狂干饭蛇',
'今天吃什么好呢',
'专业干饭二十年',
'嘎嘎香',
'馋哭隔壁小孩'
];
function randomSubtitle() {
subtitleEl.textContent = subtitles[Math.floor(Math.random() * subtitles.length)];
}
// 开始游戏
function startGame() {
// 重置状态
snake = [
{ x: 5, y: 10 },
{ x: 4, y: 10 },
{ x: 3, y: 10 }
];
direction = { x: 1, y: 0 };
nextDirection = { x: 1, y: 0 };
score = 0;
gameSpeed = INITIAL_SPEED;
combo = 0;
isGameRunning = true;
isPaused = false;
currentFace = 'happy';
scoreEl.textContent = score;
startOverlay.classList.add('hidden');
gameoverOverlay.classList.add('hidden');
spawnFood();
updateSpeedIndicator();
if (gameLoop) clearInterval(gameLoop);
gameLoop = setInterval(update, gameSpeed);
}
// 生成食物
function spawnFood() {
let valid = false;
while (!valid) {
food = {
x: Math.floor(Math.random() * GRID_WIDTH),
y: Math.floor(Math.random() * GRID_HEIGHT),
...FOOD_TYPES[Math.floor(Math.random() * FOOD_TYPES.length)]
};
// 确保食物不在蛇身上
valid = !snake.some(seg => seg.x === food.x && seg.y === food.y);
}
}
// 游戏更新
function update() {
if (!isGameRunning || isPaused) return;
// 更新方向
direction = { ...nextDirection };
// 计算新头部
const head = {
x: snake[0].x + direction.x,
y: snake[0].y + direction.y
};
// 检查撞墙
if (head.x < 0 || head.x >= GRID_WIDTH || head.y < 0 || head.y >= GRID_HEIGHT) {
gameOver('撞墙了(墙壁有意见)');
return;
}
// 检查撞自己
if (snake.some(seg => seg.x === head.x && seg.y === head.y)) {
gameOver('咬到自己了(自恋过度)');
return;
}
// 添加新头部
snake.unshift(head);
// 检查吃食物
if (head.x === food.x && head.y === food.y) {
eatFood();
} else {
snake.pop();
}
render();
}
// 吃食物
function eatFood() {
const points = food.points;
score += points;
combo++;
// 更新分数
scoreEl.textContent = score;
// 更新最高分
if (score > highScore) {
highScore = score;
localStorage.setItem('snakeHighScore', highScore);
highScoreEl.textContent = highScore;
}
// 表情变化
currentFace = 'eating';
showEmojiBubble(food.emoji);
// 连击提示
if (combo > 2) {
showComboPopup(`🔥 x${combo}连击!`);
gameSpeed = Math.max(MIN_SPEED, gameSpeed - SPEED_INCREMENT);
clearInterval(gameLoop);
gameLoop = setInterval(update, gameSpeed);
updateSpeedIndicator();
}
// 屏幕震动
gameContainer.classList.add('shake');
setTimeout(() => gameContainer.classList.remove('shake'), 300);
setTimeout(() => { currentFace = 'happy'; }, 500);
// 加速
if (combo % 5 === 0 && combo > 0) {
gameSpeed = Math.max(MIN_SPEED, gameSpeed - SPEED_INCREMENT);
clearInterval(gameLoop);
gameLoop = setInterval(update, gameSpeed);
updateSpeedIndicator();
}
spawnFood();
}
// 显示表情气泡
function showEmojiBubble(emoji) {
const bubble = document.createElement('div');
bubble.className = 'emoji-bubble';
bubble.textContent = emoji;
const rect = gameContainer.getBoundingClientRect();
bubble.style.left = rect.left + rect.width / 2 - 20 + 'px';
bubble.style.top = rect.top + rect.height / 2 + 'px';
document.body.appendChild(bubble);
setTimeout(() => bubble.remove(), 1000);
}
// 显示连击提示
function showComboPopup(text) {
const popup = document.createElement('div');
popup.className = 'combo-popup';
popup.textContent = text;
popup.style.left = '50%';
popup.style.top = '50%';
popup.style.transform = 'translate(-50%, -50%)';
gameContainer.appendChild(popup);
setTimeout(() => popup.remove(), 800);
}
// 更新速度指示器
function updateSpeedIndicator() {
if (gameSpeed < INITIAL_SPEED) {
speedIndicator.classList.add('visible');
const speedLevel = Math.floor((INITIAL_SPEED - gameSpeed) / SPEED_INCREMENT);
speedIndicator.textContent = `🚀 速度+${speedLevel}`;
} else {
speedIndicator.classList.remove('visible');
}
}
// 游戏结束
function gameOver(reason) {
isGameRunning = false;
clearInterval(gameLoop);
currentFace = 'dead';
render();
// 显示死亡界面
setTimeout(() => {
finalScoreEl.textContent = `本局得分: ${score}`;
deathMessageEl.textContent = '死因: ' + reason;
// 搞笑评语
let comment = '';
if (score < 50) {
comment = '新手村还没出呢~';
} else if (score < 150) {
comment = '还行,继续加油!';
} else if (score < 300) {
comment = '有点东西啊!';
} else if (score < 500) {
comment = '干饭王!';
} else {
comment = '🦄 蛇中之神! 🦄';
}
deathMessageEl.textContent += ` ${comment}`;
gameoverOverlay.classList.remove('hidden');
}, 500);
}
// 渲染
function render() {
// 清空画布
ctx.fillStyle = '#0a1628';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制网格
ctx.strokeStyle = 'rgba(72, 219, 251, 0.1)';
ctx.lineWidth = 0.5;
for (let x = 0; x <= GRID_WIDTH; x++) {
ctx.beginPath();
ctx.moveTo(x * CELL_SIZE, 0);
ctx.lineTo(x * CELL_SIZE, canvas.height);
ctx.stroke();
}
for (let y = 0; y <= GRID_HEIGHT; y++) {
ctx.beginPath();
ctx.moveTo(0, y * CELL_SIZE);
ctx.lineTo(canvas.width, y * CELL_SIZE);
ctx.stroke();
}
// 绘制食物
if (food) {
ctx.font = '18px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const fx = food.x * CELL_SIZE + CELL_SIZE / 2;
const fy = food.y * CELL_SIZE + CELL_SIZE / 2;
// 食物光晕
const gradient = ctx.createRadialGradient(fx, fy, 5, fx, fy, 20);
gradient.addColorStop(0, food.color + '60');
gradient.addColorStop(1, 'transparent');
ctx.fillStyle = gradient;
ctx.fillRect(food.x * CELL_SIZE - 5, food.y * CELL_SIZE - 5, CELL_SIZE + 10, CELL_SIZE + 10);
// 食物emoji
ctx.fillText(food.emoji, fx, fy);
}
// 绘制蛇
snake.forEach((segment, index) => {
const sx = segment.x * CELL_SIZE;
const sy = segment.y * CELL_SIZE;
const isHead = index === 0;
// 蛇身渐变色
const hue = 120 + (index * 2);
const lightness = 60 - (index * 1.5);
if (isHead) {
// 蛇头
ctx.fillStyle = '#2ecc71';
ctx.shadowColor = '#2ecc71';
ctx.shadowBlur = 15;
} else {
ctx.fillStyle = `hsl(${hue}, 70%, ${lightness}%)`;
ctx.shadowBlur = 0;
}
// 圆角矩形
const radius = isHead ? 8 : 6;
roundRect(ctx, sx + 2, sy + 2, CELL_SIZE - 4, CELL_SIZE - 4, radius);
// 蛇头眼睛和表情
if (isHead) {
ctx.shadowBlur = 0;
const faces = SNAKE_FACES[currentFace] || SNAKE_FACES.happy;
const face = faces[Math.floor(Math.random() * faces.length)];
ctx.fillStyle = 'white';
ctx.font = 'bold 10px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// 眼睛
const eyeOffsetX = direction.x !== 0 ? direction.x * 2 : 0;
const eyeOffsetY = direction.y !== 0 ? direction.y * 2 : 0;
ctx.fillText('●', sx + CELL_SIZE/2 - 4 - eyeOffsetX, sy + CELL_SIZE/2 - 2 - eyeOffsetY);
ctx.fillText('●', sx + CELL_SIZE/2 + 4 - eyeOffsetX, sy + CELL_SIZE/2 - 2 - eyeOffsetY);
// 表情
ctx.font = '8px Arial';
ctx.fillText(face, sx + CELL_SIZE/2, sy + CELL_SIZE/2 + 5);
}
});
}
// 圆角矩形
function roundRect(ctx, x, y, width, height, radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
}
// 按键处理
function handleKeydown(e) {
// 方向控制
switch(e.key) {
case 'ArrowUp':
case 'w':
case 'W':
if (direction.y !== 1) nextDirection = { x: 0, y: -1 };
break;
case 'ArrowDown':
case 's':
case 'S':
if (direction.y !== -1) nextDirection = { x: 0, y: 1 };
break;
case 'ArrowLeft':
case 'a':
case 'A':
if (direction.x !== 1) nextDirection = { x: -1, y: 0 };
break;
case 'ArrowRight':
case 'd':
case 'D':
if (direction.x !== -1) nextDirection = { x: 1, y: 0 };
break;
case ' ':
if (isGameRunning) {
isPaused = !isPaused;
if (!isPaused) {
clearInterval(gameLoop);
gameLoop = setInterval(update, gameSpeed);
}
}
e.preventDefault();
break;
case 'r':
case 'R':
startGame();
break;
}
}
// 触摸控制
function setupTouchControls() {
let touchStartX = 0;
let touchStartY = 0;
canvas.addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
e.preventDefault();
}, { passive: false });
canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
canvas.addEventListener('touchend', (e) => {
if (!isGameRunning) return;
const touchEndX = e.changedTouches[0].clientX;
const touchEndY = e.changedTouches[0].clientY;
const dx = touchEndX - touchStartX;
const dy = touchEndY - touchStartY;
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 30 && direction.x !== -1) nextDirection = { x: 1, y: 0 };
else if (dx < -30 && direction.x !== 1) nextDirection = { x: -1, y: 0 };
} else {
if (dy > 30 && direction.y !== -1) nextDirection = { x: 0, y: 1 };
else if (dy < -30 && direction.y !== 1) nextDirection = { x: 0, y: -1 };
}
});
}
// 初始化游戏
init();
</script>
</body>
</html>

