HTML5 Canvas游戏开发:从零构建太空射击游戏 | 完整教程

2025-08-05 0 539

通过本教程学习使用HTML5 Canvas和JavaScript创建完整的2D游戏

Canvas游戏开发基础

HTML5 Canvas是一个强大的元素,允许通过JavaScript动态绘制图形。它非常适合创建2D游戏、数据可视化和交互式动画。

专业提示: 使用Canvas时,双缓冲技术可以避免画面闪烁。在内存中绘制完整帧后再渲染到屏幕。

1. Canvas基本设置

首先在HTML中创建Canvas元素:

<canvas id="gameCanvas" width="800" height="600">
  您的浏览器不支持Canvas,请升级浏览器
</canvas>

在JavaScript中获取上下文:

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

2. 游戏循环结构

所有游戏都需要一个主循环来更新游戏状态和重绘画面:

function gameLoop() {
  // 1. 清除画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  // 2. 更新游戏状态
  updateGame();
  
  // 3. 绘制游戏场景
  drawGame();
  
  // 4. 请求下一帧
  requestAnimationFrame(gameLoop);
}

// 启动游戏循环
gameLoop();

3. 创建玩家飞船

使用路径绘制三角形作为飞船:

function drawShip(x, y) {
  ctx.save();
  ctx.translate(x, y);
  
  // 绘制三角形飞船
  ctx.beginPath();
  ctx.moveTo(0, -15);
  ctx.lineTo(10, 15);
  ctx.lineTo(-10, 15);
  ctx.closePath();
  
  ctx.fillStyle = '#2ecc71';
  ctx.fill();
  ctx.strokeStyle = '#3498db';
  ctx.lineWidth = 2;
  ctx.stroke();
  
  ctx.restore();
}

4. 处理用户输入

通过键盘事件控制飞船移动:

const keys = {};

window.addEventListener('keydown', e => {
  keys[e.key] = true;
});

window.addEventListener('keyup', e => {
  keys[e.key] = false;
});

function handleInput() {
  if (keys['ArrowLeft']) ship.x -= 5;
  if (keys['ArrowRight']) ship.x += 5;
  if (keys['ArrowUp']) ship.y -= 5;
  if (keys['ArrowDown']) ship.y += 5;
}

5. 添加敌人和碰撞检测

创建随机敌人并检测碰撞:

// 创建敌人
function createEnemy() {
  return {
    x: Math.random() * canvas.width,
    y: -30,
    radius: 15,
    speed: Math.random() * 2 + 1
  };
}

// 碰撞检测
function checkCollision(obj1, obj2) {
  const dx = obj1.x - obj2.x;
  const dy = obj1.y - obj2.y;
  const distance = Math.sqrt(dx * dx + dy * dy);
  
  return distance < obj1.radius + obj2.radius;
}

6. 添加粒子效果

使用粒子系统增强游戏体验:

class Particle {
  constructor(x, y, color) {
    this.x = x;
    this.y = y;
    this.color = color;
    this.radius = Math.random() * 3 + 1;
    this.speedX = Math.random() * 6 - 3;
    this.speedY = Math.random() * 6 - 3;
    this.alpha = 1;
  }
  
  update() {
    this.x += this.speedX;
    this.y += this.speedY;
    this.alpha -= 0.01;
  }
  
  draw() {
    ctx.save();
    ctx.globalAlpha = this.alpha;
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fill();
    ctx.restore();
  }
}

7. 完整游戏结构

游戏应包含以下核心模块:

  1. 游戏初始化
  2. 资源加载(图像、声音)
  3. 输入处理系统
  4. 游戏对象管理
  5. 物理和碰撞系统
  6. 渲染系统
  7. 游戏状态管理(菜单、游戏中、结束)

太空射击游戏演示

分数: 0
生命: 3
等级: 1



← →
↑ ↓
空格键射击

游戏说明

  • 使用方向键移动飞船
  • 空格键发射子弹
  • 躲避陨石和敌人飞船
  • 收集能量包恢复生命
  • 每1000分提升一个等级

注意: 此演示仅包含核心游戏机制,完整游戏可扩展添加音效、更多敌人类型、BOSS战和升级系统。

