从零构建「雷霆战机」:一个完整的Canvas飞机大战游戏
项目概述
「雷霆战机」是一款基于 HTML5 Canvas 开发的移动端飞机大战游戏,采用原生 JavaScript 面向对象设计,无需任何第三方游戏引擎。项目包含完整的游戏逻辑、UI 界面、本地数据持久化和 PWA 支持。
项目结构:
Plane_game/ ├── index.html # 主页面,包含游戏画布和UI ├── js/ │ ├── Game.js # 游戏主控制器 │ ├── Player.js # 玩家战机类 │ ├── Enemy.js # 敌机类 │ ├── Bullet.js # 子弹类 │ └── main.js # 入口文件,处理登录和数据存储 ├── manifest.json # PWA 配置 ├── sw.js # Service Worker └── server.js # 本地开发服务器技术架构
核心类设计
整个游戏采用经典的面向对象架构,各个类职责清晰:
Game 类 - 游戏大脑
[Game.js]是整个游戏的核心控制器,负责:
- 游戏循环:使用
requestAnimationFrame实现流畅的 60fps 渲染 - 状态管理:控制游戏的开始、暂停、结束状态
- 对象管理:维护玩家、敌机、子弹、粒子等所有游戏对象
- 碰撞检测:实现基于 AABB 的碰撞算法
- 难度调节:根据分数动态调整敌机生成频率
gameLoop(){if(!this.gameRunning)return;constcurrentTime=performance.now();constdeltaTime=currentTime-this.lastTime;this.lastTime=currentTime;this.update(deltaTime);this.render();requestAnimationFrame(()=>this.gameLoop());}Player 类 - 玩家战机
[Player.js]封装了玩家的所有行为:
- 双发射击系统:按下空格键发射双发子弹
- 闪电技能:按 J 键释放三发闪电弹,带有 3 秒冷却
- 无敌机制:被击中后有 2 秒无敌时间,期间闪烁提示
- 火焰尾焰动画:使用正弦函数实现动态火焰效果
Enemy 类 - 敌机系统
[Enemy.js]设计了两种敌机类型:
| 类型 | 血量 | 速度 | 分数 | 移动模式 |
|---|---|---|---|---|
| 普通 | 1 | 2.5 | 100 | 直线/正弦/余弦 |
| 强化 | 3 | 1.5 | 300 | 直线/正弦/余弦 |
敌机采用三种不同的移动模式,增加游戏的随机性和挑战性。强化敌机还配有血条显示。
Bullet 类 - 子弹系统
[Bullet.js]支持三种子弹类型:
- 玩家子弹:青色双发子弹
- 敌机子弹:红色单发子弹
- 闪电技能:黄色闪电形状,带有分段动画效果
核心功能实现
碰撞检测
采用带 padding 的 AABB 碰撞算法,减少误判:
isColliding(obj1,obj2){constpadding=10;returnobj1.x-obj1.width/2+padding<obj2.x+obj2.width/2-padding&&obj1.x+obj1.width/2-padding>obj2.x-obj2.width/2+padding&&obj1.y-obj1.height/2+padding<obj2.y+obj2.height/2-padding&&obj1.y+obj1.height/2-padding>obj2.y-obj2.height/2+padding;}粒子爆炸效果
当敌机或玩家被摧毁时,生成粒子系统模拟爆炸效果:
createExplosion(x,y,type){constcolors=type==='enemy'?['#ff6600','#ff0000','#ffff00']:['#00ffff','#0088ff','#ffffff'];for(leti=0;i<15;i++){this.particles.push({x,y,vx:(Math.random()-0.5)*8,vy:(Math.random()-0.5)*8,size:Math.random()*4+2,color:colors[Math.floor(Math.random()*colors.length)],life:1});}}数据持久化
使用 IndexedDB 存储玩家信息和游戏分数,实现本地排行榜:
functioninitDatabase(){constrequest=indexedDB.open('ThunderFighterDB',1);request.onupgradeneeded=function(event){constdatabase=event.target.result;if(!database.objectStoreNames.contains('players')){constplayerStore=database.createObjectStore('players',{keyPath:'id',autoIncrement:true});playerStore.createIndex('name','name',{unique:false});}if(!database.objectStoreNames.contains('scores')){constscoreStore=database.createObjectStore('scores',{keyPath:'id',autoIncrement:true});scoreStore.createIndex('playerId','playerId',{unique:false});scoreStore.createIndex('score','score',{unique:false});}};}交互设计
多端适配
游戏同时支持键盘和触屏操作:
键盘控制:
- 方向键/WASD:移动战机
- 空格键:普通攻击
- J 键:闪电技能
触屏控制:
- 左右按钮:水平移动
- 普攻/闪电按钮:释放技能
- 屏幕触摸:直接移动战机位置
难度动态调整
游戏难度随分数增加而提升:
this.enemySpawnInterval=Math.max(500,1500-this.score*2);敌机生成间隔从 1500ms 逐渐缩短到 500ms,后期战斗更加激烈。
PWA 支持
项目完整支持 PWA 标准,可安装到手机桌面:
- manifest.json:配置应用名称、图标、启动方式等
- sw.js:缓存所有资源,支持离线运行
- 响应式设计:适配不同屏幕尺寸
// sw.js - 缓存策略constCACHE_NAME='thunder-fighter-v1';constASSETS=['/index.html','/js/main.js','/js/Game.js',...];self.addEventListener('install',(event)=>{event.waitUntil(caches.open(CACHE_NAME).then((cache)=>cache.addAll(ASSETS)));});运行方式
# 启动开发服务器nodeserver.js# 访问游戏# PC:http://localhost:8080# 手机:http://<你的IP>:8080总结
「雷霆战机」展示了如何使用纯前端技术构建一个完整的游戏应用。核心技术亮点包括:
- Canvas 2D 渲染:实现流畅的游戏画面和动画效果
- 面向对象设计:清晰的类职责划分和代码组织
- 本地数据存储:IndexedDB 实现持久化和排行榜
- PWA 特性:离线运行和桌面安装能力
- 多端适配:同时支持键盘和触屏操作
整个项目代码结构清晰,易于理解和扩展,是学习 Canvas 游戏开发的优秀案例。