Skip to content

Commit

Permalink
组件新增onInitialize(允许多参数)| 优化组件结构为SparseSet
Browse files Browse the repository at this point in the history
  • Loading branch information
esengine committed May 10, 2023
1 parent e222371 commit a90ab95
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 96 deletions.
33 changes: 24 additions & 9 deletions source/bin/gs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ declare module gs {
* 通过增加 _version 的值来表示组件已更新
*/
markUpdated(): void;
/**
* 当组件初始化的时候调用
* @param args
*/
onInitialize(...args: any[]): void;
/**
* 当组件被添加到实体上时执行
*/
Expand Down Expand Up @@ -97,7 +102,7 @@ declare module gs {
* @param componentType
* @returns
*/
addComponent<T extends Component>(componentType: new (entityId: number) => T): T;
addComponent<T extends Component>(componentType: new (entityId: number) => T, ...args: any[]): T;
/**
* 获取组件
* @param componentType
Expand Down Expand Up @@ -312,9 +317,7 @@ declare module gs {
* 组件管理器
*/
class ComponentManager<T extends Component> {
private data;
private entityToDataIndex;
private freeDataIndices;
private components;
private componentType;
private componentPool;
/**
Expand Down Expand Up @@ -344,11 +347,6 @@ declare module gs {
* @returns
*/
remove(entityId: number): void;
/**
* 分配数据索引
* @returns
*/
allocateDataIndex(): number;
}
}
declare module gs {
Expand Down Expand Up @@ -688,3 +686,20 @@ declare module gs {
choose<T>(array: T[]): T;
}
}
declare module gs {
/**
* SparseSet数据结构
*/
class SparseSet<T> {
private sparse;
private dense;
private items;
private count;
constructor();
add(index: number, item: T): void;
remove(index: number): void;
has(index: number): boolean;
get(index: number): T;
getCount(): number;
}
}
111 changes: 75 additions & 36 deletions source/bin/gs.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ var __read = (this && this.__read) || function (o, n) {
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
var gs;
(function (gs) {
var ObjectPool = /** @class */ (function () {
Expand Down Expand Up @@ -203,6 +207,16 @@ var gs;
Component.prototype.markUpdated = function () {
this._version++;
};
/**
* 当组件初始化的时候调用
* @param args
*/
Component.prototype.onInitialize = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
};
/**
* 当组件被添加到实体上时执行
*/
Expand Down Expand Up @@ -275,12 +289,16 @@ var gs;
* @returns
*/
Entity.prototype.addComponent = function (componentType) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var manager = this.componentManagers.get(componentType);
if (!manager) {
throw new Error("\u7EC4\u4EF6\u7C7B\u578B\u4E3A " + componentType.name + " \u7684\u7EC4\u4EF6\u7BA1\u7406\u5668\u672A\u627E\u5230.");
}
var component = manager.create(this.id);
component.onAdded();
component.onInitialize.apply(component, __spread(args));
if (this.entityManager.systemManager) {
this.entityManager.systemManager.notifyComponentAdded(this, component);
}
Expand Down Expand Up @@ -335,7 +353,6 @@ var gs;
}
var component = this.getComponent(componentType);
if (component) {
component.onRemoved();
if (this.entityManager.systemManager) {
this.entityManager.systemManager.notifyComponentRemoved(this, component);
}
Expand Down Expand Up @@ -672,14 +689,11 @@ var gs;
* const positionManager = new ComponentManager(PositionComponent);
*/
function ComponentManager(componentType) {
this.data = [];
this.entityToDataIndex = new Map();
this.freeDataIndices = [];
this.componentPool = [];
this.componentType = componentType;
this.components = new gs.SparseSet();
}
ComponentManager.prototype.create = function (entityId) {
var index = this.allocateDataIndex();
var component;
if (this.componentPool.length > 0) {
component = this.componentPool.pop();
Expand All @@ -688,8 +702,7 @@ var gs;
component = new this.componentType();
}
component.setEntityId(entityId);
this.data[index] = component;
this.entityToDataIndex.set(entityId, index);
this.components.add(entityId, component);
return component;
};
/**
Expand All @@ -698,49 +711,28 @@ var gs;
* @returns 组件数据
*/
ComponentManager.prototype.get = function (entityId) {
var dataIndex = this.entityToDataIndex.get(entityId);
if (dataIndex === undefined) {
return null;
}
if (!this.data[dataIndex]) {
this.data[dataIndex] = {};
}
return this.data[dataIndex];
return this.components.get(entityId);
};
/**
*
* @param entityId
* @returns
*/
ComponentManager.prototype.has = function (entityId) {
return this.entityToDataIndex.has(entityId);
return this.components.has(entityId);
};
/**
*
* @param entityId
* @returns
*/
ComponentManager.prototype.remove = function (entityId) {
var dataIndex = this.entityToDataIndex.get(entityId);
if (dataIndex === undefined) {
return;
}
this.entityToDataIndex.delete(entityId);
var component = this.data[dataIndex];
component.reset();
this.data[dataIndex] = null;
this.freeDataIndices.push(dataIndex);
this.componentPool.push(component); // 将组件回收到组件池中
};
/**
* 分配数据索引
* @returns
*/
ComponentManager.prototype.allocateDataIndex = function () {
if (this.freeDataIndices.length > 0) {
return this.freeDataIndices.pop();
var component = this.components.get(entityId);
if (component) {
component.reset();
this.componentPool.push(component); // 将组件回收到组件池中
}
return this.data.length;
this.components.remove(entityId);
};
return ComponentManager;
}());
Expand Down Expand Up @@ -1582,3 +1574,50 @@ var gs;
}());
gs.Random = Random;
})(gs || (gs = {}));
var gs;
(function (gs) {
/**
* SparseSet数据结构
*/
var SparseSet = /** @class */ (function () {
function SparseSet() {
this.sparse = [];
this.dense = [];
this.items = [];
this.count = 0;
}
SparseSet.prototype.add = function (index, item) {
if (index >= this.sparse.length) {
this.sparse.length = index + 1;
}
this.sparse[index] = this.count;
this.dense[this.count] = index;
this.items[this.count] = item;
this.count++;
};
SparseSet.prototype.remove = function (index) {
var denseIndex = this.sparse[index];
var lastIndex = this.count - 1;
var lastDense = this.dense[lastIndex];
var lastItem = this.items[lastIndex];
this.dense[denseIndex] = lastDense;
this.items[denseIndex] = lastItem;
this.sparse[lastDense] = denseIndex;
this.count--;
};
SparseSet.prototype.has = function (index) {
return this.sparse[index] < this.count && this.dense[this.sparse[index]] === index;
};
SparseSet.prototype.get = function (index) {
if (!this.has(index)) {
return null;
}
return this.items[this.sparse[index]];
};
SparseSet.prototype.getCount = function () {
return this.count;
};
return SparseSet;
}());
gs.SparseSet = SparseSet;
})(gs || (gs = {}));
2 changes: 1 addition & 1 deletion source/bin/gs.min.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions source/src/Core/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ module gs {
this._version++;
}