// Canvas游戏实现
const canvas = document.getElementById(‘gameCanvas’);
const ctx = canvas.getContext(‘2d’);
const scoreElement = document.getElementById(‘score’);
const livesElement = document.getElementById(‘lives’);
const levelElement = document.getElementById(‘level’);
const startBtn = document.getElementById(‘startBtn’);
const pauseBtn = document.getElementById(‘pauseBtn’);
const resetBtn = document.getElementById(‘resetBtn’);

// 游戏状态
const gameState = {
score: 0,
lives: 3,
level: 1,
isRunning: false,
isPaused: false
};

// 玩家飞船
const ship = {
x: canvas.width / 2,
y: canvas.height – 50,
width: 30,
height: 40,
speed: 6,
color: ‘#2ecc71’,
bullets: []
};

// 游戏对象
let enemies = [];
let particles = [];
let powerUps = [];
let stars = [];

// 键盘状态
const keys = {};

// 初始化星星背景
function initStars() {
stars = [];
for (let i = 0; i {
ctx.beginPath();
ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
ctx.fill();
});
}

// 更新星星位置
function updateStars() {
stars.forEach(star => {
star.y += star.speed;
if (star.y > canvas.height) {
star.y = 0;
star.x = Math.random() * canvas.width;
}
});
}

// 绘制玩家飞船
function drawShip() {
ctx.save();
ctx.translate(ship.x, ship.y);

// 飞船主体
ctx.beginPath();
ctx.moveTo(0, -15);
ctx.lineTo(10, 15);
ctx.lineTo(-10, 15);
ctx.closePath();

ctx.fillStyle = ship.color;
ctx.fill();
ctx.strokeStyle = ‘#3498db’;
ctx.lineWidth = 2;
ctx.stroke();

// 飞船引擎
ctx.beginPath();
ctx.moveTo(-6, 15);
ctx.lineTo(0, 25);
ctx.lineTo(6, 15);
ctx.strokeStyle = ‘#e74c3c’;
ctx.lineWidth = 2;
ctx.stroke();

ctx.restore();
}

// 绘制敌人
function drawEnemies() {
enemies.forEach(enemy => {
ctx.save();
ctx.translate(enemy.x, enemy.y);

// 敌人主体
ctx.beginPath();
ctx.arc(0, 0, enemy.radius, 0, Math.PI * 2);
ctx.fillStyle = enemy.color;
ctx.fill();
ctx.strokeStyle = ‘#c0392b’;
ctx.lineWidth = 2;
ctx.stroke();

// 敌人特征
ctx.beginPath();
ctx.arc(0, 0, enemy.radius * 0.6, 0, Math.PI * 2);
ctx.strokeStyle = ‘#e74c3c’;
ctx.stroke();

ctx.restore();
});
}

// 绘制子弹
function drawBullets() {
ship.bullets.forEach(bullet => {
ctx.save();
ctx.translate(bullet.x, bullet.y);

ctx.beginPath();
ctx.rect(-2, -10, 4, 20);
ctx.fillStyle = ‘#f1c40f’;
ctx.fill();
ctx.strokeStyle = ‘#e67e22’;
ctx.lineWidth = 1;
ctx.stroke();

ctx.restore();
});
}

// 绘制粒子
function drawParticles() {
particles.forEach(particle => {
ctx.save();
ctx.globalAlpha = particle.alpha;
ctx.fillStyle = particle.color;
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
});
}

// 绘制能量包
function drawPowerUps() {
powerUps.forEach(powerUp => {
ctx.save();
ctx.translate(powerUp.x, powerUp.y);

ctx.beginPath();
ctx.rect(-10, -10, 20, 20);
ctx.fillStyle = ‘#9b59b6’;
ctx.fill();
ctx.strokeStyle = ‘#8e44ad’;
ctx.lineWidth = 2;
ctx.stroke();

ctx.fillStyle = ‘#ffffff’;
ctx.font = ‘bold 16px Arial’;
ctx.textAlign = ‘center’;
ctx.textBaseline = ‘middle’;
ctx.fillText(‘+’, 0, 0);

ctx.restore();
});
}

