从零开始打造一个简易飞机大战游戏
简易版飞机大战介绍
前言
大家好!今天我想和大家分享一个使用纯前端技术栈开发的简易飞机大战游戏。这个项目不仅适合初学者学习Web游戏开发的基础知识,也是一个了解前端项目结构组织和游戏逻辑实现的好例子。本文将详细介绍游戏的开发过程、技术栈选择、模块划分以及一些开发中遇到的技术难点。
游戏介绍
这是一个经典的飞机射击游戏,玩家控制一架飞机在屏幕下半部分自由移动,自动发射子弹击落从上方飞来的敌机。游戏包含两种敌机类型:普通敌机和精英敌机。普通敌机只会直线下落,而精英敌机会在屏幕上方自由移动并发射子弹。玩家需要躲避敌机和敌机子弹,同时击落尽可能多的敌机来获取高分。
游戏特点
- 简洁美观的界面设计,包含星空背景和发光效果
- 精美的飞机模型,使用SVG矢量图形
- 多级界面导航(主菜单、准备界面、游戏界面、结束界面)
- 两种敌机类型,增加游戏挑战性
- 血量系统,玩家和敌机都有血量属性
- 玩家可在下半屏幕自由移动(上下左右)
- 随着得分增加,游戏难度逐渐提高
- 背景音乐,提升游戏体验
- 局域网多设备访问支持
技术栈
本项目采用了以下技术栈:
- 前端:HTML5, CSS3, JavaScript (ES6+)
- 服务器:Node.js + Express
- 图形:SVG
- 构建工具:npm
这是一个轻量级的项目,没有使用任何前端框架,而是采用原生JavaScript实现,这使得项目结构清晰,容易理解,也便于初学者学习。
项目结构
easyAircraftWars/
├── public/ # 静态资源目录
│ ├── assets/ # 资源文件
│ │ ├── images/ # 图片资源
│ │ │ ├── player.svg # 玩家飞机图像
│ │ │ ├── enemy.svg # 敌机图像
│ │ │ ├── elite-enemy.svg # 精英敌机图像
│ │ │ └── explosion.svg # 爆炸效果图像
│ │ ├── audio/ # 音频资源
│ │ │ └── bgm.mp3 # 游戏背景音乐
│ │ └── favicon.ico # 网站图标
│ ├── css/ # 样式文件
│ │ └── style.css # 主样式表
│ ├── js/ # JavaScript文件
│ │ └── game.js # 游戏逻辑
│ └── index.html # 主HTML文件
├── server.js # Express服务器
├── package.json # 项目配置和依赖
└── README.md # 项目说明
模块详解
1. HTML结构 (index.html)
HTML文件定义了游戏的基本结构,包括四个主要界面:
- 主菜单:显示游戏标题、规则和开始按钮
- 准备界面:显示游戏准备信息和开始按钮
- 游戏区域:实际游戏进行的区域,包含玩家飞机、分数和血量显示
- 游戏结束界面:显示最终得分和重新开始按钮
这种多界面设计使游戏有了完整的流程,提升了用户体验。
2. 样式设计 (style.css)
CSS文件负责游戏的视觉效果,主要包括:
- 游戏容器:设置游戏区域的大小、背景和边框
- 星空背景:使用CSS渐变和多层背景创建动态星空效果
- 界面样式:为不同界面设置布局和过渡效果
- 游戏元素:定义玩家飞机、敌机、子弹和爆炸效果的样式
- 按钮和文本:设计交互元素的样式和动画效果
- 受伤效果:使用CSS动画实现飞机受伤时的闪烁效果
特别值得一提的是,我们使用了CSS滤镜和动画来创建发光效果,使游戏具有科幻感。
3. 游戏逻辑 (game.js)
JavaScript文件是游戏的核心,实现了所有游戏逻辑:
初始化和界面管理
function initGame() {
// 初始化游戏元素和事件监听器
}
function showStartScreen() {
// 显示开始界面
}
function returnToMainMenu() {
// 返回主菜单
}
这部分代码负责游戏的初始化和界面切换,确保游戏有一个完整的流程。
游戏主循环
function gameLoop(timestamp) {
if (!gameRunning) return;
updateGameState(timestamp);
requestAnimationFrame(gameLoop);
}
游戏主循环使用requestAnimationFrame实现,这是HTML5提供的一个优化动画性能的API,它会在浏览器下一次重绘之前调用指定的函数,使动画更加流畅。
游戏状态更新
function updateGameState(timestamp) {
// 生成敌机和精英敌机
// 发射子弹
// 更新位置
// 检测碰撞
}
这个函数负责更新游戏中所有元素的状态,包括生成敌机、移动敌机和子弹、检测碰撞等。
血量系统
function damagePlayer() {
playerHealth--;
updateHealthDisplay();
// 闪烁效果表示受伤
playerElement.classList.add('damaged');
setTimeout(() => {
playerElement.classList.remove('damaged');
}, 300);
// 检查是否游戏结束
if (playerHealth <= 0) {
createExplosion(playerX, playerElement.getBoundingClientRect().top - gameArea.getBoundingClientRect().top);
endGame();
}
}
血量系统为游戏增加了更多策略性,玩家和敌机都有血量属性,需要多次击中才能摧毁。同时,我们添加了受伤闪烁效果和血量显示,提升了游戏的视觉反馈。
碰撞检测
function checkCollisions() {
// 检测玩家与敌机的碰撞
// 检测子弹与敌机的碰撞
// 检测玩家与敌机子弹的碰撞
}
碰撞检测是游戏中最重要的部分之一,它决定了游戏规则的实现。我们使用矩形碰撞检测算法,通过比较元素的边界来判断是否发生碰撞。
玩家控制
function movePlayer(e) {
if (!gameRunning) return;
const gameAreaRect = gameArea.getBoundingClientRect();
playerX = e.clientX - gameAreaRect.left;
const playerY = e.clientY - gameAreaRect.top;
// 限制玩家飞机在游戏区域内
if (playerX < 20) playerX = 20;
if (playerX > gameAreaRect.width - 20) playerX = gameAreaRect.width - 20;
// 限制玩家飞机的垂直位置(保持在下半部分)
const minY = gameAreaRect.height * 0.5;
const maxY = gameAreaRect.height - 40;
let newY = playerY;
if (newY < minY) newY = minY;
if (newY > maxY) newY = maxY;
playerElement.style.left = `${playerX}px`;
playerElement.style.top = `${newY}px`;
playerElement.style.transform = 'translateX(-50%)';
}
这部分实现了玩家控制,支持鼠标和触摸屏操作,使游戏可以在不同设备上运行。玩家飞机可以在屏幕下半部分自由移动,增加了游戏的操作性和策略性。
敌机和子弹管理
function createEnemy() {
// 创建普通敌机
}
function createEliteEnemy() {
// 创建精英敌机
}
function fireBullet() {
// 玩家发射子弹
}
function fireEliteBullet(eliteEnemy) {
// 精英敌机发射子弹
}
这些函数负责创建和管理游戏中的敌机和子弹,包括它们的生成、移动和销毁。精英敌机有特殊的移动模式和攻击能力,增加了游戏的挑战性。
音频控制
// 初始化背景音乐
bgm = new Audio('assets/audio/bgm.mp3');
bgm.loop = true;
bgm.volume = 0.5;
我们使用HTML5 Audio API来实现背景音乐,在游戏开始时播放,结束时暂停。
4. 服务器 (server.js)
虽然这是一个前端游戏,但我们使用Express搭建了一个简单的服务器来提供静态文件服务,这使得游戏可以在本地运行,也为将来可能的扩展(如多人游戏、分数存储等)提供了基础。
const express = require('express');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;
// 提供静态文件服务
app.use(express.static(path.join(__dirname, 'public')));
// 获取本地IP地址
function getLocalIP() {
// 获取网络接口信息
// ...
}
// 启动服务器
app.listen(PORT, () => {
const localIP = getLocalIP();
console.log(`
========================================
🚀 飞机大战游戏服务已启动!
📂 本地访问: http://localhost:${PORT}
🌐 局域网访问: http://${localIP}:${PORT}
🎮 开始游戏吧!
========================================
`);
});
服务器还提供了局域网访问功能,自动检测本机IP地址并显示访问链接,方便在同一网络的其他设备上测试游戏。
技术难点与解决方案
在开发过程中,我遇到了一些技术难点,以下是我的解决方案:
1. 游戏性能优化
问题:当屏幕上有大量敌机和子弹时,游戏可能会出现卡顿。
解决方案:
- 使用
requestAnimationFrame代替setInterval来实现游戏循环 - 及时清除离开屏幕的敌机和子弹,减少DOM元素数量
- 使用CSS transform代替绝对定位来移动元素,利用GPU加速
- 优化碰撞检测算法,减少不必要的计算
2. 精英敌机的移动逻辑
问题:如何实现精英敌机的自由移动,使其看起来更有挑战性?
解决方案:
- 精英敌机从顶部生成,然后移动到上部区域
- 在到达特定高度后,减缓或停止垂直移动
- 水平方向上碰到边界时反弹
- 添加小幅度的随机上下浮动,增加不可预测性
// 更新精英敌机位置
elite.x += elite.dx;
elite.y += elite.dy;
// 水平边界检查和反弹
if (elite.x <= 0 || elite.x >= gameArea.offsetWidth - 40) {
elite.dx *= -1;
}
// 垂直位置限制在上部区域
if (elite.y >= gameArea.offsetHeight * 0.4) {
elite.dy = 0; // 停止向下移动
// 如果已经停止,可以添加小幅度上下浮动
if (Math.random() < 0.02) { // 2%的概率改变方向
elite.dy = (Math.random() - 0.5) * 1;
}
}
3. 血量系统实现
问题:如何实现一个直观的血量系统,并提供良好的视觉反馈?
解决方案:
- 为玩家和敌机添加血量属性
- 添加血量显示界面元素
- 实现受伤闪烁效果,使用CSS动画
- 低血量时改变血量显示颜色,提供警告
- 调整碰撞检测逻辑,支持多次碰撞
.damaged {
animation: damage-flash 0.2s 2;
}
@keyframes damage-flash {
0% { opacity: 1; }
50% { opacity: 0.3; }
100% { opacity: 1; }
}
4. 玩家飞机自由移动
问题:如何实现玩家飞机的自由移动,同时保持游戏平衡?
解决方案:
- 使用鼠标/触摸位置控制飞机位置
- 限制飞机活动范围在屏幕下半部分
- 调整子弹发射逻辑,使其从飞机当前位置发射
- 优化碰撞检测,适应飞机的自由移动
// 限制玩家飞机的垂直位置
const minY = gameAreaRect.height * 0.5; // 限制在下半部分
const maxY = gameAreaRect.height - 40; // 底部边界
let newY = playerY;
if (newY < minY) newY = minY;
if (newY > maxY) newY = maxY;
5. 响应式设计与触摸支持
问题:如何使游戏在不同设备上都有良好的体验?
解决方案:
- 使用相对单位和百分比布局,使游戏界面能够适应不同屏幕尺寸
- 添加触摸事件支持,使游戏可以在移动设备上操作
- 优化游戏元素大小和速度,使其在不同设备上都有合适的难度
- 提供局域网访问功能,方便在不同设备上测试
// 触摸控制
function movePlayerTouch(e) {
if (!gameRunning) return;
e.preventDefault();
const gameAreaRect = gameArea.getBoundingClientRect();
playerX = e.touches[0].clientX - gameAreaRect.left;
const playerY = e.touches[0].clientY - gameAreaRect.top;
// 限制玩家飞机在游戏区域内
// ...
}
未来计划
虽然这个游戏已经具备了丰富的功能,但还有很多可以改进和扩展的地方:
- 添加更多音效,如射击、爆炸和游戏结束音效
- 增加更多类型的敌机,每种敌机有不同的行为模式和血量
- 实现多种武器系统,玩家可以收集不同的武器升级
- 添加关卡系统,每个关卡有不同的难度和敌机组合
- 实现本地分数存储,记录玩家的最高分
- 添加移动端优化,提升在手机和平板上的游戏体验
- 实现多人游戏模式,支持局域网对战
总结
通过这个项目,我学习了很多关于Web游戏开发的知识,包括游戏循环、碰撞检测、动画效果、血量系统和用户交互等。虽然这只是一个简单的游戏,但它包含了游戏开发的许多基本概念和技术。
我希望这篇文章能对你有所帮助,无论你是想学习Web游戏开发,还是想了解如何组织一个前端项目。如果你有任何问题或建议,欢迎在评论区留言!
源码获取
👉 源码点击这里哦👈
6762

被折叠的 条评论
为什么被折叠?



