@cc-component/cc-core 1.2.9 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/core/interface/App.ts +3 -0
- package/assets/core/interface/Interface.ts +1 -1
- package/assets/core/lib/ecs/.ecs.md +1 -0
- package/assets/core/lib/ecs/ECS.ts +329 -0
- package/assets/core/{home/BaseBoxView.ts.meta → lib/ecs/ECS.ts.meta} +1 -1
- package/assets/core/lib/ecs/ECSComp.ts +35 -0
- package/assets/core/{home/DouYinShow.ts.meta → lib/ecs/ECSComp.ts.meta} +1 -1
- package/assets/core/lib/ecs/ECSEntity.ts +302 -0
- package/assets/core/lib/ecs/ECSEntity.ts.meta +9 -0
- package/assets/core/lib/ecs/ECSGroup.ts +83 -0
- package/assets/core/lib/ecs/ECSGroup.ts.meta +9 -0
- package/assets/core/lib/ecs/ECSMask.ts +57 -0
- package/assets/core/lib/ecs/ECSMask.ts.meta +9 -0
- package/assets/core/lib/ecs/ECSMatcher.ts +215 -0
- package/assets/core/lib/ecs/ECSMatcher.ts.meta +9 -0
- package/assets/core/lib/ecs/ECSModel.ts +82 -0
- package/assets/core/lib/ecs/ECSModel.ts.meta +9 -0
- package/assets/core/lib/ecs/ECSSystem.ts +221 -0
- package/assets/core/lib/ecs/ECSSystem.ts.meta +9 -0
- package/assets/core/lib/ecs/IECS.ts.meta +9 -0
- package/assets/core/lib/ecs.meta +9 -0
- package/package.json +1 -1
- package/assets/core/home/BaseBoxView.ts +0 -57
- package/assets/core/home/DouYinShow.ts +0 -27
|
@@ -18,6 +18,7 @@ import { BundleConfigName, HttpType, IBundleConfig, IExtData, IHttpConfig, IInit
|
|
|
18
18
|
import { LayerType } from "../config/LayerType";
|
|
19
19
|
import { ELoggerLevel } from "../lib/logger/ELoggerLevel";
|
|
20
20
|
import { SkeletonAnim } from "../home/BaseSkeleton";
|
|
21
|
+
import { Tools } from "../home/Tools";
|
|
21
22
|
|
|
22
23
|
export class App {
|
|
23
24
|
/**当前bundle */
|
|
@@ -536,6 +537,8 @@ s */
|
|
|
536
537
|
}
|
|
537
538
|
}
|
|
538
539
|
}
|
|
540
|
+
|
|
541
|
+
static PromiseQueue<T>(promises: Promise<T>[], onProgress: (completed: number, total: number) => void): Promise<T[]> { return Tools.PromiseQueue(promises, onProgress) }
|
|
539
542
|
}
|
|
540
543
|
|
|
541
544
|
window.App = App;
|
|
@@ -143,7 +143,7 @@ declare global {
|
|
|
143
143
|
// */
|
|
144
144
|
// function RunParabolaTween(item: any, target_postion: Vec3, update: (ratio: number) => void, param?: { offset_ratio?: number, is_random?: boolean, time?: number, start_position?: Vec3 })
|
|
145
145
|
// /**任务进度队列 */
|
|
146
|
-
|
|
146
|
+
function PromiseQueue<T>(promises: Promise<T>[], onProgress: (completed: number, total: number) => void): Promise<T[]>
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Entity-Component-System 框架
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { ECSComp } from "./ECSComp";
|
|
2
|
+
import { ECSEntity } from "./ECSEntity";
|
|
3
|
+
import { ECSMatcher } from "./ECSMatcher";
|
|
4
|
+
import { CompCtor, CompType, ECSModel, EntityCtor } from "./ECSModel";
|
|
5
|
+
import { ECSComblockSystem, ECSRootSystem, ECSSystem } from "./ECSSystem";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* ECSEntity对象在destroy后,会回收到ECSModel.entityPool实体对象池中
|
|
9
|
+
* ECSComp对象从ECSEntity.remove后,数据组件会回收到ECSModel.compPools组件对象池中
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Entity-Component-System(实体-组件-系统)框架
|
|
14
|
+
* 文档:https://gitee.com/dgflash/oops-framework/wikis/pages?sort_id=12033388&doc_id=2873565
|
|
15
|
+
*/
|
|
16
|
+
export namespace ecs {
|
|
17
|
+
/** 实体 - 一个概念上的定义,指的是游戏世界中的一个独特物体,是一系列组件的集合 */
|
|
18
|
+
export type Entity = ECSEntity;
|
|
19
|
+
/** 组件 - 一堆数据的集合,即不存在任何的行为,只用来存储状态 */
|
|
20
|
+
export type Comp = ECSComp;
|
|
21
|
+
/** 系统 - 关注实体上组件数据变化,处理游戏逻辑 */
|
|
22
|
+
export type System = ECSSystem;
|
|
23
|
+
/** 根系统 - 驱动游戏中所有系统工作 */
|
|
24
|
+
export type RootSystem = ECSRootSystem;
|
|
25
|
+
/** 处理游戏逻辑系统对象 - 继承此对象实现自定义业务逻辑 */
|
|
26
|
+
export type ComblockSystem = ECSComblockSystem;
|
|
27
|
+
|
|
28
|
+
/** 实体 - 一个概念上的定义,指的是游戏世界中的一个独特物体,是一系列组件的集合 */
|
|
29
|
+
export const Entity = ECSEntity;
|
|
30
|
+
/** 组件 - 一堆数据的集合,即不存在任何的行为,只用来存储状态 */
|
|
31
|
+
export const Comp = ECSComp;
|
|
32
|
+
/** 系统 - 关注实体上组件数据变化,处理游戏逻辑 */
|
|
33
|
+
export const System = ECSSystem;
|
|
34
|
+
/** 根系统 - 驱动游戏中所有系统工作 */
|
|
35
|
+
export const RootSystem = ECSRootSystem;
|
|
36
|
+
/** 处理游戏逻辑系统对象 - 继承此对象实现自定义业务逻辑 */
|
|
37
|
+
export const ComblockSystem = ECSComblockSystem;
|
|
38
|
+
|
|
39
|
+
//#region 接口
|
|
40
|
+
|
|
41
|
+
/** 组件接口 */
|
|
42
|
+
export interface IComp {
|
|
43
|
+
canRecycle: boolean;
|
|
44
|
+
ent: Entity;
|
|
45
|
+
tid: number;
|
|
46
|
+
|
|
47
|
+
reset(): void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** 实体匹配器接口 */
|
|
51
|
+
export interface IMatcher {
|
|
52
|
+
mid: number;
|
|
53
|
+
indices: number[];
|
|
54
|
+
key: string;
|
|
55
|
+
isMatch(entity: Entity): boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 监听组件首次添加到实体上时,在ComblockSystem上实现这个接口
|
|
60
|
+
* 1. entityEnter会在update方法之前执行,实体进入后,不会再次进入entityEnter方法中
|
|
61
|
+
* 2. 当实体从当前System移除,下次再次符合条件进入System也会执行上述流程
|
|
62
|
+
* @example
|
|
63
|
+
export class RoleUpgradeSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
|
|
64
|
+
filter(): ecs.IMatcher {
|
|
65
|
+
return ecs.allOf(RoleUpgradeComp, RoleModelLevelComp);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
entityEnter(e: Role): void {
|
|
69
|
+
e.remove(RoleUpgradeComp);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
*/
|
|
73
|
+
export interface IEntityEnterSystem<E extends Entity = Entity> {
|
|
74
|
+
entityEnter(entity: E): void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** 监听组件从实体上移除时,在ComblockSystem上实现这个接口 */
|
|
78
|
+
export interface IEntityRemoveSystem<E extends Entity = Entity> {
|
|
79
|
+
entityRemove(entity: E): void;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** 监听系统第一次执行update处理实体时,在ComblockSystem上实现这个接口 */
|
|
83
|
+
export interface ISystemFirstUpdate<E extends Entity = Entity> {
|
|
84
|
+
firstUpdate(entity: E): void;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 监听系统执行update处理实体时,在ComblockSystem上实现这个接口 */
|
|
88
|
+
export interface ISystemUpdate<E extends Entity = Entity> {
|
|
89
|
+
update(entity: E): void;
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 注册组件到ecs系统中
|
|
95
|
+
* @param name 由于js打包会改变类名,所以这里必须手动传入组件的名称
|
|
96
|
+
* @param canNew 标识是否可以new对象。想继承自Cocos Creator的组件就不能去new,需要写成@ecs.register('name', false)
|
|
97
|
+
* @example
|
|
98
|
+
// 注册实体
|
|
99
|
+
@ecs.register('Role')
|
|
100
|
+
export class Role extends ecs.Entity {
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 注册数据组件
|
|
105
|
+
@ecs.register('RoleModel')
|
|
106
|
+
export class RoleModelComp extends ecs.Comp {
|
|
107
|
+
id: number = -1;
|
|
108
|
+
|
|
109
|
+
reset() {
|
|
110
|
+
this.id = -1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 注册系统组件
|
|
115
|
+
@ecs.register('Initialize')
|
|
116
|
+
export class InitResSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 注册显示对象组件
|
|
121
|
+
@ccclass('RoleViewComp')
|
|
122
|
+
@ecs.register('RoleView', false)
|
|
123
|
+
export class RoleViewComp extends CCComp {
|
|
124
|
+
onLoad(){
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
*/
|
|
129
|
+
export function register<T>(name: string, canNew: boolean = true) {
|
|
130
|
+
return function (ctor: any) {
|
|
131
|
+
// 注册系统
|
|
132
|
+
if (ctor.s) {
|
|
133
|
+
var system = ECSModel.systems.get(name);
|
|
134
|
+
if (system == null) {
|
|
135
|
+
system = new ecs.System();
|
|
136
|
+
ECSModel.systems.set(name, system);
|
|
137
|
+
}
|
|
138
|
+
system.add(new ctor);
|
|
139
|
+
}
|
|
140
|
+
// 注册实体
|
|
141
|
+
else if (ctor.tid == undefined) {
|
|
142
|
+
ECSModel.entityCtors.set(ctor as EntityCtor<T>, name);
|
|
143
|
+
}
|
|
144
|
+
// 注册组件
|
|
145
|
+
else {
|
|
146
|
+
if (ctor.tid === -1) {
|
|
147
|
+
ctor.tid = ECSModel.compTid++;
|
|
148
|
+
ctor.compName = name;
|
|
149
|
+
ECSModel.compCtors.push(ctor); // 注册不同类型的组件
|
|
150
|
+
if (canNew) {
|
|
151
|
+
ECSModel.compPools.set(ctor.tid, []);
|
|
152
|
+
}
|
|
153
|
+
ECSModel.compAddOrRemove.set(ctor.tid, []);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
throw new Error(`ECS 组件重复注册: ${name}.`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 创建一个新的实体对象或从缓存中获取一个实体对象
|
|
164
|
+
* @param ctor 实体类
|
|
165
|
+
*/
|
|
166
|
+
export function getEntity<T extends Entity>(ctor: EntityCtor<T>): T {
|
|
167
|
+
// 获取实体对象名
|
|
168
|
+
var entityName = ECSModel.entityCtors.get(ctor);
|
|
169
|
+
if (entityName == undefined)
|
|
170
|
+
console.error(`${ctor.name} 实体没有注册`);
|
|
171
|
+
|
|
172
|
+
// 获取实体对象池
|
|
173
|
+
var entitys = ECSModel.entityPool.get(entityName!) || [];
|
|
174
|
+
var entity: any = entitys.pop();
|
|
175
|
+
|
|
176
|
+
// 缓存中没有同类实体,则创建一个新的
|
|
177
|
+
if (!entity) {
|
|
178
|
+
entity = new ctor();
|
|
179
|
+
entity.eid = ECSModel.eid++; // 实体唯一编号
|
|
180
|
+
entity.name = entityName;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 触发实体初始化逻辑
|
|
184
|
+
if (entity.init) {
|
|
185
|
+
entity.isValid = true;
|
|
186
|
+
entity.init();
|
|
187
|
+
}
|
|
188
|
+
else
|
|
189
|
+
console.error(`${ctor.name} 实体缺少 init 方法初始化默认组件`);
|
|
190
|
+
|
|
191
|
+
ECSModel.eid2Entity.set(entity.eid, entity);
|
|
192
|
+
return entity as T;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* 动态查询实体
|
|
197
|
+
* @param matcher 匹配器
|
|
198
|
+
* @example
|
|
199
|
+
* ecs.query(ecs.allOf(Comp1, Comp2));
|
|
200
|
+
*/
|
|
201
|
+
export function query<E extends Entity = Entity>(matcher: IMatcher): E[] {
|
|
202
|
+
let group = ECSModel.groups.get(matcher.mid);
|
|
203
|
+
if (!group) {
|
|
204
|
+
group = ECSModel.createGroup(matcher);
|
|
205
|
+
ECSModel.eid2Entity.forEach(group.onComponentAddOrRemove, group);
|
|
206
|
+
}
|
|
207
|
+
return group.matchEntities as E[];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** 清理所有的实体 */
|
|
211
|
+
export function clear() {
|
|
212
|
+
ECSModel.eid2Entity.forEach((entity) => {
|
|
213
|
+
entity.destroy();
|
|
214
|
+
});
|
|
215
|
+
ECSModel.groups.forEach((group) => {
|
|
216
|
+
group.clear();
|
|
217
|
+
});
|
|
218
|
+
ECSModel.compAddOrRemove.forEach(callbackLst => {
|
|
219
|
+
callbackLst.length = 0;
|
|
220
|
+
});
|
|
221
|
+
ECSModel.eid2Entity.clear();
|
|
222
|
+
ECSModel.groups.clear();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 通过实体唯一编号获得实体对象
|
|
227
|
+
* @param eid 实体唯一编号
|
|
228
|
+
*/
|
|
229
|
+
export function getEntityByEid<E extends Entity = Entity>(eid: number): E {
|
|
230
|
+
return ECSModel.eid2Entity.get(eid) as E;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** 当前活动中的实体数量 */
|
|
234
|
+
export function activeEntityCount() {
|
|
235
|
+
return ECSModel.eid2Entity.size;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** 创建实体 */
|
|
239
|
+
function createEntity<E extends Entity = Entity>(): E {
|
|
240
|
+
let entity = new Entity();
|
|
241
|
+
entity.eid = ECSModel.eid++; // 实体id也是有限的资源
|
|
242
|
+
ECSModel.eid2Entity.set(entity.eid, entity);
|
|
243
|
+
return entity as E;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* 指定一个组件创建实体,返回组件对象。
|
|
248
|
+
* @param ctor
|
|
249
|
+
*/
|
|
250
|
+
function createEntityWithComp<T extends IComp>(ctor: CompCtor<T>): T {
|
|
251
|
+
let entity = createEntity();
|
|
252
|
+
return entity.add(ctor);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
//#region 过滤器
|
|
256
|
+
/**
|
|
257
|
+
* 表示只关心这些组件的添加和删除动作。虽然实体可能有这些组件之外的组件,但是它们的添加和删除没有被关注,所以不会存在对关注之外的组件
|
|
258
|
+
* 进行添加操作引发Group重复添加实体。
|
|
259
|
+
* @param args
|
|
260
|
+
* @example
|
|
261
|
+
* ecs.allOf(AComponent, BComponent, CComponent);
|
|
262
|
+
*/
|
|
263
|
+
export function allOf(...args: CompType<IComp>[]) {
|
|
264
|
+
return new ECSMatcher().allOf(...args);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 组件间是或的关系,表示关注拥有任意一个这些组件的实体
|
|
269
|
+
* @param args 组件类
|
|
270
|
+
* @example
|
|
271
|
+
* ecs.anyOf(AComponent, BComponent);
|
|
272
|
+
*/
|
|
273
|
+
export function anyOf(...args: CompType<IComp>[]) {
|
|
274
|
+
return new ECSMatcher().anyOf(...args);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* 表示关注只拥有这些组件的实体
|
|
279
|
+
* 注:不是特殊情况不建议使用onlyOf。因为onlyOf会监听所有组件的添加和删除事件
|
|
280
|
+
* @param args 组件类
|
|
281
|
+
* @example
|
|
282
|
+
// 不包含CComponent或者DComponent
|
|
283
|
+
ecs.allOf(AComponent, BComponent).excludeOf(CComponent, DComponent);
|
|
284
|
+
|
|
285
|
+
// 不同时包含CComponent和DComponent
|
|
286
|
+
ecs.allOf(AComponent, BComponent).excludeOf(CComponent).excludeOf(DComponent);
|
|
287
|
+
*/
|
|
288
|
+
export function onlyOf(...args: CompType<IComp>[]) {
|
|
289
|
+
return new ECSMatcher().onlyOf(...args);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* 不包含指定的任意一个组件
|
|
294
|
+
* @param args 组件类
|
|
295
|
+
* @example
|
|
296
|
+
// 表示不包含组件A或者组件B
|
|
297
|
+
ecs.excludeOf(A, B);
|
|
298
|
+
*/
|
|
299
|
+
export function excludeOf(...args: CompType<IComp>[]) {
|
|
300
|
+
return new ECSMatcher().excludeOf(...args);
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
303
|
+
|
|
304
|
+
//#region 单例组件
|
|
305
|
+
/**
|
|
306
|
+
* 获取单例组件
|
|
307
|
+
* @param ctor 组件类
|
|
308
|
+
*/
|
|
309
|
+
export function getSingleton<T extends IComp>(ctor: CompCtor<T>) {
|
|
310
|
+
if (!ECSModel.tid2comp.has(ctor.tid)) {
|
|
311
|
+
let comp = createEntityWithComp(ctor) as T;
|
|
312
|
+
ECSModel.tid2comp.set(ctor.tid, comp);
|
|
313
|
+
}
|
|
314
|
+
return ECSModel.tid2comp.get(ctor.tid) as T;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* 注册单例组件 - 主要用于那些不能手动创建对象的组件
|
|
319
|
+
* @param obj
|
|
320
|
+
*/
|
|
321
|
+
export function addSingleton(obj: IComp) {
|
|
322
|
+
let tid = (obj.constructor as CompCtor<IComp>).tid;
|
|
323
|
+
if (!ECSModel.tid2comp.has(tid)) {
|
|
324
|
+
ECSModel.tid2comp.set(tid, obj);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
//#endregion
|
|
329
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: dgflash
|
|
3
|
+
* @Date: 2022-09-01 18:00:28
|
|
4
|
+
* @LastEditors: dgflash
|
|
5
|
+
* @LastEditTime: 2022-09-05 14:03:54
|
|
6
|
+
*/
|
|
7
|
+
import { ecs } from "./ECS";
|
|
8
|
+
import { ECSEntity } from "./ECSEntity";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 组件抽象类
|
|
12
|
+
* 注:建议组件里面只放数据可能在实际写代码会碰到一些比较麻烦的问题,如果是单纯对组件内的数据操作可以在组件里面写方法
|
|
13
|
+
*/
|
|
14
|
+
export abstract class ECSComp implements ecs.IComp {
|
|
15
|
+
/** 组件的类型编号,-1表示未给该组件分配编号 */
|
|
16
|
+
static tid: number = -1;
|
|
17
|
+
/** 组件名 */
|
|
18
|
+
static compName: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 是否可回收组件对象,默认情况下都是可回收的
|
|
22
|
+
* 注:如果该组件对象是由ecs系统外部创建的,则不可回收,需要用户自己手动进行回收
|
|
23
|
+
*/
|
|
24
|
+
canRecycle: boolean = true;
|
|
25
|
+
/** 拥有该组件的实体 */
|
|
26
|
+
ent!: ECSEntity;
|
|
27
|
+
/** 组件的类型编号 */
|
|
28
|
+
tid: number = -1;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 组件被回收时会调用这个接口。可以在这里重置数据,或者解除引用
|
|
32
|
+
* 注:不要偷懒,除非你能确定并保证组件在复用时,里面的数据是先赋值然后再使用
|
|
33
|
+
*/
|
|
34
|
+
abstract reset(): void;
|
|
35
|
+
}
|