@shed/render2d-system v0.2.0
@shed/render2d-system
:hammer: @shed/ecs 的一个 2d渲染 系统,它会尽量把所有 Entity 打包在一起一次渲染,使其效率最高。
安装
npm install @shed/render2d-system或使用 yarn
yarn add @shed/render2d-system用法
同其他 System 一样, 首先要加入到 ecs 中
import { Render2DSystem, Render2DComponent } from "@shed/render2d-system";
this._ecs.addSystem(new Render2DSystem(this._ecs, this._ctx))默认情况下,Render2DSystem 会遍历渲染所有包含 transform 和 render2d 组件的 Entity。
例如下边代码会渲染出一个红色方块:
// 创建并添加一个新的 Entity
this._ecs.addNewEntity('redQuad',
{ type: 'render2d', visible: true, color: { r: 1, g: 0, b: 0, a: 1 },
{ type: 'transform', x: 0, y: 0, width: 100, height: 100, rotation: 0 },
);Component 部分
System 运行时会查找包含对应 Components 的 Entity,并执行相关逻辑。Entity Component System 的概念请参考 @shed/ecs 中相关说明。
在 @shed/ecs 中 component 只是纯粹的数据,所以是 pure object,类似 { type : 'mycomponent' } 就可以表示为一个组件
Render2DSystem 只会与以下两个组件打交道
transformcomponentrender2dcomponent
transform component
transform 组件用来表示物体的 位置,大小与旋转角度。
创建一个 transform component 只需
let comp = { type: 'transform', x: 0, y: 0, width: 100, height: 100, rotation: 0 }使用 TypeScript 的好处就是可以导入类型信息,如果手误打错,编辑器会提醒你
import { TransformComponent } from "@shed/render2d-system";
let comp: TransformComponent = ...;还提供了更简便方式创建一个 TransformComponent
import { createTransformComponent } from "@shed/render2d-system";
let comp = createTransformComponent(0,0,1,1,0); // x = 0, y = 0, width = 1, height = 1, rotation = 0不管用什么方法创建,总而言之类型是这样的
type TransformComponent = {
type: 'transform',
x: number, y: number,
width: number, height: number,
rotation: number; // 角度值
};render2d component
render2d component 通常表示一个图片,或一个色块,他们的类型如下
type Quad2D = {
type: "render2d";
visible: boolean;
color: {
r: number;
g: number;
b: number;
a: number;
};
}type Image2D = {
type: "render2d";
visible: boolean;
image: {
src: string;
region: {
l: number;
r: number;
t: number;
b: number;
};
repeat: boolean;
linear: boolean;
};
}可以直接使用,也可以泛型版本
let img: Render2DComponent<Image2D> = ...;分层渲染
WebGL 中有一个 DrawCall 的概念,他是影响性能的最重要的指标,@render2d-system 默认会尽量把所有精灵在一个 DrawCall 中渲染出来使其效率最高,这也是小游戏最理想的渲染方式。
但大多数时候需要将不同的物件,分层级渲染出来,例如背景图在最底层,然后敌人,然后子弹,最后放主角
const renderSystem = new Render2DSystem(this._ecs, this._ctx, this._ecs.state.assets, true);
renderSystem.addLayer(this._ecs.getGroup('bg', 'render2d', 'transform'));
renderSystem.addLayer(this._ecs.getGroup('enemy', 'render2d', 'transform'));
renderSystem.addLayer(this._ecs.getGroup('bullet', 'render2d', 'transform'));
renderSystem.addLayer(this._ecs.getGroup('player', 'render2d', 'transform'));这样分了4层,画4次,也才只有4个 DrawCall,效率还是非常高的。 这也就是说我们可以根据需要,尽量减少层数来优化效率。
Contributors
License
6 years ago