基于Electron开发的跨平台鸿蒙PC经典吃豆人游戏
本项目实现了一个功能完整的经典吃豆人游戏,结合了Electron框架的跨平台能力和现代Web技术的交互体验。游戏核心算法包括吃豆人移动系统、幽灵AI、碰撞检测等,通过精心设计的游戏状态管理和性能优化策略,提供了流畅的游戏体验。该实现不仅保留了经典吃豆人的游戏乐趣,还通过模块化设计和清晰的代码结构,为进一步扩展和定制提供了良好的基础。
项目概述
本项目是一个基于Electron开发的跨平台鸿蒙PC经典吃豆人(Pac-Man)游戏实现。游戏保持了经典吃豆人的核心玩法,同时利用Electron框架提供了跨平台的桌面应用体验。
技术栈
- 主框架: Electron.js
- 前端技术: HTML5 Canvas, JavaScript, CSS3
- 渲染引擎: Canvas 2D API
- 存储: localStorage (本地最高分存储)
- 构建工具: npm/yarn
核心算法实现
1. 游戏核心逻辑
// 游戏主循环
gameLoop(timestamp) {
// 计算时间差
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
// 更新游戏状态
updateGame(deltaTime);
// 绘制游戏画面
drawGame();
// 继续游戏循环
if (gameState === 'playing') {
gameLoopId = requestAnimationFrame(gameLoop);
}
}
游戏采用经典的游戏循环模式,通过requestAnimationFrame实现高效渲染,确保平滑的游戏体验。每帧执行两个核心步骤:更新游戏状态和渲染游戏画面。
2. 吃豆人移动与碰撞检测
// 更新吃豆人位置
function updatePacman(deltaTime) {
// 尝试转向
if (canMoveTo(pacman.x + pacman.nextDirection.x * pacman.speed,
pacman.y + pacman.nextDirection.y * pacman.speed)) {
pacman.direction = pacman.nextDirection;
}
// 移动吃豆人
if (canMoveTo(pacman.x + pacman.direction.x * pacman.speed,
pacman.y + pacman.direction.y * pacman.speed)) {
pacman.x += pacman.direction.x * pacman.speed;
pacman.y += pacman.direction.y * pacman.speed;
}
// 检查是否吃到食物
checkFood();
}
// 碰撞检测函数
function canMoveTo(x, y) {
// 转换为网格坐标
const gridX = Math.floor(x / TILE_SIZE);
const gridY = Math.floor(y / TILE_SIZE);
// 检查边界
if (gridX < 0 || gridX >= GRID_WIDTH || gridY < 0 || gridY >= GRID_HEIGHT) {
return false;
}
// 检查是否为墙
return map[gridY][gridX] !== 1;
}
吃豆人的移动系统采用了网格碰撞检测算法,结合方向预输入机制(nextDirection),实现了流畅的转向体验。碰撞检测通过将像素坐标转换为网格坐标,与地图数据进行比对来判断是否可以移动。
3. 幽灵AI系统
// 幽灵移动更新
function updateGhosts(deltaTime) {
ghosts.forEach(ghost => {
// 根据当前模式选择目标
if (ghost.mode === 'frightened') {
// 恐惧模式下随机移动
// ...
} else if (ghost.mode === 'scatter') {
// 分散模式,前往预设角落
// ...
} else if (ghost.mode === 'chase') {
// 追击模式,根据不同幽灵设定不同目标
setChaseTarget(ghost);
}
// 改变方向
changeGhostDirection(ghost);
// 移动
if (canMoveTo(ghost.x + ghost.direction.x * ghost.speed,
ghost.y + ghost.direction.y * ghost.speed)) {
ghost.x += ghost.direction.x * ghost.speed;
ghost.y += ghost.direction.y * ghost.speed;
}
});
// 检查与吃豆人的碰撞
checkCollisions();
}
幽灵AI系统是游戏的核心特色之一,实现了经典吃豆人中四种不同幽灵的行为模式:
- Blinky(红色):直接追击吃豆人当前位置
- Pinky(粉色):追击吃豆人前方4格的位置
- Inky(青色):基于Blinky和吃豆人的相对位置计算目标
- Clyde(橙色):接近时会转向分散模式
每个幽灵都有三种主要行为模式:
- Scatter Mode:前往地图角落
- Chase Mode:追击吃豆人
- Frightened Mode:被能量球击中后随机移动,可被吃掉
4. 地图系统
// 地图数据表示
const map = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
// ... 更多地图数据
];
// 地图渲染函数
function drawMap() {
for (let y = 0; y < GRID_HEIGHT; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
const tile = map[y][x];
const pixelX = x * TILE_SIZE;
const pixelY = y * TILE_SIZE;
// 绘制墙
if (tile === 1) {
ctx.fillStyle = '#0000FF';
ctx.fillRect(pixelX, pixelY, TILE_SIZE, TILE_SIZE);
}
// 绘制食物
else if (tile === 2) {
ctx.fillStyle = '#FFFF00';
ctx.beginPath();
ctx.arc(pixelX + TILE_SIZE/2, pixelY + TILE_SIZE/2, 2, 0, Math.PI * 2);
ctx.fill();
}
// 绘制能量球
else if (tile === 3) {
ctx.fillStyle = '#FFFF00';
ctx.beginPath();
ctx.arc(pixelX + TILE_SIZE/2, pixelY + TILE_SIZE/2, 6, 0, Math.PI * 2);
ctx.fill();
}
}
}
}
地图系统使用二维数组表示,支持多种元素类型:
- 0: 空白
- 1: 墙
- 2: 普通食物
- 3: 能量球
渲染时通过Canvas API将二维数组转换为视觉元素,实现了高效的地图绘制。
5. 动画系统
// 更新吃豆人嘴部动画
function updatePacmanMouth(deltaTime) {
pacman.mouthTimer += deltaTime;
if (pacman.mouthTimer > 200) { // 200ms切换一次
pacman.mouthOpen = !pacman.mouthOpen;
pacman.mouthTimer = 0;
}
}
// 绘制吃豆人
function drawPacman() {
ctx.fillStyle = '#FFFF00';
ctx.beginPath();
// 根据嘴部状态和方向绘制扇形
if (pacman.mouthOpen) {
// 绘制张嘴状态
// ...
} else {
// 绘制闭嘴状态
// ...
}
ctx.fill();
}
游戏实现了流畅的动画系统,包括:
- 吃豆人的嘴部开合动画
- 幽灵的闪烁效果(恐惧模式)
- 过渡动画(如幽灵被吃掉后的眼睛返回效果)
游戏状态管理
// 游戏状态枚举
const GAME_STATUS = {
READY: 'ready',
PLAYING: 'playing',
PAUSED: 'paused',
GAME_OVER: 'game_over',
LEVEL_COMPLETE: 'level_complete'
};
// 游戏状态管理变量
let gameState = 'idle'; // idle, playing, paused, gameOver, levelComplete
let score = 0;
let lives = 3;
let level = 1;
let highScore = localStorage.getItem('pacman-high-score') || 0;
游戏采用状态机模式管理整体流程,包括以下核心状态:
- idle: 游戏初始状态
- playing: 游戏进行中
- paused: 游戏暂停
- gameOver: 游戏结束
- levelComplete: 关卡完成
状态转换由各种游戏事件触发,如按键操作、碰撞检测结果等。
分数与关卡系统
// 分数计算函数
function checkFood() {
const gridX = Math.floor(pacman.x / TILE_SIZE);
const gridY = Math.floor(pacman.y / TILE_SIZE);
// 吃到普通食物
if (map[gridY][gridX] === 2) {
score += 10;
map[gridY][gridX] = 0;
dotsRemaining--;
}
// 吃到能量球
else if (map[gridY][gridX] === 3) {
score += 50;
map[gridY][gridX] = 0;
powerPelletsRemaining--;
// 激活恐惧模式
activateFrightenedMode();
}
// 更新显示
updateDisplay();
// 检查关卡完成
checkLevelComplete();
}
// 关卡完成检查
function checkLevelComplete() {
if (dotsRemaining === 0) {
levelComplete();
}
}
// 进入下一关
function nextLevel() {
level++;
resetMap();
resetGhosts();
// 提高难度(增加幽灵速度)
ghosts.forEach(ghost => {
ghost.speed = Math.min(ghost.speed + 0.2, 2.5);
});
// 重置游戏状态
gameState = 'playing';
levelCompleteModal.style.display = 'none';
startGameLoop();
}
分数系统根据吃到的不同食物类型增加不同分数:
- 普通食物: 10分
- 能量球: 50分
- 恐惧模式下吃幽灵: 200, 400, 800, 1600分(累进)
关卡系统支持多关卡游戏,每完成一个关卡会重置地图并增加游戏难度(提高幽灵速度)。
Electron应用架构
1. 主进程实现
// main.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
title: '吃豆人游戏',
webPreferences: {
preload: path.join(__dirname, 'src', 'preload.js'),
nodeIntegration: true,
contextIsolation: false
}
});
mainWindow.loadFile(path.join(__dirname, 'src', 'index.html'));
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
2. 预加载脚本
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
// 游戏常量定义
const PACMAN_CONSTANTS = {
DIRECTIONS: { /* ... */ },
GAME_STATUS: { /* ... */ },
ELEMENT_TYPES: { /* ... */ },
GHOST_STATES: { /* ... */ },
GHOST_COLORS: { /* ... */ },
GAME_CONFIG: { /* ... */ }
};
// 暴露API给渲染进程
contextBridge.exposeInMainWorld('pacmanGame', {
game: { /* ... */ },
window: { /* ... */ },
dialog: { /* ... */ },
constants: PACMAN_CONSTANTS
});
应用遵循Electron的多进程架构:
- 主进程(main.js):负责创建和管理浏览器窗口,处理应用生命周期
- 预加载脚本(preload.js):在渲染器进程加载前执行,提供安全的IPC通信机制
- 渲染进程(renderer.js):运行在浏览器窗口中,负责游戏逻辑和UI渲染
性能优化策略
1. 高效渲染优化
- 局部渲染:通过只重绘变化的区域减少Canvas绘制操作
- requestAnimationFrame:利用浏览器渲染时机优化动画性能
- 对象池模式:复用游戏对象减少内存分配
2. 算法优化
- 网格碰撞检测:使用整数坐标系统加速碰撞计算
- 空间分区:通过网格划分减少碰撞检测次数
- 方向预计算:提前计算幽灵可能的移动方向
3. 资源管理
- 本地存储:使用localStorage保存高分记录
- 懒加载:按需加载游戏资源
- 内存优化:及时释放不再使用的对象和引用
错误处理机制
// 错误处理函数
function handleError(error, context) {
console.error(`[${context}] Error:`, error);
// 记录错误信息
logError(error, context);
// 根据错误类型进行恢复
switch(error.type) {
case 'game_state':
// 重置游戏状态
resetGame();
break;
case 'rendering':
// 尝试重新渲染
drawGame();
break;
default:
// 显示用户友好的错误消息
showErrorMessage('游戏发生错误,正在恢复...');
}
}
// 监听未捕获异常
window.addEventListener('error', (e) => {
handleError(e.error, 'global');
e.preventDefault();
});
游戏实现了完善的错误处理机制:
- 全局错误监听:捕获未处理的JavaScript异常
- 游戏逻辑错误恢复:检测并纠正游戏状态异常
- 资源加载失败处理:优雅降级处理资源加载问题
- 用户友好的错误提示:避免技术错误直接暴露给用户
运行与开发
安装依赖
npm install
开发模式运行
npm start
构建应用
# 构建Windows版本
npm run build:win
# 构建macOS版本
npm run build:mac
# 构建Linux版本
npm run build:linux
鸿蒙适配后结构(需整合到 Electron 鸿蒙项目模板中):
ohos_hap/
├── electron/
│ ├── libs/
│ │ └── arm64-v8a/ # 鸿蒙核心库文件
│ │ ├── libelectron.so
│ │ ├── libadapter.so
│ │ ├── libffmpeg.so
│ │ └── libc++_shared.so
├── web_engine/
│ └── src/
│ └── main/
│ └── resources/
│ └── resfile/
│ └── resources/
│ └── app/ # 放置electron应用代码
│ ├── main.js
│ ├── package.json
│ └── src/
└── module.json5 # 鸿蒙应用配置文件
鸿蒙PC适配改造指南
1. 环境准备
-
系统要求:Windows 10/11、8GB RAM以上、20GB可用空间
-
工具安装:
DevEco Studio 5.0+(安装鸿蒙SDK API 20+) -
Node.js 18.x+
2. 获取Electron鸿蒙编译产物
-
下载Electron 34+版本的Release包(.zip格式)
-
解压到项目目录,确认
electron/libs/arm64-v8a/下包含核心.so库
3. 部署应用代码
将Electron应用代码按以下目录结构放置:
web_engine/src/main/resources/resfile/resources/app/
├── main.js
├── package.json
└── src/
├── index.html
├── preload.js
├── renderer.js
└── style.css
4. 配置与运行
-
打开项目:在DevEco Studio中打开ohos_hap目录
-
配置签名:
进入File → Project Structure → Signing Configs -
自动生成调试签名或导入已有签名
-
连接设备:
启用鸿蒙设备开发者模式和USB调试 -
通过USB Type-C连接电脑
-
编译运行:点击Run按钮或按Shift+F10
5. 验证检查项
-
✅ 应用窗口正常显示
-
✅ 窗口大小可调整,响应式布局生效
-
✅ 控制台无"SysCap不匹配"或"找不到.so文件"错误
-
✅ 动画效果正常播放
跨平台兼容性
| 平台 | 适配策略 | 特殊处理 |
|---|---|---|
| Windows | 标准Electron运行 | 无特殊配置 |
| macOS | 标准Electron运行 | 保留dock图标激活逻辑 |
| Linux | 标准Electron运行 | 确保系统依赖库完整 |
| 鸿蒙PC | 通过Electron鸿蒙适配层 | 禁用硬件加速,使用特定目录结构 |
鸿蒙开发调试技巧
1. 日志查看
在DevEco Studio的Log面板中过滤"Electron"关键词,查看应用运行日志和错误信息。
2. 常见问题解决
-
"SysCap不匹配"错误:检查module.json5中的reqSysCapabilities,只保留必要系统能力
-
"找不到.so文件"错误:确认arm64-v8a目录下四个核心库文件完整
-
窗口不显示:在main.js中添加app.disableHardwareAcceleration()
-
动画卡顿:简化CSS动画效果,减少重绘频率
结语
本项目实现了一个功能完整的经典吃豆人游戏,结合了Electron框架的跨平台能力和现代Web技术的交互体验。游戏核心算法包括吃豆人移动系统、幽灵AI、碰撞检测等,通过精心设计的游戏状态管理和性能优化策略,提供了流畅的游戏体验。
该实现不仅保留了经典吃豆人的游戏乐趣,还通过模块化设计和清晰的代码结构,为进一步扩展和定制提供了良好的基础。
更多推荐



所有评论(0)