- BC20270270's blog
贪吃蛇大便2
- 2025-6-14 11:58:01 @
增强游戏功能:
多种特殊食物系统:
蓝色食物:缩短蛇身
黄色食物:加速效果
粉色食物:无敌效果
障碍物系统:
紫色方块作为障碍物
每升一级增加障碍物数量
无敌状态下可穿过障碍物
关卡系统:
每获得100分升一级
关卡显示在右上角
游戏结束显示最终关卡
分数倍数机制:
连续吃到3个食物激活x2倍数
每多连续吃3个食物倍数+1(最高x5)
倍数有5秒计时器
蛇身皮肤系统:
经典皮肤(默认)
火焰皮肤(红橙色)
寒冰皮肤(蓝青色)
视觉效果增强:
粒子背景效果
按钮悬停动画
状态指示器动画
无敌状态闪烁效果
特殊食物闪烁效果
UI改进:
更清晰的游戏说明
能量状态计时器
分数倍数显示
更美观的状态指示器
<!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: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
display: flex;
justify-content: center;
align-items: flex-start; /* 改为顶部对齐 */
min-height: 100vh;
background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
color: #fff;
padding: 20px;
overflow-x: hidden; /* 只隐藏水平滚动 */
}
.game-container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
max-width: 1000px;
width: 100%;
}
.header {
text-align: center;
margin-bottom: 20px;
width: 100%;
position: relative;
}
h1 {
font-size: 3.5rem;
margin-bottom: 10px;
color: #e94560;
text-shadow: 0 0 10px rgba(233, 69, 96, 0.7);
letter-spacing: 3px;
}
.header::after {
content: "";
display: block;
width: 100%;
height: 4px;
background: linear-gradient(90deg, transparent, #e94560, #4dccbd, #e94560, transparent);
margin-top: 10px;
border-radius: 2px;
}
.stats-container {
display: flex;
justify-content: space-between;
width: 100%;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 15px 25px;
margin-bottom: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
}
.stats-container::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: linear-gradient(90deg, #e94560, #4dccbd, #e94560);
}
.stat-box {
text-align: center;
position: relative;
z-index: 1;
}
.stat-title {
font-size: 1.1rem;
color: #a9a9a9;
margin-bottom: 5px;
}
.stat-value {
font-size: 2.2rem;
font-weight: bold;
color: #4dccbd;
text-shadow: 0 0 8px rgba(77, 204, 189, 0.6);
}
.multiplier {
font-size: 1.2rem;
color: #ffd166;
margin-left: 5px;
display: inline-block;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.game-board {
position: relative;
width: 600px;
height: 450px;
margin: 20px auto;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
border: 3px solid rgba(255, 255, 255, 0.1);
}
canvas {
background: rgba(13, 19, 33, 0.9);
display: block;
}
.controls {
display: flex;
gap: 15px;
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
}
button {
padding: 12px 25px;
font-size: 1.1rem;
font-weight: 600;
border: none;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
background: linear-gradient(to right, #e94560, #ff6b81);
color: white;
box-shadow: 0 5px 15px rgba(233, 69, 96, 0.4);
position: relative;
overflow: hidden;
}
button::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: 0.5s;
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(233, 69, 96, 0.6);
}
button:hover::before {
left: 100%;
}
button:active {
transform: translateY(1px);
}
.difficulty {
display: flex;
gap: 10px;
margin-top: 15px;
flex-wrap: wrap;
justify-content: center;
}
.difficulty-btn {
padding: 8px 20px;
font-size: 0.9rem;
background: rgba(255, 255, 255, 0.1);
}
.difficulty-btn.active {
background: linear-gradient(to right, #4dccbd, #3aafa9);
box-shadow: 0 5px 15px rgba(77, 204, 189, 0.4);
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
border-radius: 15px;
text-align: center;
padding: 20px;
}
.overlay h2 {
font-size: 3rem;
margin-bottom: 20px;
color: #e94560;
text-shadow: 0 0 15px rgba(233, 69, 96, 0.8);
}
.overlay p {
font-size: 1.5rem;
margin-bottom: 30px;
text-align: center;
max-width: 80%;
line-height: 1.6;
}
.instructions {
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
padding: 20px;
margin-top: 20px;
width: 100%;
max-width: 600px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.instructions h3 {
color: #4dccbd;
margin-bottom: 15px;
text-align: center;
font-size: 1.8rem;
}
.instructions ul {
padding-left: 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px;
}
.instructions li {
margin-bottom: 12px;
line-height: 1.5;
padding: 8px 12px;
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.key {
display: inline-block;
background: rgba(255, 255, 255, 0.15);
padding: 2px 8px;
border-radius: 5px;
font-family: monospace;
margin: 0 3px;
}
.mobile-controls {
display: none;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 10px;
margin-top: 20px;
width: 200px;
height: 200px;
}
.mobile-btn {
display: flex;
justify-content: center;
align-items: center;
background: rgba(255, 255, 255, 0.15);
border-radius: 10px;
font-size: 24px;
font-weight: bold;
user-select: none;
transition: all 0.2s;
}
.mobile-btn:active {
background: rgba(255, 255, 255, 0.3);
transform: scale(0.95);
}
.up { grid-column: 2; grid-row: 1; }
.left { grid-column: 1; grid-row: 2; }
.right { grid-column: 3; grid-row: 2; }
.down { grid-column: 2; grid-row: 3; }
.power-ups {
display: flex;
justify-content: center;
gap: 15px;
margin: 15px 0;
flex-wrap: wrap;
}
.power-up {
display: flex;
flex-direction: column;
align-items: center;
background: rgba(255, 255, 255, 0.05);
padding: 10px;
border-radius: 10px;
min-width: 80px;
}
.power-up-icon {
width: 40px;
height: 40px;
border-radius: 50%;
margin-bottom: 5px;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
}
.power-up-timer {
font-size: 0.9rem;
color: #ffd166;
font-weight: bold;
}
.skin-selector {
display: flex;
gap: 10px;
margin: 15px 0;
flex-wrap: wrap;
justify-content: center;
}
.skin-btn {
padding: 8px 15px;
font-size: 0.9rem;
background: rgba(255, 255, 255, 0.1);
}
.skin-btn.active {
background: linear-gradient(to right, #e94560, #ff6b81);
box-shadow: 0 3px 10px rgba(233, 69, 96, 0.4);
}
.level-indicator {
position: absolute;
top: 15px;
right: 15px;
background: rgba(0, 0, 0, 0.5);
padding: 5px 15px;
border-radius: 20px;
font-size: 1.2rem;
font-weight: bold;
color: #ffd166;
z-index: 5;
}
.obstacle {
position: absolute;
background: #8a4fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(138, 79, 255, 0.7);
}
.scrollable-container {
max-height: 100vh;
overflow-y: auto;
width: 100%;
}
/* 新增的粒子效果 */
.particles {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
}
.particle {
position: absolute;
width: 4px;
height: 4px;
background: rgba(255, 255, 255, 0.5);
border-radius: 50%;
animation: float 15s infinite linear;
}
@keyframes float {
0% {
transform: translateY(0) translateX(0);
opacity: 0;
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
transform: translateY(-100vh) translateX(100px);
opacity: 0;
}
}
@media (max-width: 650px) {
body {
padding: 10px;
align-items: flex-start;
}
.game-board {
width: 95vw;
height: 70vw;
}
h1 {
font-size: 2.5rem;
}
.stat-value {
font-size: 1.8rem;
}
.overlay h2 {
font-size: 2.2rem;
}
.overlay p {
font-size: 1.2rem;
}
.mobile-controls {
display: grid;
}
.instructions ul {
grid-template-columns: 1fr;
}
.stats-container {
flex-direction: column;
gap: 10px;
}
.controls, .difficulty, .skin-selector {
flex-direction: column;
width: 100%;
}
button {
width: 100%;
}
}
</style>
</head>
<body>
<div class="particles" id="particles"></div>
<div class="scrollable-container">
<div class="game-container">
<div class="header">
<h1>贪吃蛇大冒险</h1>
<div class="level-indicator">关卡: <span id="level">1</span></div>
</div>
<div class="stats-container">
<div class="stat-box">
<div class="stat-title">当前分数</div>
<div class="stat-value" id="score">0</div>
</div>
<div class="stat-box">
<div class="stat-title">最高分数</div>
<div class="stat-value" id="high-score">0</div>
</div>
<div class="stat-box">
<div class="stat-title">游戏速度</div>
<div class="stat-value" id="speed">5<span class="multiplier">x1</span></div>
</div>
</div>
<div class="power-ups">
<div class="power-up">
<div class="power-up-icon" style="background: #4dccbd;">S</div>
<div class="stat-title">缩短</div>
<div class="power-up-timer" id="shorten-timer">0s</div>
</div>
<div class="power-up">
<div class="power-up-icon" style="background: #ffd166;">F</div>
<div class="stat-title">加速</div>
<div class="power-up-timer" id="speedup-timer">0s</div>
</div>
<div class="power-up">
<div class="power-up-icon" style="background: #ef476f;">I</div>
<div class="stat-title">无敌</div>
<div class="power-up-timer" id="invincible-timer">0s</div>
</div>
<div class="power-up">
<div class="power-up-icon" style="background: #118ab2;">X</div>
<div class="stat-title">分数倍数</div>
<div class="power-up-timer" id="multiplier">x1</div>
</div>
</div>
<div class="skin-selector">
<button class="skin-btn active" data-skin="default">经典皮肤</button>
<button class="skin-btn" data-skin="fire">火焰皮肤</button>
<button class="skin-btn" data-skin="ice">寒冰皮肤</button>
</div>
<div class="game-board">
<canvas id="game-canvas" width="600" height="450"></canvas>
<div class="overlay" id="start-screen">
<h2>贪吃蛇大冒险 - 增强版</h2>
<p>收集多种特殊食物,避开障碍物,挑战更高关卡!</p>
<button id="start-btn">开始游戏</button>
</div>
<div class="overlay" id="game-over" style="display: none;">
<h2>游戏结束!</h2>
<p>你的分数: <span id="final-score">0</span></p>
<p>最高关卡: <span id="final-level">1</span></p>
<button id="restart-btn">再来一次</button>
</div>
</div>
<div class="controls">
<button id="pause-btn">暂停</button>
<button id="reset-btn">重新开始</button>
</div>
<div class="difficulty">
<button class="difficulty-btn active" data-speed="120">简单</button>
<button class="difficulty-btn" data-speed="80">中等</button>
<button class="difficulty-btn" data-speed="50">困难</button>
<button class="difficulty-btn" data-speed="30">地狱</button>
</div>
<div class="mobile-controls">
<div class="mobile-btn up">↑</div>
<div class="mobile-btn left">←</div>
<div class="mobile-btn right">→</div>
<div class="mobile-btn down">↓</div>
</div>
<div class="instructions">
<h3>游戏说明</h3>
<ul>
<li>使用 <span class="key">方向键</span> 或 <span class="key">WASD</span> 控制贪吃蛇移动</li>
<li>吃到 <span style="color: #ff6b6b">红色食物</span> 得10分,蛇身变长</li>
<li>吃到 <span style="color: #4dccbd">蓝色食物</span> 缩短蛇身,<span style="color: #ffd166">黄色食物</span> 加速,<span style="color: #ef476f">粉色食物</span> 无敌</li>
<li>连续吃到食物激活 <span style="color: #118ab2">分数倍数</span> (最高x5)</li>
<li>紫色方块是障碍物,碰到会结束游戏</li>
<li>每得100分进入下一关,增加障碍物</li>
<li>无敌状态可穿过障碍物和自身</li>
</ul>
</div>
</div>
</div>
<script>
// 游戏主逻辑
document.addEventListener('DOMContentLoaded', () => {
// 创建背景粒子
function createParticles() {
const particlesContainer = document.getElementById('particles');
const particleCount = 50;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.classList.add('particle');
// 随机位置
const posX = Math.random() * 100;
const posY = Math.random() * 100 + 100;
particle.style.left = `${posX}%`;
particle.style.top = `${posY}%`;
// 随机大小和动画延迟
const size = Math.random() * 3 + 1;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
particle.style.animationDelay = `${Math.random() * 15}s`;
particlesContainer.appendChild(particle);
}
}
createParticles();
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const highScoreElement = document.getElementById('high-score');
const speedElement = document.getElementById('speed');
const startScreen = document.getElementById('start-screen');
const gameOverScreen = document.getElementById('game-over');
const startBtn = document.getElementById('start-btn');
const pauseBtn = document.getElementById('pause-btn');
const resetBtn = document.getElementById('reset-btn');
const restartBtn = document.getElementById('restart-btn');
const finalScoreElement = document.getElementById('final-score');
const finalLevelElement = document.getElementById('final-level');
const difficultyBtns = document.querySelectorAll('.difficulty-btn');
const mobileControls = document.querySelectorAll('.mobile-btn');
const skinBtns = document.querySelectorAll('.skin-btn');
const levelElement = document.getElementById('level');
// 能量计时器元素
const shortenTimer = document.getElementById('shorten-timer');
const speedupTimer = document.getElementById('speedup-timer');
const invincibleTimer = document.getElementById('invincible-timer');
const multiplierElement = document.getElementById('multiplier');
// 游戏变量
const gridSize = 20;
const gridWidth = canvas.width / gridSize;
const gridHeight = canvas.height / gridSize;
let snake = [];
let food = {};
let specialFood = {};
let obstacles = [];
let direction = 'right';
let nextDirection = 'right';
let score = 0;
let highScore = localStorage.getItem('snakeHighScore') || 0;
let baseSpeed = 120; // 毫秒
let actualSpeed = 120;
let gameInterval;
let gameRunning = false;
let gamePaused = false;
let specialFoodActive = false;
let specialFoodTimer = 0;
let level = 1;
let consecutiveFood = 0;
let scoreMultiplier = 1;
let multiplierTimer = 0;
// 能量状态
let isShortenActive = false;
let shortenTime = 0;
let isSpeedUpActive = false;
let speedupTime = 0;
let isInvincibleActive = false;
let invincibleTime = 0;
// 皮肤
let currentSkin = 'default';
// 初始化游戏
function initGame() {
// 初始化蛇
snake = [
{x: 5, y: 10},
{x: 4, y: 10},
{x: 3, y: 10}
];
// 生成食物
generateFood();
specialFoodActive = false;
specialFoodTimer = 0;
// 生成障碍物
generateObstacles();
// 重置分数和方向
score = 0;
level = 1;
consecutiveFood = 0;
scoreMultiplier = 1;
multiplierTimer = 0;
direction = 'right';
nextDirection = 'right';
updateScore();
// 重置能量状态
isShortenActive = false;
isSpeedUpActive = false;
isInvincibleActive = false;
shortenTime = 0;
speedupTime = 0;
invincibleTime = 0;
updatePowerUpTimers();
// 隐藏游戏结束界面
gameOverScreen.style.display = 'none';
// 设置最高分
highScoreElement.textContent = highScore;
// 设置关卡
levelElement.textContent = level;
// 绘制游戏
draw();
}
// 生成障碍物
function generateObstacles() {
obstacles = [];
const obstacleCount = 3 + level; // 每关增加障碍物
for (let i = 0; i < obstacleCount; i++) {
let newObstacle;
let validPosition = false;
while (!validPosition) {
newObstacle = {
x: Math.floor(Math.random() * gridWidth),
y: Math.floor(Math.random() * gridHeight)
};
validPosition = true;
// 检查是否与蛇身重叠
for (let segment of snake) {
if (segment.x === newObstacle.x && segment.y === newObstacle.y) {
validPosition = false;
break;
}
}
// 检查是否与食物重叠
if (validPosition && food.x === newObstacle.x && food.y === newObstacle.y) {
validPosition = false;
}
// 检查是否与其他障碍物重叠
for (let obstacle of obstacles) {
if (obstacle.x === newObstacle.x && obstacle.y === newObstacle.y) {
validPosition = false;
break;
}
}
}
obstacles.push(newObstacle);
}
}
// 生成食物
function generateFood() {
food = {
x: Math.floor(Math.random() * gridWidth),
y: Math.floor(Math.random() * gridHeight),
type: 'normal'
};
// 确保食物不出现在蛇身上或障碍物上
for (let segment of snake) {
if (segment.x === food.x && segment.y === food.y) {
return generateFood();
}
}
for (let obstacle of obstacles) {
if (obstacle.x === food.x && obstacle.y === food.y) {
return generateFood();
}
}
}
// 生成特殊食物
function generateSpecialFood() {
if (!specialFoodActive && Math.random() > 0.8) {
const foodTypes = ['shorten', 'speed', 'invincible'];
const selectedType = foodTypes[Math.floor(Math.random() * foodTypes.length)];
specialFood = {
x: Math.floor(Math.random() * gridWidth),
y: Math.floor(Math.random() * gridHeight),
type: selectedType
};
// 确保特殊食物不出现在蛇身上、普通食物上或障碍物上
for (let segment of snake) {
if (segment.x === specialFood.x && segment.y === specialFood.y) {
return generateSpecialFood();
}
}
if (specialFood.x === food.x && specialFood.y === food.y) {
return generateSpecialFood();
}
for (let obstacle of obstacles) {
if (obstacle.x === specialFood.x && obstacle.y === specialFood.y) {
return generateSpecialFood();
}
}
specialFoodActive = true;
specialFoodTimer = 300; // 特殊食物存在300帧
}
}
// 绘制游戏
function draw() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制网格背景
drawGrid();
// 绘制障碍物
drawObstacles();
// 绘制蛇
drawSnake();
// 绘制食物
drawFood();
// 绘制特殊食物
if (specialFoodActive) {
drawSpecialFood();
}
}
// 绘制网格
function drawGrid() {
ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
ctx.lineWidth = 0.5;
// 垂直线
for (let x = 0; x < canvas.width; x += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
// 水平线
for (let y = 0; y < canvas.height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
}
// 绘制障碍物
function drawObstacles() {
for (let obstacle of obstacles) {
ctx.fillStyle = '#8a4fff';
ctx.fillRect(obstacle.x * gridSize, obstacle.y * gridSize, gridSize, gridSize);
// 添加内部细节
ctx.fillStyle = '#6a30ff';
ctx.fillRect(
obstacle.x * gridSize + 3,
obstacle.y * gridSize + 3,
gridSize - 6,
gridSize - 6
);
// 添加高光
ctx.fillStyle = '#a87bff';
ctx.fillRect(
obstacle.x * gridSize + 6,
obstacle.y * gridSize + 6,
gridSize - 12,
gridSize - 12
);
}
}
// 绘制蛇
function drawSnake() {
// 绘制蛇身
for (let i = 0; i < snake.length; i++) {
const segment = snake[i];
// 蛇头
if (i === 0) {
if (currentSkin === 'fire') {
// 火焰皮肤
ctx.fillStyle = '#ff6b35';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
// 火焰效果
ctx.fillStyle = '#ff9e58';
ctx.beginPath();
ctx.arc(
segment.x * gridSize + gridSize/2,
segment.y * gridSize + gridSize/2,
gridSize/2 - 2,
0,
Math.PI * 2
);
ctx.fill();
} else if (currentSkin === 'ice') {
// 寒冰皮肤
ctx.fillStyle = '#4cc9f0';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
// 寒冰效果
ctx.fillStyle = '#90e0ef';
ctx.beginPath();
ctx.arc(
segment.x * gridSize + gridSize/2,
segment.y * gridSize + gridSize/2,
gridSize/2 - 2,
0,
Math.PI * 2
);
ctx.fill();
} else {
// 默认皮肤
ctx.fillStyle = '#4dccbd';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
// 蛇头高光
ctx.fillStyle = '#7bdef0';
ctx.fillRect(segment.x * gridSize + 4, segment.y * gridSize + 4, gridSize - 8, gridSize - 8);
}
// 眼睛
ctx.fillStyle = '#1a1a2e';
if (direction === 'right') {
ctx.fillRect(segment.x * gridSize + 12, segment.y * gridSize + 5, 4, 4);
ctx.fillRect(segment.x * gridSize + 12, segment.y * gridSize + 11, 4, 4);
} else if (direction === 'left') {
ctx.fillRect(segment.x * gridSize + 4, segment.y * gridSize + 5, 4, 4);
ctx.fillRect(segment.x * gridSize + 4, segment.y * gridSize + 11, 4, 4);
} else if (direction === 'up') {
ctx.fillRect(segment.x * gridSize + 5, segment.y * gridSize + 4, 4, 4);
ctx.fillRect(segment.x * gridSize + 11, segment.y * gridSize + 4, 4, 4);
} else if (direction === 'down') {
ctx.fillRect(segment.x * gridSize + 5, segment.y * gridSize + 12, 4, 4);
ctx.fillRect(segment.x * gridSize + 11, segment.y * gridSize + 12, 4, 4);
}
}
// 蛇身
else {
if (currentSkin === 'fire') {
// 火焰皮肤
ctx.fillStyle = '#f72585';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
ctx.fillStyle = '#ff70a6';
ctx.fillRect(segment.x * gridSize + 4, segment.y * gridSize + 4, gridSize - 8, gridSize - 8);
} else if (currentSkin === 'ice') {
// 寒冰皮肤
ctx.fillStyle = '#4895ef';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
ctx.fillStyle = '#90e0ef';
ctx.fillRect(segment.x * gridSize + 4, segment.y * gridSize + 4, gridSize - 8, gridSize - 8);
} else {
// 默认皮肤
ctx.fillStyle = '#3aafa9';
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
// 蛇身内部
ctx.fillStyle = '#4dccbd';
ctx.fillRect(segment.x * gridSize + 4, segment.y * gridSize + 4, gridSize - 8, gridSize - 8);
}
}
}
// 无敌状态下的闪烁效果
if (isInvincibleActive && Math.floor(invincibleTime / 5) % 2 === 0) {
ctx.globalAlpha = 0.5;
ctx.fillStyle = '#ffffff';
for (let segment of snake) {
ctx.beginPath();
ctx.arc(
segment.x * gridSize + gridSize/2,
segment.y * gridSize + gridSize/2,
gridSize/2,
0,
Math.PI * 2
);
ctx.fill();
}
ctx.globalAlpha = 1.0;
}
}
// 绘制食物
function drawFood() {
// 食物主体
ctx.fillStyle = '#ff6b6b';
ctx.beginPath();
ctx.arc(
food.x * gridSize + gridSize / 2,
food.y * gridSize + gridSize / 2,
gridSize / 2 - 2,
0,
Math.PI * 2
);
ctx.fill();
// 食物高光
ctx.fillStyle = '#ff9e9e';
ctx.beginPath();
ctx.arc(
food.x * gridSize + gridSize / 3,
food.y * gridSize + gridSize / 3,
gridSize / 6,
0,
Math.PI * 2
);
ctx.fill();
}
// 绘制特殊食物
function drawSpecialFood() {
// 设置颜色
let mainColor, highlightColor;
switch (specialFood.type) {
case 'shorten':
mainColor = '#4dccbd';
highlightColor = '#7bdef0';
break;
case 'speed':
mainColor = '#ffd166';
highlightColor = '#ffedb0';
break;
case 'invincible':
mainColor = '#ef476f';
highlightColor = '#ff87a1';
break;
}
// 特殊食物主体
ctx.fillStyle = mainColor;
ctx.beginPath();
ctx.arc(
specialFood.x * gridSize + gridSize / 2,
specialFood.y * gridSize + gridSize / 2,
gridSize / 2 - 2,
0,
Math.PI * 2
);
ctx.fill();
// 特殊食物闪烁效果
if (Math.floor(specialFoodTimer / 10) % 2 === 0) {
ctx.fillStyle = highlightColor;
ctx.beginPath();
ctx.arc(
specialFood.x * gridSize + gridSize / 2,
specialFood.y * gridSize + gridSize / 2,
gridSize / 4,
0,
Math.PI * 2
);
ctx.fill();
}
}
// 更新游戏状态
function update() {
if (gamePaused) return;
// 更新特殊食物计时器
if (specialFoodActive) {
specialFoodTimer--;
if (specialFoodTimer <= 0) {
specialFoodActive = false;
}
} else {
generateSpecialFood();
}
// 更新能量状态计时器
updatePowerUpTimers();
// 更新方向
direction = nextDirection;
// 计算新蛇头位置
const head = {x: snake[0].x, y: snake[0].y};
switch (direction) {
case 'up':
head.y--;
break;
case 'down':
head.y++;
break;
case 'left':
head.x--;
break;
case 'right':
head.x++;
break;
}
// 检查游戏结束条件(无敌状态除外)
if (!isInvincibleActive) {
// 检查撞墙
if (
head.x < 0 ||
head.y < 0 ||
head.x >= gridWidth ||
head.y >= gridHeight
) {
gameOver();
return;
}
// 检查撞到障碍物
for (let obstacle of obstacles) {
if (head.x === obstacle.x && head.y === obstacle.y) {
gameOver();
return;
}
}
// 检查撞到自己
if (checkCollision(head)) {
gameOver();
return;
}
}
// 添加新蛇头
snake.unshift(head);
// 检查是否吃到食物
if (head.x === food.x && head.y === food.y) {
// 增加分数
const points = 10 * scoreMultiplier;
score += points;
// 连续吃到食物
consecutiveFood++;
if (consecutiveFood >= 3) {
scoreMultiplier = Math.min(5, Math.floor(consecutiveFood / 3) + 1);
multiplierTimer = 300; // 5秒
}
updateScore();
// 检查是否升级
checkLevelUp();
// 生成新食物
generateFood();
}
// 检查是否吃到特殊食物
else if (specialFoodActive && head.x === specialFood.x && head.y === specialFood.y) {
// 增加分数
const points = 50 * scoreMultiplier;
score += points;
updateScore();
// 根据特殊食物类型应用效果
switch (specialFood.type) {
case 'shorten':
// 缩短蛇身(最多保留3节)
if (snake.length > 3) {
snake.pop();
if (snake.length > 3) snake.pop();
}
isShortenActive = true;
shortenTime = 300; // 5秒
break;
case 'speed':
isSpeedUpActive = true;
speedupTime = 300; // 5秒
break;
case 'invincible':
isInvincibleActive = true;
invincibleTime = 450; // 7.5秒
break;
}
specialFoodActive = false;
}
// 没吃到食物,移除蛇尾
else {
snake.pop();
consecutiveFood = 0;
}
// 绘制游戏
draw();
}
// 更新能量状态计时器
function updatePowerUpTimers() {
// 更新缩短计时器
if (isShortenActive) {
shortenTime--;
if (shortenTime <= 0) {
isShortenActive = false;
}
}
// 更新加速计时器
if (isSpeedUpActive) {
speedupTime--;
if (speedupTime <= 0) {
isSpeedUpActive = false;
}
}
// 更新无敌计时器
if (isInvincibleActive) {
invincibleTime--;
if (invincibleTime <= 0) {
isInvincibleActive = false;
}
}
// 更新分数倍数计时器
if (scoreMultiplier > 1) {
multiplierTimer--;
if (multiplierTimer <= 0) {
scoreMultiplier = 1;
consecutiveFood = 0;
}
}
// 更新显示
shortenTimer.textContent = isShortenActive ? Math.ceil(shortenTime/60) + 's' : '0s';
speedupTimer.textContent = isSpeedUpActive ? Math.ceil(speedupTime/60) + 's' : '0s';
invincibleTimer.textContent = isInvincibleActive ? Math.ceil(invincibleTime/60) + 's' : '0s';
multiplierElement.textContent = 'x' + scoreMultiplier;
// 更新实际游戏速度
actualSpeed = baseSpeed;
if (isSpeedUpActive) {
actualSpeed = Math.max(30, baseSpeed * 0.6);
}
// 如果游戏正在运行,更新游戏速度
if (gameRunning) {
clearInterval(gameInterval);
gameInterval = setInterval(update, actualSpeed);
}
}
// 检查升级
function checkLevelUp() {
const newLevel = Math.floor(score / 100) + 1;
if (newLevel > level) {
level = newLevel;
levelElement.textContent = level;
generateObstacles();
}
}
// 检查碰撞
function checkCollision(position) {
for (let i = 1; i < snake.length; i++) {
if (snake[i].x === position.x && snake[i].y === position.y) {
return true;
}
}
return false;
}
// 更新分数显示
function updateScore() {
scoreElement.textContent = score;
const speedValue = Math.floor(1500 / baseSpeed);
speedElement.innerHTML = speedValue + `<span class="multiplier">x${isSpeedUpActive ? 1.5 : 1}</span>`;
// 更新最高分
if (score > highScore) {
highScore = score;
highScoreElement.textContent = highScore;
localStorage.setItem('snakeHighScore', highScore);
}
}
// 游戏结束
function gameOver() {
clearInterval(gameInterval);
gameRunning = false;
finalScoreElement.textContent = score;
finalLevelElement.textContent = level;
gameOverScreen.style.display = 'flex';
}
// 开始游戏
function startGame() {
if (gameRunning) return;
initGame();
gameRunning = true;
gamePaused = false;
startScreen.style.display = 'none';
pauseBtn.textContent = '暂停';
gameInterval = setInterval(update, actualSpeed);
}
// 暂停游戏
function togglePause() {
if (!gameRunning) return;
gamePaused = !gamePaused;
pauseBtn.textContent = gamePaused ? '继续' : '暂停';
}
// 重置游戏
function resetGame() {
clearInterval(gameInterval);
startGame();
}
// 键盘控制
document.addEventListener('keydown', (e) => {
if (!gameRunning) return;
switch (e.key) {
case 'ArrowUp':
case 'w':
case 'W':
if (direction !== 'down') nextDirection = 'up';
break;
case 'ArrowDown':
case 's':
case 'S':
if (direction !== 'up') nextDirection = 'down';
break;
case 'ArrowLeft':
case 'a':
case 'A':
if (direction !== 'right') nextDirection = 'left';
break;
case 'ArrowRight':
case 'd':
case 'D':
if (direction !== 'left') nextDirection = 'right';
break;
case ' ':
togglePause();
break;
}
});
// 移动端控制
mobileControls.forEach(btn => {
btn.addEventListener('click', () => {
if (!gameRunning) return;
const directionMap = {
'up': () => { if (direction !== 'down') nextDirection = 'up'; },
'down': () => { if (direction !== 'up') nextDirection = 'down'; },
'left': () => { if (direction !== 'right') nextDirection = 'left'; },
'right': () => { if (direction !== 'left') nextDirection = 'right'; }
};
directionMap[btn.classList[1]]();
});
});
// 难度选择
difficultyBtns.forEach(btn => {
btn.addEventListener('click', () => {
// 更新活动按钮
difficultyBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
// 更新游戏速度
baseSpeed = parseInt(btn.dataset.speed);
updateScore();
// 如果游戏正在运行,更新游戏速度
if (gameRunning) {
clearInterval(gameInterval);
gameInterval = setInterval(update, actualSpeed);
}
});
});
// 皮肤选择
skinBtns.forEach(btn => {
btn.addEventListener('click', () => {
// 更新活动按钮
skinBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
// 更新皮肤
currentSkin = btn.dataset.skin;
// 重绘游戏
if (gameRunning) draw();
});
});
// 按钮事件监听
startBtn.addEventListener('click', startGame);
pauseBtn.addEventListener('click', togglePause);
resetBtn.addEventListener('click', resetGame);
restartBtn.addEventListener('click', startGame);
// 初始化
initGame();
highScoreElement.textContent = highScore;
});
</script>
</body>
</html>