// 创建敌人
function createEnemy() {
const radius = Math.random() * 15 + 10;
return {
x: Math.random() * (canvas.width – radius * 2) + radius,
y: -radius,
radius: radius,
speed: Math.random() * 2 + 1,
color: `hsl(${Math.random() * 360}, 70%, 60%)`
};
}

// 创建粒子
function createParticles(x, y, color, count) {
for (let i = 0; i < count; i++) {
particles.push({
x: x,
y: y,
color: color,
radius: Math.random() * 3 + 1,
speedX: Math.random() * 6 – 3,
speedY: Math.random() * 6 – 3,
alpha: 1
});
}
}

// 创建能量包
function createPowerUp(x, y) {
powerUps.push({
x: x,
y: y,
width: 20,
height: 20,
speed: 2
});
}

// 发射子弹
function fireBullet() {
ship.bullets.push({
x: ship.x,
y: ship.y – 20,
width: 4,
height: 20,
speed: 10
});
}

// 碰撞检测
function checkCollision(obj1, obj2) {
const dx = obj1.x – obj2.x;
const dy = obj1.y – obj2.y;
const distance = Math.sqrt(dx * dx + dy * dy);

return distance ship.width/2) ship.x -= ship.speed;
if (keys[‘ArrowRight’] && ship.x ship.height/2) ship.y -= ship.speed;
if (keys[‘ArrowDown’] && ship.y < canvas.height – ship.height/2) ship.y += ship.speed;

// 生成敌人
if (Math.random() {
enemy.y += enemy.speed;

// 检测敌人与玩家碰撞
if (checkCollision(ship, enemy)) {
createParticles(enemy.x, enemy.y, enemy.color, 20);
enemies.splice(index, 1);
gameState.lives–;
livesElement.textContent = gameState.lives;
return;
}

// 移除超出屏幕的敌人
if (enemy.y > canvas.height + enemy.radius) {
enemies.splice(index, 1);
}
});

// 更新子弹位置
ship.bullets.forEach((bullet, bIndex) => {
bullet.y -= bullet.speed;

// 检测子弹与敌人碰撞
enemies.forEach((enemy, eIndex) => {
if (checkCollision(bullet, enemy)) {
createParticles(enemy.x, enemy.y, enemy.color, 20);
enemies.splice(eIndex, 1);
ship.bullets.splice(bIndex, 1);
gameState.score += 100;
scoreElement.textContent = gameState.score;

// 随机生成能量包
if (Math.random() < 0.3) {
createPowerUp(enemy.x, enemy.y);
}

// 更新等级
gameState.level = Math.floor(gameState.score / 1000) + 1;
levelElement.textContent = gameState.level;
return;
}
});

// 移除超出屏幕的子弹
if (bullet.y {
powerUp.y += powerUp.speed;

// 检测能量包与玩家碰撞
if (checkCollision(ship, powerUp)) {
powerUps.splice(index, 1);
gameState.lives = Math.min(gameState.lives + 1, 5);
livesElement.textContent = gameState.lives;
return;
}

// 移除超出屏幕的能量包
if (powerUp.y > canvas.height) {
powerUps.splice(index, 1);
}
});

// 更新粒子
particles.forEach((particle, index) => {
particle.x += particle.speedX;
particle.y += particle.speedY;
particle.alpha -= 0.02;

if (particle.alpha <= 0) {
particles.splice(index, 1);
}
});

// 更新星星背景
updateStars();

// 检查游戏结束
if (gameState.lives {
if (!gameState.isRunning) {
initGame();
}
gameState.isPaused = false;
});

pauseBtn.addEventListener(‘click’, () => {
gameState.isPaused = !gameState.isPaused;
});

resetBtn.addEventListener(‘click’, initGame);

window.addEventListener(‘keydown’, e => {
keys[e.key] = true;

// 空格键发射子弹
if (e.key === ‘ ‘ && gameState.isRunning && !gameState.isPaused) {
fireBullet();
}
});

window.addEventListener(‘keyup’, e => {
keys[e.key] = false;
});

// 启动游戏循环
initStars();
gameLoop();

HTML5 Canvas游戏开发:从零构建太空射击游戏 | 完整教程
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 html HTML5 Canvas游戏开发:从零构建太空射击游戏 | 完整教程 https://www.taomawang.com/web/html/758.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务