/**
* 当组件初始化的时候调用
* @param args
*/
onInitialize(...args: any[]) { }

/**
* 当组件被添加到实体上时执行
*/
Expand Down
5 changes: 2 additions & 3 deletions source/src/Core/Entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ module gs {
* @param componentType
* @returns
*/
public addComponent<T extends Component>(componentType: new (entityId: number) => T): T {
public addComponent<T extends Component>(componentType: new (entityId: number) => T, ...args: any[]): T {
const manager = this.componentManagers.get(componentType);
if (!manager) {
throw new Error(`组件类型为 ${componentType.name} 的组件管理器未找到.`);
}
const component = manager.create(this.id) as T;
component.onAdded();
component.onInitialize(...args);
if (this.entityManager.systemManager) {
this.entityManager.systemManager.notifyComponentAdded(this, component);
}
Expand Down Expand Up @@ -78,7 +78,6 @@ module gs {
}
const component = this.getComponent(componentType);
if (component) {
component.onRemoved();
if (this.entityManager.systemManager) {
this.entityManager.systemManager.notifyComponentRemoved(this, component);
}
Expand Down
49 changes: 10 additions & 39 deletions source/src/Manager/ComponentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ module gs {
* 组件管理器
*/
export class ComponentManager<T extends Component> {
private data: T[] = [];
private entityToDataIndex: Map<number, number> = new Map();
private freeDataIndices: number[] = [];
private components: SparseSet<T>;
private componentType: ComponentConstructor<T>;
private componentPool: T[] = [];

Expand All @@ -22,10 +20,10 @@ module gs {
*/
constructor(componentType: ComponentConstructor<T>) {
this.componentType = componentType;
this.components = new SparseSet<T>();
}

public create(entityId: number): T {
const index = this.allocateDataIndex();
let component: T;
if (this.componentPool.length > 0) {
component = this.componentPool.pop();
Expand All @@ -34,8 +32,7 @@ module gs {
}
component.setEntityId(entityId);

this.data[index] = component;
this.entityToDataIndex.set(entityId, index);
this.components.add(entityId, component);
return component;
}

Expand All @@ -45,16 +42,7 @@ module gs {
* @returns 组件数据
*/
public get(entityId: number): T | null {
const dataIndex = this.entityToDataIndex.get(entityId);
if (dataIndex === undefined) {
return null;
}

if (!this.data[dataIndex]) {
this.data[dataIndex] = {} as T;
}

return this.data[dataIndex];
return this.components.get(entityId);
}

/**
Expand All @@ -63,7 +51,7 @@ module gs {
* @returns
*/
public has(entityId: number): boolean {
return this.entityToDataIndex.has(entityId);
return this.components.has(entityId);
}

/**
Expand All @@ -72,29 +60,12 @@ module gs {
* @returns
*/
public remove(entityId: number): void {
const dataIndex = this.entityToDataIndex.get(entityId);
if (dataIndex === undefined) {
return;
}
this.entityToDataIndex.delete(entityId);

const component = this.data[dataIndex];
component.reset();

this.data[dataIndex] = null;
this.freeDataIndices.push(dataIndex);
this.componentPool.push(component); // 将组件回收到组件池中
}

/**
* 分配数据索引
* @returns
*/
public allocateDataIndex(): number {
if (this.freeDataIndices.length > 0) {
return this.freeDataIndices.pop();
const component = this.components.get(entityId);
if (component) {
component.reset();
this.componentPool.push(component); // 将组件回收到组件池中
}
return this.data.length;
this.components.remove(entityId);
}
}
}
Loading

0 comments on commit a90ab95

Please sign in to comment.