You've already forked Pandona-Engine
初始化提交
This commit is contained in:
889
README.md
889
README.md
@@ -1,20 +1,107 @@
|
||||
# DOM 渲染引擎
|
||||
# Pandona Engine (PE)
|
||||
|
||||
这个轻量级 JavaScript 渲染引擎使用 DOM 元素创建 2D 场景,支持精灵、容器、文本、HTML 和 SVG 等元素,提供简单直观的 API 进行场景管理。
|
||||
一个功能完整的 JavaScript 2D 游戏引擎,基于 DOM 实现,用于创建各种类型的 2D 游戏和动画。
|
||||
|
||||
## 功能特性
|
||||
## 编译时架构
|
||||
|
||||
- 🎭 创建可自定义尺寸的舞台容器
|
||||
- 🖼️ 支持加载和显示图像精灵
|
||||
- 📦 创建容器元素用于分组管理
|
||||
- ✏️ 文本元素创建和样式设置
|
||||
- 🌐 支持原生 HTML 内容嵌入
|
||||
- 🎨 SVG 矢量图形支持
|
||||
- 📍 精确控制元素位置和尺寸
|
||||
- 🎭 简单的事件绑定机制
|
||||
Pandona Engine 现在支持现代编译时架构,使用 Vite 作为构建工具,支持:
|
||||
- ES6 模块系统
|
||||
- Less CSS 预处理器
|
||||
- 代码压缩和优化
|
||||
- 开发服务器热重载
|
||||
- 场景化组织结构
|
||||
|
||||
## 简化版API (推荐)
|
||||
|
||||
为了让开发者更容易上手,Pandona Engine提供了简化版API,参考了PixiJS、Egret和Vue 3的设计理念,让代码更加简洁易读。
|
||||
|
||||
## 特性
|
||||
|
||||
- 🎮 **完整的游戏开发功能**:支持创建各种类型的2D游戏
|
||||
- 🌟 **模块化架构**:核心功能拆分为独立模块,易于扩展和维护
|
||||
- 🌟 **插件系统**:支持自定义插件扩展引擎功能
|
||||
- 🎨 **多种元素类型**:支持精灵、容器、文本、HTML 和 SVG 元素
|
||||
- 🌈 **高级动画系统**:内置补间动画、帧动画、动画序列和时间轴
|
||||
- 🎵 **音频管理**:支持音效和背景音乐播放
|
||||
- 🌍 **场景管理**:支持多场景切换和过渡效果
|
||||
- 📡 **事件系统**:增强的事件总线,支持全局和局部事件
|
||||
- 🧹 **内存管理**:完善的资源清理机制
|
||||
- 🎯 **碰撞检测**:矩形碰撞检测系统
|
||||
- 🎮 **输入处理**:键盘和鼠标输入处理
|
||||
- 📱 **UI系统**:按钮、标签、图像、滑块等UI组件
|
||||
- 🎥 **摄像机系统**:支持跟随、缩放、旋转和震动效果
|
||||
- ✨ **粒子系统**:创建各种视觉效果
|
||||
- ⚙️ **组件系统**:基于组件的游戏对象系统
|
||||
- 📈 **游戏循环**:固定时间步长的游戏循环
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone <repository-url>
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 开发模式
|
||||
|
||||
```bash
|
||||
# 启动开发服务器
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 构建项目
|
||||
|
||||
```bash
|
||||
# 构建生产版本
|
||||
npm run build
|
||||
|
||||
# 预览构建结果
|
||||
npm run preview
|
||||
```
|
||||
|
||||
### 简化版API用法 (推荐)
|
||||
|
||||
```javascript
|
||||
// 创建引擎实例
|
||||
const game = PE.createEngine('#game-container', {
|
||||
width: 800,
|
||||
height: 600,
|
||||
background: '#f0f0f0'
|
||||
});
|
||||
|
||||
// 加载资源
|
||||
game.assets.load('character.png')
|
||||
.then(img => {
|
||||
// 创建精灵 (链式调用)
|
||||
const player = game.create('sprite', {
|
||||
image: img,
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 50,
|
||||
height: 50
|
||||
}).position(100, 100)
|
||||
.size(50, 50)
|
||||
.on('click', () => {
|
||||
player.position(200, 150);
|
||||
});
|
||||
|
||||
// 添加到舞台
|
||||
game.stage.add(player);
|
||||
|
||||
// 创建移动动画
|
||||
game.animate(player, { x: 300, y: 200 }, 1000, {
|
||||
easing: 'easeInOutQuad',
|
||||
onComplete: () => {
|
||||
console.log('动画完成!');
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 基本用法
|
||||
|
||||
```javascript
|
||||
@@ -26,10 +113,10 @@ const game = new Engine('#game-container', {
|
||||
});
|
||||
|
||||
// 加载资源
|
||||
game.Load('character.png')
|
||||
game.load('character.png')
|
||||
.then(img => {
|
||||
// 创建精灵
|
||||
const player = game.CreateSprite(img, 100, 100, 50, 50);
|
||||
const player = game.createSprite(img, 100, 100, 50, 50);
|
||||
|
||||
// 添加到舞台
|
||||
game.stage.add(player);
|
||||
@@ -41,60 +128,465 @@ game.Load('character.png')
|
||||
});
|
||||
```
|
||||
|
||||
### 使用动画系统
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 创建移动动画
|
||||
game.animate(player, { x: 300, y: 200 }, 1000, {
|
||||
easing: 'easeInOutQuad',
|
||||
onUpdate: (progress) => {
|
||||
console.log(`动画进度: ${Math.round(progress * 100)}%`);
|
||||
},
|
||||
onComplete: () => {
|
||||
console.log('动画完成!');
|
||||
}
|
||||
});
|
||||
|
||||
// 创建帧动画
|
||||
const walkAnimation = game.animate.frame(player, [
|
||||
'walk1.png', 'walk2.png', 'walk3.png'
|
||||
], 10, { loop: true });
|
||||
|
||||
// 播放帧动画
|
||||
walkAnimation.play();
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 创建移动动画
|
||||
game.tween(player, 1000, 'easeInOutQuad')
|
||||
.to({ x: 300, y: 200 })
|
||||
.onUpdate(progress => {
|
||||
console.log(`动画进度: ${Math.round(progress * 100)}%`);
|
||||
})
|
||||
.onComplete(() => {
|
||||
console.log('动画完成!');
|
||||
})
|
||||
.start();
|
||||
```
|
||||
|
||||
### 使用场景管理
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 创建场景
|
||||
const menuScene = game.scene.create('menu');
|
||||
const gameScene = game.scene.create('game');
|
||||
|
||||
// 切换场景
|
||||
game.scene.switch('menu');
|
||||
|
||||
// 带过渡效果的场景切换
|
||||
game.scene.switch('game', {
|
||||
transition: {
|
||||
type: 'fade',
|
||||
duration: 1000
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 创建场景
|
||||
const menuScene = game.createScene('menu');
|
||||
const gameScene = game.createScene('game');
|
||||
|
||||
// 切换场景
|
||||
game.switchScene('menu');
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
### 引擎初始化
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
const engine = PE.createEngine(elementSelector, options);
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
const engine = new Engine(elementSelector, options);
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 默认值 | 说明 |
|
||||
|------|------|---------|------|
|
||||
| `elementSelector` | string | `'body'` | 挂载舞台的 DOM 选择器 |
|
||||
| `options.width` | number | 800 | 舞台宽度(px) |
|
||||
| `options.height` | number | 600 | 舞台高度(px) |
|
||||
| `options.background` | string | `'transparent'` | 舞台背景色 |
|
||||
| `options.fps` | number | 60 | 游戏循环帧率 |
|
||||
|
||||
### 插件系统
|
||||
```javascript
|
||||
// 安装插件
|
||||
engine.use(YourPlugin, options);
|
||||
```
|
||||
|
||||
### 资源加载
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
engine.Load(imageUrl)
|
||||
// 加载单个资源
|
||||
game.assets.load(imageUrl)
|
||||
.then(img => { /* 使用图像 */ })
|
||||
.catch(error => { /* 处理错误 */ });
|
||||
|
||||
// 批量加载资源
|
||||
game.assets.load([imageUrl1, imageUrl2, imageUrl3])
|
||||
.then(resources => { /* 使用资源 */ })
|
||||
.catch(error => { /* 处理错误 */ });
|
||||
|
||||
// 预加载资源并显示进度
|
||||
game.assets.preload([
|
||||
'image1.png',
|
||||
'image2.png',
|
||||
'sound1.wav'
|
||||
], (progress, loaded, total) => {
|
||||
console.log(`加载进度: ${Math.round(progress * 100)}% (${loaded}/${total})`);
|
||||
}).then(() => {
|
||||
console.log('所有资源加载完成!');
|
||||
});
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
engine.load(imageUrl)
|
||||
.then(img => { /* 使用图像 */ })
|
||||
.catch(error => { /* 处理错误 */ });
|
||||
```
|
||||
|
||||
### 音频管理
|
||||
```javascript
|
||||
// 加载音效
|
||||
engine.loadSound('shoot', 'sounds/shoot.wav');
|
||||
|
||||
// 播放音效
|
||||
engine.playSound('shoot');
|
||||
|
||||
// 加载音乐
|
||||
engine.loadMusic('background', 'sounds/bg.mp3');
|
||||
|
||||
// 播放音乐
|
||||
engine.playMusic('background', { loop: true });
|
||||
```
|
||||
|
||||
### 动画系统
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 创建补间动画
|
||||
game.animate(target, { x: 100, y: 200 }, 1000, {
|
||||
easing: 'easeInOutQuad',
|
||||
delay: 500,
|
||||
repeat: 2,
|
||||
yoyo: true,
|
||||
onUpdate: (progress) => { /* 更新回调 */ },
|
||||
onComplete: () => { /* 完成回调 */ }
|
||||
});
|
||||
|
||||
// 创建并行动画
|
||||
const parallelAnimation = game.animate.parallel([
|
||||
game.animate(target1, { x: 100 }, 1000),
|
||||
game.animate(target2, { y: 200 }, 1000)
|
||||
]);
|
||||
|
||||
parallelAnimation.play();
|
||||
|
||||
// 创建链式动画
|
||||
const chainAnimation = game.animate.chain([
|
||||
game.animate(target, { x: 100 }, 1000),
|
||||
game.animate(target, { y: 200 }, 1000)
|
||||
]);
|
||||
|
||||
chainAnimation.play();
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 创建补间动画
|
||||
engine.tween(target, duration, easing)
|
||||
.to({ x: 100, y: 200 })
|
||||
.onUpdate(callback)
|
||||
.onComplete(callback)
|
||||
.start();
|
||||
|
||||
// 创建帧动画
|
||||
engine.createFrameAnimation('walk', [
|
||||
'walk1.png', 'walk2.png', 'walk3.png'
|
||||
], 10);
|
||||
|
||||
// 播放帧动画
|
||||
engine.playFrameAnimation(sprite, 'walk', true);
|
||||
```
|
||||
|
||||
支持的缓动函数:
|
||||
- `linear`
|
||||
- `easeInQuad`
|
||||
- `easeOutQuad`
|
||||
- `easeInOutQuad`
|
||||
- `easeInCubic`
|
||||
- `easeOutCubic`
|
||||
- `easeInOutCubic`
|
||||
- `easeInQuart`
|
||||
- `easeOutQuart`
|
||||
- `easeInOutQuart`
|
||||
- `easeInQuint`
|
||||
- `easeOutQuint`
|
||||
- `easeInOutQuint`
|
||||
- `easeInSine`
|
||||
- `easeOutSine`
|
||||
- `easeInOutSine`
|
||||
- `easeInExpo`
|
||||
- `easeOutExpo`
|
||||
- `easeInOutExpo`
|
||||
- `easeInCirc`
|
||||
- `easeOutCirc`
|
||||
- `easeInOutCirc`
|
||||
- `easeInBack`
|
||||
- `easeOutBack`
|
||||
- `easeInOutBack`
|
||||
- `easeInElastic`
|
||||
- `easeOutElastic`
|
||||
- `easeInOutElastic`
|
||||
- `easeInBounce`
|
||||
- `easeOutBounce`
|
||||
- `easeInOutBounce`
|
||||
|
||||
### 场景管理
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 创建场景
|
||||
const scene = engine.scene.create(name);
|
||||
|
||||
// 切换场景
|
||||
engine.scene.switch(name);
|
||||
|
||||
// 场景过渡效果
|
||||
engine.scene.transition.fade('game', 1000);
|
||||
engine.scene.transition.slide('game', 'left', 500);
|
||||
engine.scene.transition.zoom('game', 1000);
|
||||
engine.scene.transition.flip('game', 1000);
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 创建场景
|
||||
const scene = engine.createScene(name);
|
||||
|
||||
// 切换场景
|
||||
engine.switchScene(name);
|
||||
|
||||
// 场景过渡效果
|
||||
engine.transitionFade('game', 1000);
|
||||
engine.transitionSlide('game', 'left', 500);
|
||||
```
|
||||
|
||||
### 摄像机系统
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 设置摄像机位置 (带动画)
|
||||
engine.camera.move(400, 300, 1000).then(() => {
|
||||
console.log('摄像机移动完成');
|
||||
});
|
||||
|
||||
// 跟随目标
|
||||
engine.camera.follow(player, { x: 0, y: 100 });
|
||||
|
||||
// 摄像机缩放 (带动画)
|
||||
engine.camera.zoom(1.5, 1000).then(() => {
|
||||
console.log('摄像机缩放完成');
|
||||
});
|
||||
|
||||
// 摄像机旋转 (带动画)
|
||||
engine.camera.rotate(PE.PI, 1000).then(() => {
|
||||
console.log('摄像机旋转完成');
|
||||
});
|
||||
|
||||
// 屏幕震动
|
||||
engine.camera.shake(10, 500);
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 设置摄像机位置
|
||||
engine.setCameraPosition(400, 300);
|
||||
|
||||
// 跟随目标
|
||||
engine.follow(player, { x: 0, y: 100 });
|
||||
|
||||
// 摄像机缩放
|
||||
engine.setCameraZoom(1.5);
|
||||
|
||||
// 屏幕震动
|
||||
engine.shakeCamera(10, 500);
|
||||
```
|
||||
|
||||
### UI系统
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 创建按钮 (链式调用)
|
||||
const button = engine.ui.create('button', {
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 200,
|
||||
height: 50,
|
||||
text: '点击我'
|
||||
}).position(100, 100)
|
||||
.size(200, 50)
|
||||
.background('#007acc')
|
||||
.hover('#005a99')
|
||||
.pressed('#003d66')
|
||||
.color('#ffffff')
|
||||
.on('click', () => {
|
||||
console.log('按钮被点击了!');
|
||||
});
|
||||
|
||||
engine.ui.add(button);
|
||||
|
||||
// 创建标签 (链式调用)
|
||||
const label = engine.ui.create('label', {
|
||||
x: 100,
|
||||
y: 200,
|
||||
text: 'Hello World'
|
||||
}).position(100, 200)
|
||||
.text('Hello World')
|
||||
.font('20px Arial')
|
||||
.color('#ffffff');
|
||||
|
||||
engine.ui.add(label);
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 创建按钮
|
||||
const button = new UIButton(100, 100, 200, 50, '点击我');
|
||||
button.on('click', () => {
|
||||
console.log('按钮被点击了!');
|
||||
});
|
||||
engine.addUIElement(button);
|
||||
|
||||
// 创建标签
|
||||
const label = new UILabel(100, 200, 'Hello World');
|
||||
engine.addUIElement(label);
|
||||
```
|
||||
|
||||
### 创建元素
|
||||
|
||||
#### 精灵 (CreateSprite)
|
||||
#### 简化版API
|
||||
```javascript
|
||||
const sprite = engine.CreateSprite(imgElement, x, y, width, height);
|
||||
// 创建精灵 (链式调用)
|
||||
const sprite = engine.create('sprite', {
|
||||
image: imgElement,
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 50,
|
||||
height: 50
|
||||
}).position(100, 100)
|
||||
.size(50, 50)
|
||||
.alpha(0.8)
|
||||
.scale(1.2)
|
||||
.rotate(PE.PI_2)
|
||||
.on('click', () => {
|
||||
console.log('精灵被点击了!');
|
||||
});
|
||||
|
||||
// 创建容器 (链式调用)
|
||||
const container = game.create('box', {
|
||||
x: 50,
|
||||
y: 50,
|
||||
width: 200,
|
||||
height: 200
|
||||
}).position(50, 50)
|
||||
.size(200, 200)
|
||||
.addChild(sprite);
|
||||
|
||||
// 创建文本 (链式调用)
|
||||
const text = game.create('text', {
|
||||
text: 'Hello World',
|
||||
x: 100,
|
||||
y: 100
|
||||
}).position(100, 100)
|
||||
.text('Hello World')
|
||||
.font('bold 24px Arial')
|
||||
.color('#ff0000')
|
||||
.align('center');
|
||||
|
||||
// 创建HTML元素 (链式调用)
|
||||
const html = game.create('html', {
|
||||
html: '<button>Click</button>',
|
||||
x: 300,
|
||||
y: 200
|
||||
}).position(300, 200)
|
||||
.html('<button>Click</button>');
|
||||
|
||||
// 创建SVG元素 (链式调用)
|
||||
const svg = game.create('svg', {
|
||||
x: 400,
|
||||
y: 300,
|
||||
width: 100,
|
||||
height: 100,
|
||||
content: '<circle cx="50" cy="50" r="40"/>'
|
||||
}).position(400, 300)
|
||||
.size(100, 100)
|
||||
.content('<circle cx="50" cy="50" r="40"/>');
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
|
||||
##### 精灵 (createSprite)
|
||||
```javascript
|
||||
const sprite = engine.createSprite(imgElement, x, y, width, height);
|
||||
```
|
||||
- 支持位置和尺寸控制
|
||||
- 支持事件绑定
|
||||
|
||||
#### 容器 (CreateBox)
|
||||
##### 容器 (createBox)
|
||||
```javascript
|
||||
const container = engine.CreateBox(x, y, width, height);
|
||||
const container = engine.createBox(x, y, width, height);
|
||||
```
|
||||
- 用于元素分组管理
|
||||
- 支持嵌套结构
|
||||
|
||||
#### 文本 (CreateText)
|
||||
##### 文本 (createText)
|
||||
```javascript
|
||||
const text = engine.CreateText('Hello', 50, 50);
|
||||
const text = engine.createText('Hello', 50, 50);
|
||||
text.setColor('#ff0000');
|
||||
text.setFont('bold 24px Arial');
|
||||
```
|
||||
|
||||
#### HTML 元素 (CreateHtml)
|
||||
##### HTML 元素 (createHtml)
|
||||
```javascript
|
||||
const html = engine.CreateHtml('<button>Click</button>', 300, 200);
|
||||
const html = engine.createHtml('<button>Click</button>', 300, 200);
|
||||
```
|
||||
|
||||
#### SVG 元素 (CreateSvg)
|
||||
##### SVG 元素 (createSvg)
|
||||
```javascript
|
||||
const svg = engine.CreateSvg(400, 300, 100, 100, '<circle cx="50" cy="50" r="40"/>');
|
||||
const svg = engine.createSvg(400, 300, 100, 100, '<circle cx="50" cy="50" r="40"/>');
|
||||
```
|
||||
|
||||
### 元素通用方法
|
||||
|
||||
#### 简化版API
|
||||
所有创建的元素支持以下链式调用方法:
|
||||
|
||||
| 方法 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| `position(x, y)` | 设置元素位置 | `sprite.position(150, 200)` |
|
||||
| `size(width, height)` | 设置元素尺寸 | `box.size(100, 80)` |
|
||||
| `alpha(value)` | 设置透明度 | `sprite.alpha(0.8)` |
|
||||
| `scale(x, y)` | 设置缩放 | `sprite.scale(1.2, 1.2)` |
|
||||
| `rotate(angle)` | 设置旋转 | `sprite.rotate(PE.PI_2)` |
|
||||
| `add(child)` | 添加子元素 | `container.add(sprite)` |
|
||||
| `remove(child)` | 移除子元素 | `container.remove(sprite)` |
|
||||
| `on(event, callback)` | 绑定事件 | `sprite.on('click', handleClick)` |
|
||||
| `visible(visible)` | 显示/隐藏元素 | `sprite.visible(false)` |
|
||||
|
||||
#### 基本用法
|
||||
所有创建的元素支持以下方法:
|
||||
|
||||
| 方法 | 说明 | 示例 |
|
||||
@@ -109,57 +601,342 @@ const svg = engine.CreateSvg(400, 300, 100, 100, '<circle cx="50" cy="50" r="40"
|
||||
| `hide()` | 隐藏元素 | `sprite.hide()` |
|
||||
| `show()` | 显示元素 | `sprite.show()` |
|
||||
|
||||
### 游戏对象系统
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 创建游戏对象 (链式调用)
|
||||
const player = engine.gameobject.create({
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 50,
|
||||
height: 50,
|
||||
name: 'player',
|
||||
components: {
|
||||
physics: PE.components.physics({
|
||||
velocityX: 100,
|
||||
velocityY: 0
|
||||
}),
|
||||
collider: PE.components.collider({
|
||||
width: 50,
|
||||
height: 50
|
||||
})
|
||||
},
|
||||
events: {
|
||||
update: (deltaTime) => {
|
||||
// 更新逻辑
|
||||
}
|
||||
}
|
||||
}).position(100, 100)
|
||||
.size(50, 50)
|
||||
.addComponent('animation', PE.components.animation())
|
||||
.on('update', (deltaTime) => {
|
||||
// 更新逻辑
|
||||
});
|
||||
|
||||
// 添加到引擎
|
||||
engine.addGameObject(player);
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 创建游戏对象
|
||||
const player = new GameObject(100, 100, 50, 50);
|
||||
|
||||
// 添加组件
|
||||
player.addComponent('physics', new PhysicsComponent({
|
||||
velocityX: 100,
|
||||
velocityY: 0
|
||||
}));
|
||||
|
||||
player.addComponent('collider', new ColliderComponent({
|
||||
width: 50,
|
||||
height: 50
|
||||
}));
|
||||
|
||||
// 添加到引擎
|
||||
engine.addGameObject(player);
|
||||
```
|
||||
|
||||
### 碰撞检测
|
||||
```javascript
|
||||
// 检查两个对象是否碰撞
|
||||
if (engine.checkCollision(player, enemy)) {
|
||||
console.log('发生碰撞!');
|
||||
}
|
||||
```
|
||||
|
||||
### 音频系统
|
||||
|
||||
#### 简化版API
|
||||
```javascript
|
||||
// 加载音频
|
||||
engine.sound.load('shoot', 'sounds/shoot.wav');
|
||||
engine.sound.load('background', 'sounds/bg.mp3', { type: 'music' });
|
||||
|
||||
// 播放音频
|
||||
engine.sound.play('shoot');
|
||||
engine.sound.play('background', { loop: true, type: 'music' });
|
||||
|
||||
// 控制音量
|
||||
engine.sound.volume(0.5, 'master'); // 主音量
|
||||
engine.sound.volume(0.8, 'sound'); // 音效音量
|
||||
engine.sound.volume(0.6, 'music'); // 音乐音量
|
||||
|
||||
// 停止音频
|
||||
engine.sound.stop('background', 'music');
|
||||
|
||||
// 暂停/恢复音频
|
||||
engine.sound.pause('background', 'music');
|
||||
engine.sound.resume('background', 'music');
|
||||
```
|
||||
|
||||
#### 基本用法
|
||||
```javascript
|
||||
// 加载音效
|
||||
engine.loadSound('shoot', 'sounds/shoot.wav');
|
||||
|
||||
// 播放音效
|
||||
engine.playSound('shoot');
|
||||
|
||||
// 加载音乐
|
||||
engine.loadMusic('background', 'sounds/bg.mp3');
|
||||
|
||||
// 播放音乐
|
||||
engine.playMusic('background', { loop: true });
|
||||
```
|
||||
|
||||
### 销毁引擎
|
||||
```javascript
|
||||
engine.Destroy();
|
||||
engine.destroy();
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
cssEngine/
|
||||
├── index.html # 主页面
|
||||
├── main.js # 应用入口文件
|
||||
├── vite.config.js # Vite配置文件
|
||||
├── package.json # 项目配置
|
||||
├── README.md # 项目说明文档
|
||||
├── public/ # 静态资源
|
||||
│ └── sprite.css # 精灵样式文件
|
||||
├── style/ # 全局样式
|
||||
│ └── base.less # 基础样式
|
||||
├── examples/ # 示例项目
|
||||
│ ├── spaceShooter.js # 太空射击游戏示例
|
||||
│ └── spaceShooter.html # 示例游戏HTML文件
|
||||
├── src/
|
||||
│ ├── core/ # 核心模块
|
||||
│ │ ├── Engine.js # 引擎主类
|
||||
│ │ └── SimplifiedEngine.js # 简化版引擎API
|
||||
│ ├── elements/ # 元素类
|
||||
│ │ ├── BaseElement.js
|
||||
│ │ ├── Sprite.js
|
||||
│ │ ├── Box.js
|
||||
│ │ ├── TextElement.js
|
||||
│ │ ├── HtmlElement.js
|
||||
│ │ ├── SvgElement.js
|
||||
│ │ ├── GameObject.js
|
||||
│ │ ├── Component.js
|
||||
│ │ ├── SimplifiedElements.js # 简化版元素API
|
||||
│ │ ├── SimplifiedGameObject.js # 简化版游戏对象API
|
||||
│ │ └── SimplifiedComponent.js # 简化版组件API
|
||||
│ ├── managers/ # 管理器
|
||||
│ │ ├── ResourceManager.js
|
||||
│ │ ├── SceneManager.js
|
||||
│ │ ├── AudioManager.js
|
||||
│ │ ├── TransitionManager.js
|
||||
│ │ ├── Camera.js
|
||||
│ │ ├── SimplifiedResourceManager.js # 简化版资源管理API
|
||||
│ │ ├── SimplifiedSceneManager.js # 简化版场景管理API
|
||||
│ │ ├── SimplifiedAudioManager.js # 简化版音频管理API
|
||||
│ │ └── SimplifiedCamera.js # 简化版摄像机API
|
||||
│ ├── animation/ # 动画系统
|
||||
│ │ ├── Tween.js
|
||||
│ │ ├── AnimationSystem.js
|
||||
│ │ ├── AnimationController.js
|
||||
│ │ └── SimplifiedAnimation.js # 简化版动画API
|
||||
│ ├── effects/ # 特效系统
|
||||
│ │ ├── ParticleSystem.js
|
||||
│ │ └── SimplifiedParticleSystem.js # 简化版粒子系统API
|
||||
│ ├── ui/ # UI系统
|
||||
│ │ ├── UI.js
|
||||
│ │ └── SimplifiedUI.js # 简化版UI系统API
|
||||
│ ├── utils/ # 工具类
|
||||
│ │ ├── EventBus.js
|
||||
│ │ └── SimplifiedEventBus.js # 简化版事件系统API
|
||||
│ └── scenes/ # 场景目录
|
||||
│ └── index/ # 主场景
|
||||
│ ├── index.js # 场景结构和逻辑
|
||||
│ └── index.less # 场景样式
|
||||
└── test/ # 测试文件
|
||||
└── ... # 各模块测试
|
||||
```
|
||||
|
||||
## 开发指南
|
||||
|
||||
### 编译时架构开发指南
|
||||
|
||||
Pandona Engine 现在支持现代编译时架构,使用 Vite 作为构建工具:
|
||||
|
||||
```bash
|
||||
# 启动开发服务器(热重载)
|
||||
npm run dev
|
||||
|
||||
# 构建生产版本
|
||||
npm run build
|
||||
|
||||
# 预览构建结果
|
||||
npm run preview
|
||||
```
|
||||
|
||||
### 场景化开发
|
||||
|
||||
使用场景化组织结构开发应用:
|
||||
|
||||
```
|
||||
src/scenes/
|
||||
├── index/ # 主场景
|
||||
│ ├── index.js # 场景结构和逻辑
|
||||
│ └── index.less # 场景样式
|
||||
└── other-scene/ # 其他场景
|
||||
├── index.js
|
||||
└── index.less
|
||||
```
|
||||
|
||||
### 简化版API开发指南
|
||||
|
||||
简化版API提供了更简洁的开发方式,推荐新项目使用:
|
||||
|
||||
### 创建游戏角色
|
||||
```javascript
|
||||
const game = new Engine('#game', {
|
||||
width: 1024,
|
||||
height: 768
|
||||
// 使用简化版API创建游戏
|
||||
const game = PE.createEngine('#game-container', {
|
||||
width: 800,
|
||||
height: 600,
|
||||
background: '#000022'
|
||||
});
|
||||
|
||||
game.Load('player.png').then(playerImg => {
|
||||
const player = game.CreateSprite(playerImg, 512, 384, 64, 64);
|
||||
|
||||
// 添加角色名标签
|
||||
const nameTag = game.CreateText('Player 1', 0, -20);
|
||||
nameTag.setColor('gold');
|
||||
nameTag.setFont('bold 14px sans-serif');
|
||||
|
||||
player.add(nameTag);
|
||||
game.stage.add(player);
|
||||
// 使用链式调用创建和配置元素
|
||||
const player = game.create('sprite', {
|
||||
image: playerImage,
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 50,
|
||||
height: 50
|
||||
}).position(100, 100)
|
||||
.size(50, 50)
|
||||
.on('click', () => {
|
||||
console.log('Player clicked!');
|
||||
});
|
||||
|
||||
// 添加到舞台
|
||||
game.stage.add(player);
|
||||
|
||||
// 创建动画
|
||||
game.animate(player, { x: 300, y: 200 }, 1000, {
|
||||
easing: 'easeInOutQuad',
|
||||
onComplete: () => {
|
||||
console.log('Animation completed!');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 创建 UI 面板
|
||||
### 扩展功能
|
||||
|
||||
可以通过插件系统扩展引擎功能:
|
||||
|
||||
```javascript
|
||||
const panel = game.CreateBox(50, 50, 200, 300);
|
||||
panel.setStyle('background: rgba(0,0,0,0.7); border-radius: 10px;');
|
||||
// 定义插件
|
||||
const MyPlugin = {
|
||||
name: 'MyPlugin',
|
||||
install(engine, options) {
|
||||
// 扩展引擎功能
|
||||
engine.myMethod = () => {
|
||||
console.log('This is my custom method');
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const title = game.CreateText('控制面板', 20, 20);
|
||||
title.setStyle('font-size: 20px; color: white;');
|
||||
|
||||
const button = game.CreateHtml(
|
||||
'<button style="padding: 8px 16px; background: blue; color: white;">开始</button>',
|
||||
50, 80
|
||||
);
|
||||
|
||||
panel.add(title);
|
||||
panel.add(button);
|
||||
game.stage.add(panel);
|
||||
// 使用插件
|
||||
engine.use(MyPlugin);
|
||||
```
|
||||
|
||||
### 自定义元素
|
||||
|
||||
可以通过继承 `BaseElement` 创建自定义元素:
|
||||
|
||||
```javascript
|
||||
import BaseElement from './src/elements/BaseElement.js';
|
||||
|
||||
class CustomElement extends BaseElement {
|
||||
constructor(x, y, width, height, engineId) {
|
||||
super('div', engineId);
|
||||
this.setPosition(x, y);
|
||||
this.setSize(width, height);
|
||||
// 添加自定义逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 游戏对象和组件
|
||||
|
||||
可以通过GameObject和Component系统创建复杂的游戏对象:
|
||||
|
||||
```javascript
|
||||
import { GameObject } from './src/elements/GameObject.js';
|
||||
import { PhysicsComponent, ColliderComponent } from './src/elements/Component.js';
|
||||
|
||||
class Player extends GameObject {
|
||||
constructor(x, y) {
|
||||
super(x, y, 50, 50);
|
||||
// 添加物理组件
|
||||
this.addComponent('physics', new PhysicsComponent({
|
||||
velocityX: 0,
|
||||
velocityY: 0,
|
||||
friction: 0.9
|
||||
}));
|
||||
|
||||
// 添加碰撞组件
|
||||
this.addComponent('collider', new ColliderComponent({
|
||||
width: 50,
|
||||
height: 50
|
||||
}));
|
||||
}
|
||||
|
||||
update(deltaTime) {
|
||||
super.update(deltaTime);
|
||||
// 自定义更新逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 示例游戏
|
||||
|
||||
项目包含一个完整的太空射击游戏示例,展示了引擎的各种功能:
|
||||
|
||||
1. 游戏对象系统
|
||||
2. 组件系统
|
||||
3. 碰撞检测
|
||||
4. 动画系统
|
||||
5. 音频管理
|
||||
6. 场景管理
|
||||
7. UI系统
|
||||
8. 摄像机系统
|
||||
9. 粒子效果
|
||||
10. 场景过渡效果
|
||||
|
||||
要运行示例游戏,请在浏览器中打开 `examples/spaceShooter.html`。
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 所有元素位置基于舞台左上角(0,0)计算
|
||||
2. 使用 `Destroy()` 方法会完全移除舞台并清理内存
|
||||
2. 使用 `destroy()` 方法会完全移除舞台并清理内存
|
||||
3. 图像元素自动添加 `user-drag: none` 防止拖动
|
||||
4. 舞台默认启用硬件加速 (`transform: translateZ(0)`)
|
||||
5. 每个引擎实例有唯一ID标识 (`data-engine-id`)
|
||||
6. 游戏循环基于requestAnimationFrame实现
|
||||
7. 坐标系统基于世界坐标和屏幕坐标的转换
|
||||
|
||||
这个轻量级引擎适合创建简单的 2D 界面和游戏原型,使用原生 DOM 操作,无需额外依赖。
|
||||
Pandona Engine是一个功能完整的2D游戏引擎,适合创建各种类型的2D游戏和动画,使用原生DOM操作,无需额外依赖。
|
||||
Reference in New Issue
Block a user