我将为您创建一个功能完整的水果忍者HTML5网页版游戏,这个游戏将包含切水果、炸弹躲避、连击系统等核心玩法。

(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">水果忍者 - HTML5版</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
overflow: hidden;
position: relative;
height: 100vh;
}
#gameCanvas {
display: block;
cursor: none;
background: linear-gradient(to bottom, #87CEEB 0%, #98D8E8 50%, #F0E68C 100%);
}
.game-ui {
position: absolute;
top: 0;
left: 0;
right: 0;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(to bottom, rgba(0,0,0,0.3), transparent);
pointer-events: none;
}
.score {
font-size: 36px;
font-weight: bold;
color: white;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
.lives {
display: flex;
gap: 10px;
}
.heart {
width: 40px;
height: 40px;
background: #ff4757;
position: relative;
transform: rotate(-45deg);
animation: heartbeat 1.5s ease-in-out infinite;
}
.heart::before,
.heart::after {
content: '';
width: 40px;
height: 40px;
position: absolute;
background: #ff4757;
border-radius: 50%;
}
.heart::before {
top: -20px;
left: 0;
}
.heart::after {
left: 20px;
top: 0;
}
.heart.lost {
background: #555;
animation: none;
}
.heart.lost::before,
.heart.lost::after {
background: #555;
}
@keyframes heartbeat {
0% { transform: rotate(-45deg) scale(1); }
50% { transform: rotate(-45deg) scale(1.1); }
100% { transform: rotate(-45deg) scale(1); }
}
.combo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 60px;
font-weight: bold;
color: #ffd700;
text-shadow: 3px 3px 6px rgba(0,0,0,0.7);
opacity: 0;
pointer-events: none;
}
.combo.show {
animation: comboAnimation 1s ease-out;
}
@keyframes comboAnimation {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(0.5);
}
50% {
opacity: 1;
transform: translate(-50%, -50%) scale(1.2);
}
100% {
opacity: 0;
transform: translate(-50%, -50%) scale(1.5);
}
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.9);
color: white;
padding: 40px;
border-radius: 20px;
text-align: center;
display: none;
}
.game-over h2 {
font-size: 48px;
margin-bottom: 20px;
color: #ff4757;
}
.game-over p {
font-size: 24px;
margin-bottom: 30px;
}
.restart-btn {
background: #5dade2;
color: white;
border: none;
padding: 15px 40px;
font-size: 20px;
border-radius: 30px;
cursor: pointer;
transition: all 0.3s;
}
.restart-btn:hover {
background: #3498db;
transform: scale(1.05);
}
.start-screen {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
}
.start-screen h1 {
font-size: 64px;
margin-bottom: 20px;
text-shadow: 3px 3px 6px rgba(0,0,0,0.7);
}
.start-screen p {
font-size: 24px;
margin-bottom: 40px;
text-align: center;
max-width: 600px;
}
.start-btn {
background: #2ecc71;
color: white;
border: none;
padding: 20px 60px;
font-size: 28px;
border-radius: 40px;
cursor: pointer;
transition: all 0.3s;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.start-btn:hover {
background: #27ae60;
transform: scale(1.1);
}
.blade-trail {
position: absolute;
pointer-events: none;
z-index: 1000;
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<div class="game-ui">
<div class="score">得分: <span id="scoreValue">0</span></div>
<div class="lives" id="livesContainer">
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
</div>
</div>
<div class="combo" id="comboText"></div>
<div class="game-over" id="gameOverScreen">
<h2>游戏结束</h2>
<p>最终得分: <span id="finalScore">0</span></p>
<button class="restart-btn" onclick="restartGame()">重新开始</button>
</div>
<div class="start-screen" id="startScreen">
<h1>水果忍者</h1>
<p>用鼠标或手指切开水果,避开炸弹!<br>连续切开水果可获得连击加分!</p>
<button class="start-btn" onclick="startGame()">开始游戏</button>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('scoreValue');
const comboElement = document.getElementById('comboText');
const gameOverScreen = document.getElementById('gameOverScreen');
const finalScoreElement = document.getElementById('finalScore');
const startScreen = document.getElementById('startScreen');
const livesContainer = document.getElementById('livesContainer');
// 游戏状态
let gameRunning = false;
let score = 0;
let lives = 3;
let combo = 0;
let lastCutTime = 0;
let particles = [];
let fruits = [];
let bombs = [];
let bladeTrail = [];
// 设置画布大小
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// 水果类型
const fruitTypes = [
{ name: 'apple', color: '#ff6b6b', points: 10 },
{ name: 'orange', color: '#ffa502', points: 15 },
{ name: 'watermelon', color: '#2ed573', points: 20 },
{ name: 'grape', color: '#a55eea', points: 25 },
{ name: 'banana', color: '#ffd93d', points: 30 }
];
// 水果类
class Fruit {
constructor() {
this.type = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
this.x = Math.random() * (canvas.width - 100) + 50;
this.y = canvas.height + 50;
this.vx = (Math.random() - 0.5) * 8;
this.vy = -20 - Math.random() * 10;
this.gravity = 0.5;
this.radius = 40;
this.sliced = false;
this.rotation = 0;
this.rotationSpeed = (Math.random() - 0.5) * 0.2;
}
update() {
if (!this.sliced) {
this.x += this.vx;
this.y += this.vy;
this.vy += this.gravity;
this.rotation += this.rotationSpeed;
} else {
this.vy += this.gravity * 0.5;
this.y += this.vy;
this.x += this.vx * 0.5;
this.rotation += this.rotationSpeed * 2;
}
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation);
if (!this.sliced) {
// 绘制完整水果
ctx.fillStyle = this.type.color;
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
ctx.fill();
// 添加高光
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
ctx.beginPath();
ctx.arc(-this.radius * 0.3, -this.radius * 0.3, this.radius * 0.3, 0, Math.PI * 2);
ctx.fill();
} else {
// 绘制切开的水果
for (let i = 0; i < 2; i++) {
ctx.save();
ctx.translate(i * this.radius * 0.8 - this.radius * 0.4, 0);
ctx.scale(i === 0 ? 1 : -1, 1);
ctx.fillStyle = this.type.color;
ctx.beginPath();
ctx.arc(0, 0, this.radius * 0.6, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
ctx.restore();
}
checkSlice(x1, y1, x2, y2) {
if (this.sliced) return false;
// 简化的切割检测
const dist = this.distanceToLine(x1, y1, x2, y2);
if (dist < this.radius) {
this.sliced = true;
this.vx = (this.x - x1) * 0.1;
this.vy = -5;
createParticles(this.x, this.y, this.type.color);
return true;
}
return false;
}
distanceToLine(x1, y1, x2, y2) {
const A = this.x - x1;
const B = this.y - y1;
const C = x2 - x1;
const D = y2 - y1;
const dot = A * C + B * D;
const lenSq = C * C + D * D;
let param = -1;
if (lenSq !== 0) param = dot / lenSq;
let xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
} else if (param > 1) {
xx = x2;
yy = y2;
} else {
xx = x1 + param * C;
yy = y1 + param * D;
}
const dx = this.x - xx;
const dy = this.y - yy;
return Math.sqrt(dx * dx + dy * dy);
}
}
// 炸弹类
class Bomb {
constructor() {
this.x = Math.random() * (canvas.width - 100) + 50;
this.y = canvas.height + 50;
this.vx = (Math.random() - 0.5) * 6;
this.vy = -18 - Math.random() * 8;
this.gravity = 0.5;
this.radius = 35;
this.rotation = 0;
this.rotationSpeed = 0.05;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.vy += this.gravity;
this.rotation += this.rotationSpeed;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation);
// 绘制炸弹
ctx.fillStyle = '#2c3e50';
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
ctx.fill();
// 绘制引线
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(0, -this.radius);
ctx.lineTo(0, -this.radius - 20);
ctx.stroke();
// 绘制火花
ctx.fillStyle = '#f39c12';
for (let i = 0; i < 5; i++) {
const angle = (Date.now() / 100 + i * 72) * Math.PI / 180;
const sparkX = Math.cos(angle) * 10;
const sparkY = Math.sin(angle) * 10 - this.radius - 20;
ctx.beginPath();
ctx.arc(sparkX, sparkY, 3, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
}
checkSlice(x1, y1, x2, y2) {
const dist = this.distanceToLine(x1, y1, x2, y2);
if (dist < this.radius) {
explodeBomb(this.x, this.y);
return true;
}
return false;
}
distanceToLine(x1, y1, x2, y2) {
const A = this.x - x1;
const B = this.y - y1;
const C = x2 - x1;
const D = y2 - y1;
const dot = A * C + B * D;
const lenSq = C * C + D * D;
let param = -1;
if (lenSq !== 0) param = dot / lenSq;
let xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
} else if (param > 1) {
xx = x2;
yy = y2;
} else {
xx = x1 + param * C;
yy = y1 + param * D;
}
const dx = this.x - xx;
const dy = this.y - yy;
return Math.sqrt(dx * dx + dy * dy);
}
}
// 粒子效果
class Particle {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.vx = (Math.random() - 0.5) * 10;
this.vy = (Math.random() - 0.5) * 10;
this.color = color;
this.life = 1;
this.decay = 0.02;
this.size = Math.random() * 5 + 2;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.vy += 0.3;
this.life -= this.decay;
this.size *= 0.98;
}
draw() {
ctx.save();
ctx.globalAlpha = this.life;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
// 创建粒子效果
function createParticles(x, y, color) {
for (let i = 0; i < 20; i++) {
particles.push(new Particle(x, y, color));
}
}
// 炸弹爆炸效果
function explodeBomb(x, y) {
createParticles(x, y, '#e74c3c');
createParticles(x, y, '#f39c12');
createParticles(x, y, '#2c3e50');
loseLife();
combo = 0;
}
// 失去生命
function loseLife() {
lives--;
const hearts = livesContainer.querySelectorAll('.heart');
hearts[3 - lives].classList.add('lost');
if (lives <= 0) {
gameOver();
}
}
// 显示连击
function showCombo() {
if (combo > 1) {
comboElement.textContent = `${combo}x 连击!`;
comboElement.classList.remove('show');
void comboElement.offsetWidth; // 触发重排
comboElement.classList.add('show');
}
}
// 生成水果和炸弹
function spawnObject() {
if (Math.random() < 0.8) {
fruits.push(new Fruit());
} else {
bombs.push(new Bomb());
}
}
// 鼠标/触摸事件
let isMouseDown = false;
let lastMouseX = 0;
let lastMouseY = 0;
canvas.addEventListener('mousedown', (e) => {
isMouseDown = true;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
});
canvas.addEventListener('mousemove', (e) => {
if (isMouseDown && gameRunning) {
const currentX = e.clientX;
const currentY = e.clientY;
// 检查切割
fruits.forEach(fruit => {
if (fruit.checkSlice(lastMouseX, lastMouseY, currentX, currentY)) {
score += fruit.type.points * (combo + 1);
scoreElement.textContent = score;
combo++;
lastCutTime = Date.now();
showCombo();
}
});
bombs.forEach(bomb => {
if (bomb.checkSlice(lastMouseX, lastMouseY, currentX, currentY)) {
// 炸弹已在checkSlice中处理
}
});
// 更新刀光轨迹
bladeTrail.push({
x1: lastMouseX,
y1: lastMouseY,
x2: currentX,
y2: currentY,
life: 1
});
lastMouseX = currentX;
lastMouseY = currentY;
}
});
canvas.addEventListener('mouseup', () => {
isMouseDown = false;
});
// 触摸事件支持
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
const touch = e.touches[0];
isMouseDown = true;
lastMouseX = touch.clientX;
lastMouseY = touch.clientY;
});
canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
if (isMouseDown && gameRunning) {
const touch = e.touches[0];
const currentX = touch.clientX;
const currentY = touch.clientY;
// 检查切割
fruits.forEach(fruit => {
if (fruit.checkSlice(lastMouseX, lastMouseY, currentX, currentY)) {
score += fruit.type.points * (combo + 1);
scoreElement.textContent = score;
combo++;
lastCutTime = Date.now();
showCombo();
}
});
bombs.forEach(bomb => {
if (bomb.checkSlice(lastMouseX, lastMouseY, currentX, currentY)) {
// 炸弹已在checkSlice中处理
}
});
bladeTrail.push({
x1: lastMouseX,
y1: lastMouseY,
x2: currentX,
y2: currentY,
life: 1
});
lastMouseX = currentX;
lastMouseY = currentY;
}
});
canvas.addEventListener('touchend', (e) => {
e.preventDefault();
isMouseDown = false;
});
// 游戏循环
function gameLoop() {
if (!gameRunning) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制背景渐变
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, '#87CEEB');
gradient.addColorStop(0.5, '#98D8E8');
gradient.addColorStop(1, '#F0E68C');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 生成新对象
if (Math.random() < 0.02) {
spawnObject();
}
// 更新和绘制水果
fruits = fruits.filter(fruit => {
fruit.update();
fruit.draw();
return fruit.y < canvas.height + 100 && !fruit.sliced || fruit.y < canvas.height + 50;
});
// 更新和绘制炸弹
bombs = bombs.filter(bomb => {
bomb.update();
bomb.draw();
return bomb.y < canvas.height + 100;
});
// 更新和绘制粒子
particles = particles.filter(particle => {
particle.update();
particle.draw();
return particle.life > 0;
});
// 更新和绘制刀光轨迹
bladeTrail = bladeTrail.filter(trail => {
trail.life -= 0.05;
if (trail.life > 0) {
ctx.save();
ctx.globalAlpha = trail.life * 0.5;
ctx.strokeStyle = '#fff';
ctx.lineWidth = 3;
ctx.lineCap = 'round';
ctx.shadowBlur = 10;
ctx.shadowColor = '#fff';
ctx.beginPath();
ctx.moveTo(trail.x1, trail.y1);
ctx.lineTo(trail.x2, trail.y2);
ctx.stroke();
ctx.restore();
return true;
}
return false;
});
// 检查连击超时
if (Date.now() - lastCutTime > 2000 && combo > 0) {
combo = 0;
}
requestAnimationFrame(gameLoop);
}
// 开始游戏
function startGame() {
startScreen.style.display = 'none';
gameRunning = true;
score = 0;
lives = 3;
combo = 0;
fruits = [];
bombs = [];
particles = [];
bladeTrail = [];
scoreElement.textContent = score;
// 重置生命值显示
const hearts = livesContainer.querySelectorAll('.heart');
hearts.forEach(heart => heart.classList.remove('lost'));
gameLoop();
}
// 游戏结束
function gameOver() {
gameRunning = false;
finalScoreElement.textContent = score;
gameOverScreen.style.display = 'block';
}
// 重新开始
function restartGame() {
gameOverScreen.style.display = 'none';
startGame();
}
// 初始化
window.addEventListener('load', () => {
// 游戏在开始界面等待
});
</script>
</body>
</html>
这个水果忍者HTML5游戏包含了以下特性:
核心功能:
- 切水果机制 - 鼠标拖动或触摸滑动来切开水果
- 多种水果类型 - 苹果、橙子、西瓜、葡萄、香蕉,不同分值
- 炸弹系统 - 切到炸弹会失去生命值
- 生命系统 - 3条生命,用心形图标显示
- 连击系统 - 连续切开水果获得加分倍数
- 粒子效果 - 切开水果时的爆炸粒子效果
- 刀光轨迹 - 切割时显示白色发光轨迹
视觉效果:
- 渐变天空背景
- 水果3D旋转效果
- 切开水果的动画
- 炸弹的旋转和火花效果
- 连击提示动画
- 心跳动画的生命值显示
游戏控制:
- 鼠标拖动切割
- 触摸屏支持
- 响应式设计,适配各种屏幕
游戏玩法:
- 点击"开始游戏"按钮
- 用鼠标或手指切开飞起的水果
- 避开黑色炸弹
- 连续切开水果获得连击加分
- 失去所有生命后游戏结束
游戏具有流畅的动画效果和完整的游戏体验,可以直接在浏览器中运行!

(图片来源网络,侵删)
