mirror of
https://gitee.com/dgflash/oops-framework.git
synced 2026-05-31 18:59:19 +08:00
感谢 Hess 建议优化 ecs 框架所有生命周期事件在处理多实体时,将批处理逻辑移到框架层实现,减小业务层代码量
This commit is contained in:
15
README.md
15
README.md
@@ -1,3 +1,9 @@
|
||||
<!--
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-04-14 17:08:00
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-04-15 10:43:53
|
||||
-->
|
||||
# oops-framework
|
||||
#### 介绍
|
||||
oops-framework 基于 Cocos Creato 3.x 开发的一款游戏框架
|
||||
@@ -81,3 +87,12 @@ oops-framework 基于 Cocos Creato 3.x 开发的一款游戏框架
|
||||
打开项目请用Cocos Creator v3.4.2 以上版本
|
||||
|
||||
#### 学习交流QQ群:798575969
|
||||
|
||||
#### 贡献榜
|
||||
| 时间 | 开发者 | 贡献内容 |
|
||||
| ---------- | -------- | ------------------------------------------------------------------------------------------- |
|
||||
| 2022-04.15 | Hess | 建议优化 ecs 框架所有生命周期事件在处理多实体时,将批处理逻辑移到框架层实现,减小业务代码量 |
|
||||
| 2021-10-13 | laret | 修复 Dialog 类型的 UI 不能连续触发 |
|
||||
| 2021-10-20 | dogegg | 支持添加 cc.Component 到 ecs 实体对象中 |
|
||||
| 2022-02-18 | 匿名好友 | 修复 TimerManager 时间管理对象,在游戏最小化切到最大化时,定时间器不触发完成事件的问题 |
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
"_priority": 1073741824,
|
||||
"_fov": 45,
|
||||
"_fovAxis": 0,
|
||||
"_orthoHeight": 391.032967032967,
|
||||
"_orthoHeight": 394.00651465798046,
|
||||
"_near": 1,
|
||||
"_far": 2000,
|
||||
"_color": {
|
||||
|
||||
@@ -527,6 +527,7 @@ export module ecs {
|
||||
}
|
||||
|
||||
this.mask.set(compTid);
|
||||
//@ts-ignore
|
||||
this[tmpCtor.compName] = ctor;
|
||||
this.compTid2Ctor.set(compTid, tmpCtor);
|
||||
ctor.ent = this;
|
||||
@@ -589,12 +590,14 @@ export module ecs {
|
||||
compName = ctor.compName;
|
||||
if (this.mask.has(componentTypeId)) {
|
||||
hasComp = true;
|
||||
//@ts-ignore
|
||||
let comp = this[ctor.compName] as IComp;
|
||||
//@ts-ignore
|
||||
comp.ent = null;
|
||||
if (isRecycle) {
|
||||
comp.reset();
|
||||
if (comp.canRecycle) {
|
||||
compPools.get(componentTypeId).push(comp);
|
||||
compPools.get(componentTypeId)!.push(comp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -604,6 +607,7 @@ export module ecs {
|
||||
}
|
||||
|
||||
if (hasComp) {
|
||||
//@ts-ignore
|
||||
this[compName] = null;
|
||||
this.mask.delete(componentTypeId);
|
||||
this.compTid2Ctor.delete(componentTypeId);
|
||||
@@ -703,6 +707,8 @@ export module ecs {
|
||||
}
|
||||
}
|
||||
|
||||
//#region Matcher
|
||||
|
||||
abstract class BaseOf {
|
||||
protected mask = new Mask();
|
||||
public indices: number[] = [];
|
||||
@@ -918,6 +924,7 @@ export module ecs {
|
||||
return newMatcher;
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region System
|
||||
/**
|
||||
@@ -927,21 +934,28 @@ export module ecs {
|
||||
* 当实体从当前System移除,下次再次符合条件进入System也会执行上述流程。
|
||||
*/
|
||||
export interface IEntityEnterSystem<E extends Entity = Entity> {
|
||||
entityEnter(entities: E[]): void;
|
||||
entityEnter(entity: E): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果需要监听实体从当前System移除,需要实现这个接口。
|
||||
*/
|
||||
export interface IEntityRemoveSystem<E extends Entity = Entity> {
|
||||
entityRemove(entities: E[]): void;
|
||||
entityRemove(entity: E): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 第一次执行update
|
||||
*/
|
||||
export interface ISystemFirstUpdate<E extends Entity = Entity> {
|
||||
firstUpdate(entities: E[]): void;
|
||||
firstUpdate(entity: E): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行update
|
||||
*/
|
||||
export interface ISystemUpdate<E extends Entity = Entity> {
|
||||
update(entity: E): void;
|
||||
}
|
||||
|
||||
export abstract class ComblockSystem<E extends Entity = Entity> {
|
||||
@@ -998,17 +1012,32 @@ export module ecs {
|
||||
return this.group.count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 先执行entityEnter,最后执行firstUpdate
|
||||
* @param dt
|
||||
* @returns
|
||||
*/
|
||||
private updateOnce(dt: number) {
|
||||
if (this.group.count === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dt = dt;
|
||||
|
||||
// 处理刚进来的实体
|
||||
if (this.enteredEntities!.size > 0) {
|
||||
(this as unknown as IEntityEnterSystem).entityEnter(Array.from(this.enteredEntities!.values()) as E[]);
|
||||
var entities = this.enteredEntities!.values();
|
||||
for (let entity of entities) {
|
||||
(this as unknown as IEntityEnterSystem).entityEnter(entity);
|
||||
}
|
||||
this.enteredEntities!.clear();
|
||||
}
|
||||
(this as unknown as ISystemFirstUpdate).firstUpdate(this.group.matchEntities);
|
||||
|
||||
// 只执行firstUpdate
|
||||
for (let entity of this.group.matchEntities) {
|
||||
(this as unknown as ISystemFirstUpdate).firstUpdate(entity);
|
||||
}
|
||||
|
||||
this.execute = this.tmpExecute!;
|
||||
this.execute(dt);
|
||||
this.tmpExecute = null;
|
||||
@@ -1020,37 +1049,51 @@ export module ecs {
|
||||
* @returns
|
||||
*/
|
||||
private execute0(dt: number): void {
|
||||
if (this.group.count === 0) {
|
||||
return;
|
||||
}
|
||||
if (this.group.count === 0) return;
|
||||
|
||||
this.dt = dt;
|
||||
this.update(this.group.matchEntities);
|
||||
|
||||
// 执行update
|
||||
for (let entity of this.group.matchEntities) {
|
||||
this.update(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 先执行entityRemove,再执行entityEnter,最后执行update。
|
||||
* 先执行entityRemove,再执行entityEnter,最后执行update
|
||||
* @param dt
|
||||
* @returns
|
||||
*/
|
||||
private execute1(dt: number): void {
|
||||
if (this.removedEntities!.size > 0) {
|
||||
if (this.hasEntityRemove) {
|
||||
(this as unknown as IEntityRemoveSystem).entityRemove(Array.from(this.removedEntities!.values()) as E[]);
|
||||
var entities = this.removedEntities!.values();
|
||||
for (let entity of entities) {
|
||||
(this as unknown as IEntityRemoveSystem).entityRemove(entity);
|
||||
}
|
||||
}
|
||||
this.removedEntities!.clear();
|
||||
}
|
||||
if (this.group.count === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.group.count === 0) return;
|
||||
|
||||
this.dt = dt;
|
||||
|
||||
// 处理刚进来的实体
|
||||
if (this.enteredEntities!.size > 0) {
|
||||
if (this.hasEntityEnter) {
|
||||
(this as unknown as IEntityEnterSystem).entityEnter(Array.from(this.enteredEntities!.values()) as E[]);
|
||||
var entities = this.enteredEntities!.values();
|
||||
for (let entity of entities) {
|
||||
(this as unknown as IEntityEnterSystem).entityEnter(entity);
|
||||
}
|
||||
}
|
||||
this.enteredEntities!.clear();
|
||||
}
|
||||
this.update(this.group.matchEntities as E[]);
|
||||
|
||||
// 执行update
|
||||
for (let entity of this.group.matchEntities) {
|
||||
this.update(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1059,8 +1102,8 @@ export module ecs {
|
||||
* 根据提供的组件过滤实体。
|
||||
*/
|
||||
abstract filter(): IMatcher;
|
||||
// abstract update(entities: E[]): void;
|
||||
update(entities: E[]) { }; // 避免不需要用update时写一些多余的代码
|
||||
|
||||
update(entity: E) { }; // 避免不需要用update时写一些多余的代码
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-11-23 15:51:15
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-03-10 10:21:27
|
||||
* @LastEditTime: 2022-04-15 09:47:36
|
||||
*/
|
||||
|
||||
import { v3 } from "cc";
|
||||
@@ -28,44 +28,42 @@ export class AccountNetDataSystem extends ecs.ComblockSystem implements ecs.IEnt
|
||||
return ecs.allOf(AccountNetDataComp, AccountModelComp);
|
||||
}
|
||||
|
||||
entityEnter(entities: Account[]): void {
|
||||
for (let e of entities) {
|
||||
var params: any = {
|
||||
playerId: netConfig.dbid,
|
||||
sessionKey: netConfig.sessionKey,
|
||||
}
|
||||
|
||||
let onComplete = {
|
||||
target: this,
|
||||
callback: (data: any) => {
|
||||
// 设置本地存储的用户标识(用于下次登录不输入帐号)
|
||||
this.setLocalStorage(data.id);
|
||||
|
||||
// 创建玩家角色对象
|
||||
this.createRole(e, data);
|
||||
|
||||
// 玩家登录成功事件
|
||||
Message.dispatchEvent(GameEvent.LoginSuccess);
|
||||
}
|
||||
}
|
||||
// 请求登录游戏获取角色数据
|
||||
// netChannel.game.req("LoginAction", "loadPlayer", params, onComplete);
|
||||
|
||||
// 离线测试代码开始
|
||||
var data = {
|
||||
id: 1,
|
||||
name: "Oops",
|
||||
power: 10,
|
||||
agile: 10,
|
||||
physical: 10,
|
||||
lv: 1,
|
||||
jobId: 1
|
||||
}
|
||||
onComplete.callback(data);
|
||||
// 离线测试代码结束
|
||||
|
||||
e.remove(AccountNetDataComp);
|
||||
entityEnter(e: Account): void {
|
||||
var params: any = {
|
||||
playerId: netConfig.dbid,
|
||||
sessionKey: netConfig.sessionKey,
|
||||
}
|
||||
|
||||
let onComplete = {
|
||||
target: this,
|
||||
callback: (data: any) => {
|
||||
// 设置本地存储的用户标识(用于下次登录不输入帐号)
|
||||
this.setLocalStorage(data.id);
|
||||
|
||||
// 创建玩家角色对象
|
||||
this.createRole(e, data);
|
||||
|
||||
// 玩家登录成功事件
|
||||
Message.dispatchEvent(GameEvent.LoginSuccess);
|
||||
}
|
||||
}
|
||||
// 请求登录游戏获取角色数据
|
||||
// netChannel.game.req("LoginAction", "loadPlayer", params, onComplete);
|
||||
|
||||
// 离线测试代码开始
|
||||
var data = {
|
||||
id: 1,
|
||||
name: "Oops",
|
||||
power: 10,
|
||||
agile: 10,
|
||||
physical: 10,
|
||||
lv: 1,
|
||||
jobId: 1
|
||||
}
|
||||
onComplete.callback(data);
|
||||
// 离线测试代码结束
|
||||
|
||||
e.remove(AccountNetDataComp);
|
||||
}
|
||||
|
||||
/** 创建角色对象(自定义逻辑) */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-08-11 16:41:12
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-01-27 11:33:31
|
||||
* @LastEditTime: 2022-04-15 10:01:35
|
||||
*/
|
||||
import { Node, Vec3 } from "cc";
|
||||
import { Timer } from "../../../../core/common/manager/TimerManager";
|
||||
@@ -63,73 +63,67 @@ export class MoveToSystem extends ecs.ComblockSystem<ecs.Entity> implements ecs.
|
||||
return ecs.allOf(MoveToComp);
|
||||
}
|
||||
|
||||
entityEnter(entities: ecs.Entity[]): void {
|
||||
for (let e of entities) {
|
||||
e.add(VariableMoveToComponent);
|
||||
}
|
||||
entityEnter(e: ecs.Entity): void {
|
||||
e.add(VariableMoveToComponent);
|
||||
}
|
||||
|
||||
entityRemove(entities: ecs.Entity[]): void {
|
||||
for (let e of entities) {
|
||||
e.remove(VariableMoveToComponent);
|
||||
}
|
||||
entityRemove(e: ecs.Entity): void {
|
||||
e.remove(VariableMoveToComponent);
|
||||
}
|
||||
|
||||
update(entities: ecs.Entity[]) {
|
||||
for (let e of entities) {
|
||||
let move = e.get(MoveToComp);
|
||||
let mtv = e.get(VariableMoveToComponent);
|
||||
let end: Vec3;
|
||||
update(e: ecs.Entity) {
|
||||
let move = e.get(MoveToComp);
|
||||
let mtv = e.get(VariableMoveToComponent);
|
||||
let end: Vec3;
|
||||
|
||||
console.assert(move.speed > 0, "移动速度必须要大于零");
|
||||
console.assert(move.speed > 0, "移动速度必须要大于零");
|
||||
|
||||
if (move.target instanceof Node) {
|
||||
end = move.ns == Node.NodeSpace.WORLD ? move.target.worldPosition : move.target.position;
|
||||
}
|
||||
else {
|
||||
end = move.target as Vec3;
|
||||
if (move.target instanceof Node) {
|
||||
end = move.ns == Node.NodeSpace.WORLD ? move.target.worldPosition : move.target.position;
|
||||
}
|
||||
else {
|
||||
end = move.target as Vec3;
|
||||
}
|
||||
|
||||
// 目标移动后,重计算移动方向与移动到目标点的速度
|
||||
if (mtv.end == null || !mtv.end.strictEquals(end)) {
|
||||
let target = end.clone();
|
||||
if (move.offsetVector) {
|
||||
target = target.add(move.offsetVector); // 这里的问题
|
||||
}
|
||||
|
||||
// 目标移动后,重计算移动方向与移动到目标点的速度
|
||||
if (mtv.end == null || !mtv.end.strictEquals(end)) {
|
||||
let target = end.clone();
|
||||
if (move.offsetVector) {
|
||||
target = target.add(move.offsetVector); // 这里的问题
|
||||
}
|
||||
// 移动方向与移动数度
|
||||
let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
|
||||
move.velocity = Vec3Util.sub(target, start).normalize();
|
||||
|
||||
// 移动方向与移动数度
|
||||
let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
|
||||
move.velocity = Vec3Util.sub(target, start).normalize();
|
||||
// 移动时间与目标偏位置计算
|
||||
let distance = Vec3.distance(start, target) - move.offset;
|
||||
|
||||
// 移动时间与目标偏位置计算
|
||||
let distance = Vec3.distance(start, target) - move.offset;
|
||||
|
||||
move.onChange?.call(this);
|
||||
|
||||
if (distance - move.offset <= 0) {
|
||||
this.exit(e);
|
||||
}
|
||||
else {
|
||||
mtv.timer.step = distance / move.speed;
|
||||
mtv.end = end.clone();
|
||||
mtv.target = move.velocity.clone().multiplyScalar(distance).add(start);
|
||||
}
|
||||
}
|
||||
|
||||
if (move.speed > 0) {
|
||||
let trans = Vec3Util.mul(move.velocity, move.speed * this.dt);
|
||||
move.node.translate(trans, Node.NodeSpace.LOCAL);
|
||||
}
|
||||
|
||||
// 移动完成事件
|
||||
if (mtv.timer.update(this.dt)) {
|
||||
if (move.ns == Node.NodeSpace.WORLD)
|
||||
move.node.worldPosition = mtv.target;
|
||||
else
|
||||
move.node.position = mtv.target;
|
||||
move.onChange?.call(this);
|
||||
|
||||
if (distance - move.offset <= 0) {
|
||||
this.exit(e);
|
||||
}
|
||||
else {
|
||||
mtv.timer.step = distance / move.speed;
|
||||
mtv.end = end.clone();
|
||||
mtv.target = move.velocity.clone().multiplyScalar(distance).add(start);
|
||||
}
|
||||
}
|
||||
|
||||
if (move.speed > 0) {
|
||||
let trans = Vec3Util.mul(move.velocity, move.speed * this.dt);
|
||||
move.node.translate(trans, Node.NodeSpace.LOCAL);
|
||||
}
|
||||
|
||||
// 移动完成事件
|
||||
if (mtv.timer.update(this.dt)) {
|
||||
if (move.ns == Node.NodeSpace.WORLD)
|
||||
move.node.worldPosition = mtv.target;
|
||||
else
|
||||
move.node.position = mtv.target;
|
||||
|
||||
this.exit(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-01-25 17:49:26
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-03-10 13:47:35
|
||||
* @LastEditTime: 2022-04-15 09:37:39
|
||||
*/
|
||||
|
||||
import { Message } from "../../../core/common/event/MessageManager";
|
||||
@@ -38,15 +38,13 @@ export class RoleChangeJobSystem extends ecs.ComblockSystem implements ecs.IEnti
|
||||
return ecs.allOf(RoleChangeJobComp, RoleModelJobComp);
|
||||
}
|
||||
|
||||
entityEnter(entities: Role[]): void {
|
||||
for (let e of entities) {
|
||||
// 数值更新
|
||||
e.RoleModelJob.id = e.RoleChangeJob.jobId;
|
||||
entityEnter(e: Role): void {
|
||||
// 数值更新
|
||||
e.RoleModelJob.id = e.RoleChangeJob.jobId;
|
||||
|
||||
// 转职事件,通知视图层逻辑刷新界面效果,实现两层逻辑分离
|
||||
Message.dispatchEvent(RoleEvent.ChangeJob);
|
||||
// 转职事件,通知视图层逻辑刷新界面效果,实现两层逻辑分离
|
||||
Message.dispatchEvent(RoleEvent.ChangeJob);
|
||||
|
||||
e.remove(RoleChangeJobComp);
|
||||
}
|
||||
e.remove(RoleChangeJobComp);
|
||||
}
|
||||
}
|
||||
@@ -21,27 +21,25 @@ export class RoleUpgradeSystem extends ecs.ComblockSystem implements ecs.IEntity
|
||||
return ecs.allOf(RoleUpgradeComp, RoleModelLevelComp);
|
||||
}
|
||||
|
||||
entityEnter(entities: Role[]): void {
|
||||
for (let e of entities) {
|
||||
let rm = e.RoleModel;
|
||||
let rlm = e.RoleModelLevel;
|
||||
let ru = e.RoleUpgrade;
|
||||
entityEnter(e: Role): void {
|
||||
let rm = e.RoleModel;
|
||||
let rlm = e.RoleModelLevel;
|
||||
let ru = e.RoleUpgrade;
|
||||
|
||||
if (ru.lv == 0)
|
||||
rlm.vm.lv++; // 提升一级
|
||||
else
|
||||
rlm.vm.lv = ru.lv; // 设置等级
|
||||
if (ru.lv == 0)
|
||||
rlm.vm.lv++; // 提升一级
|
||||
else
|
||||
rlm.vm.lv = ru.lv; // 设置等级
|
||||
|
||||
// 当前等级配置
|
||||
rlm.rtluCurrent.init(rlm.vm.lv);
|
||||
// 等级附加属性
|
||||
rm.attributes.get(RoleAttributeType.hp).level = rlm.rtluCurrent.hp;
|
||||
// 当前等级配置
|
||||
rlm.rtluCurrent.init(rlm.vm.lv);
|
||||
// 等级附加属性
|
||||
rm.attributes.get(RoleAttributeType.hp).level = rlm.rtluCurrent.hp;
|
||||
|
||||
// 下个等级配置
|
||||
rlm.rtluNext.init(rlm.vm.lv + 1);
|
||||
rlm.vm.expNext = rlm.rtluNext.needexp;
|
||||
// 下个等级配置
|
||||
rlm.rtluNext.init(rlm.vm.lv + 1);
|
||||
rlm.vm.expNext = rlm.rtluNext.needexp;
|
||||
|
||||
e.remove(RoleUpgradeComp);
|
||||
}
|
||||
e.remove(RoleUpgradeComp);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user