去掉碰撞系统
This commit is contained in:
@@ -7,6 +7,7 @@ import { UIConfigData } from './game/common/config/GameUIConfig';
|
|||||||
import { smc } from './game/common/SingletonModuleComp';
|
import { smc } from './game/common/SingletonModuleComp';
|
||||||
import { Initialize } from './game/initialize/Initialize';
|
import { Initialize } from './game/initialize/Initialize';
|
||||||
import { EcsPositionSystem } from './game/common/ecs/position/EcsPositionSystem';
|
import { EcsPositionSystem } from './game/common/ecs/position/EcsPositionSystem';
|
||||||
|
import { EcsSkillSystem } from './game/skill/EcsSkillSystem';
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -30,9 +31,10 @@ export class Main extends Root {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async initEcsSystem() {
|
protected async initEcsSystem() {
|
||||||
oops.ecs.add(new EcsPositionSystem())
|
oops.ecs.add(new EcsPositionSystem());
|
||||||
// oops.ecs.add(new EcsAccountSystem());
|
oops.ecs.add(new EcsSkillSystem());
|
||||||
// oops.ecs.add(new EcsRoleSystem());
|
// oops.ecs.add(new EcsRoleSystem());
|
||||||
// oops.ecs.add(new EcsInitializeSystem());
|
// oops.ecs.add(new EcsInitializeSystem());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,5 +117,20 @@ export const SkillSet = {
|
|||||||
6031:{uuid:6031,path:"6031",type:1,tg:0,fname:"buff_do",flash:true,with:false,debuff:0,depb:0,debtime:0,derate:0,in:2,count:1,def:20,apup:0,ap:70,mhp:0,hp:70,cd:1,shield:0,speed:120,sonsk:0,hero:5211,name:"召唤仆从",sp_name:"zhaohuan",info:"召唤一个与施法者等级相同的骷髅战士为我方而战"},
|
6031:{uuid:6031,path:"6031",type:1,tg:0,fname:"buff_do",flash:true,with:false,debuff:0,depb:0,debtime:0,derate:0,in:2,count:1,def:20,apup:0,ap:70,mhp:0,hp:70,cd:1,shield:0,speed:120,sonsk:0,hero:5211,name:"召唤仆从",sp_name:"zhaohuan",info:"召唤一个与施法者等级相同的骷髅战士为我方而战"},
|
||||||
6032:{uuid:6032,path:"6032",type:1,tg:0,fname:"",flash:false,with:false,debuff:0,depb:0,debtime:0,derate:0,in:2,count:1,def:0,apup:0,ap:100,mhp:0,hp:5,cd:1,shield:0,speed:120,sonsk:0,hero:0,name:"自愈",sp_name:"heath_small",info:"主动:自己回复自身5%最大生命值的生命"},
|
6032:{uuid:6032,path:"6032",type:1,tg:0,fname:"",flash:false,with:false,debuff:0,depb:0,debtime:0,derate:0,in:2,count:1,def:0,apup:0,ap:100,mhp:0,hp:5,cd:1,shield:0,speed:120,sonsk:0,hero:0,name:"自愈",sp_name:"heath_small",info:"主动:自己回复自身5%最大生命值的生命"},
|
||||||
6033:{uuid:6033,path:"6033",type:1,tg:3,fname:"",flash:false,with:false,debuff:4,depb:100,debtime:1,derate:20,in:1,count:1,def:0,apup:0,ap:500,mhp:0,hp:0,cd:1,shield:0,speed:500,sonsk:6035,hero:0,name:"爆锤",sp_name:"cuida",info:"捶爆前方目标,造成300%攻击的伤害,震慑敌人,本局内全部敌方降低对方10%攻击力"},
|
6033:{uuid:6033,path:"6033",type:1,tg:3,fname:"",flash:false,with:false,debuff:4,depb:100,debtime:1,derate:20,in:1,count:1,def:0,apup:0,ap:500,mhp:0,hp:0,cd:1,shield:0,speed:500,sonsk:6035,hero:0,name:"爆锤",sp_name:"cuida",info:"捶爆前方目标,造成300%攻击的伤害,震慑敌人,本局内全部敌方降低对方10%攻击力"},
|
||||||
6034:{uuid:6034,path:"6034",type:1,tg:3,fname:"",flash:false,with:false,debuff:4,depb:100,debtime:1,derate:20,in:1,count:1,def:0,apup:0,ap:80,mhp:0,hp:0,cd:1,shield:0,speed:350,sonsk:0,hero:0,name:"暴风箭",sp_name:"bingyu",info:"射出能量暴风箭攻击最前方范围敌人,每波造成80%攻击的伤害"}
|
6034:{uuid:6034,path:"6034",type:1,tg:3,fname:"",flash:false,with:false,debuff:4,depb:100,debtime:1,derate:20,in:1,count:1,def:0,apup:0,ap:80,mhp:0,hp:0,cd:1,shield:0,speed:350,sonsk:0,hero:0,name:"暴风箭",sp_name:"bingyu",info:"射出能量暴风箭攻击最前方范围敌人,每波造成80%攻击的伤害"},
|
||||||
|
7001: {
|
||||||
|
prefab: "arrow", // 预制体路径
|
||||||
|
range: 500, // 攻击距离
|
||||||
|
width: 30, // 攻击宽度
|
||||||
|
penetrate: 3, // 最大穿透数
|
||||||
|
speed: 800, // 飞行速度(像素/秒)
|
||||||
|
hitInterval: 0.1 // 伤害间隔(秒)
|
||||||
|
},
|
||||||
|
8001: {
|
||||||
|
prefab: "fireball",
|
||||||
|
speed: 600,
|
||||||
|
range: 800,
|
||||||
|
penetrate: 2,
|
||||||
|
collisionRadius: 50 // 碰撞检测半径
|
||||||
|
}
|
||||||
};
|
};
|
||||||
17
assets/script/game/common/ecs/position/BattleMoveComp.ts
Normal file
17
assets/script/game/common/ecs/position/BattleMoveComp.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { ecs } from "../../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
|
@ecs.register('BattleMove')
|
||||||
|
|
||||||
|
export class BattleMoveComp extends ecs.Comp {
|
||||||
|
/** 移动方向:1向右,-1向左 */
|
||||||
|
direction: number = 1;
|
||||||
|
/** 目标x坐标 */
|
||||||
|
targetX: number = 0;
|
||||||
|
/** 是否处于移动状态 */
|
||||||
|
moving: boolean = true;
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.direction = 1;
|
||||||
|
this.targetX = 0;
|
||||||
|
this.moving = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
51
assets/script/game/common/ecs/position/BattleMoveSystem.ts
Normal file
51
assets/script/game/common/ecs/position/BattleMoveSystem.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { HeroViewComp } from "../../../hero/HeroViewComp";
|
||||||
|
import { BattleMoveComp } from "./BattleMoveComp";
|
||||||
|
import { ecs } from "../../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
|
|
||||||
|
@ecs.register('BattleMoveSystem')
|
||||||
|
export class BattleMoveSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(BattleMoveComp, HeroViewComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: ecs.Entity) {
|
||||||
|
const move = e.get(BattleMoveComp);
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
|
||||||
|
if (!move.moving) return;
|
||||||
|
|
||||||
|
// 检测攻击范围内是否有敌人
|
||||||
|
const hasEnemy = this.checkEnemiesInRange(e, view.dis);
|
||||||
|
|
||||||
|
if (!hasEnemy) {
|
||||||
|
// 计算移动量
|
||||||
|
const delta = view.speed * this.dt * move.direction;
|
||||||
|
const newX = view.node.position.x + delta;
|
||||||
|
|
||||||
|
// 限制移动范围
|
||||||
|
if (this.validatePosition(newX, move)) {
|
||||||
|
view.node.setPosition(newX, view.node.position.y, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 验证目标位置有效性 */
|
||||||
|
private validatePosition(newX: number, move: BattleMoveComp): boolean {
|
||||||
|
// 我方不能超过右边界,敌方不能超过左边界
|
||||||
|
return move.direction === 1 ?
|
||||||
|
newX <= move.targetX :
|
||||||
|
newX >= move.targetX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 检测攻击范围内敌人 */
|
||||||
|
private checkEnemiesInRange(entity: ecs.Entity, range: number): boolean {
|
||||||
|
const currentPos = entity.get(HeroViewComp).node.position;
|
||||||
|
const team = entity.get(HeroViewComp).fac;
|
||||||
|
|
||||||
|
return ecs.query(ecs.allOf(HeroViewComp)).some(e => {
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
return view.fac !== team &&
|
||||||
|
Math.abs(currentPos.x - view.node.position.x) <= range;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +1,33 @@
|
|||||||
|
|
||||||
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas} from "cc";
|
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas} from "cc";
|
||||||
import { UICallbacks } from "../../../../extensions/oops-plugin-framework/assets/core/gui/layer/Defines";
|
|
||||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { UIID } from "../common/config/GameUIConfig";
|
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
import { HeroModelComp } from "./HeroModelComp";
|
import { HeroModelComp } from "./HeroModelComp";
|
||||||
import { HeroSpine } from "./HeroSpine";
|
|
||||||
import { HeroViewComp } from "./HeroViewComp";
|
import { HeroViewComp } from "./HeroViewComp";
|
||||||
import { BoxSet } from "../common/config/BoxSet";
|
import { BoxSet } from "../common/config/BoxSet";
|
||||||
import { RandomManager } from "../../../../extensions/oops-plugin-framework/assets/core/common/random/RandomManager";
|
|
||||||
import { HeroInfo } from "../common/config/heroSet";
|
import { HeroInfo } from "../common/config/heroSet";
|
||||||
import { MoveToComp } from "../common/ecs/position/MoveTo";
|
|
||||||
import { Talents } from "../common/config/TalentSet";
|
import { Talents } from "../common/config/TalentSet";
|
||||||
import { MonModelComp } from "./MonModelComp";
|
import { SkillsComp } from "../skill/SkillSystem";
|
||||||
|
import { BattleMoveComp } from "../common/ecs/position/BattleMoveComp";
|
||||||
/** 角色实体 */
|
/** 角色实体 */
|
||||||
@ecs.register(`Hero`)
|
@ecs.register(`Hero`)
|
||||||
|
|
||||||
export class Hero extends ecs.Entity {
|
export class Hero extends ecs.Entity {
|
||||||
// 数据层
|
|
||||||
HeroModel!: HeroModelComp;
|
HeroModel!: HeroModelComp;
|
||||||
// 视图层
|
HeroView!: HeroViewComp;
|
||||||
HeroView!: HeroViewComp;
|
Skills!: SkillsComp;
|
||||||
|
BattleMove!: BattleMoveComp;
|
||||||
|
|
||||||
protected init() {
|
protected init() {
|
||||||
|
this.addComponents<ecs.Comp>(
|
||||||
|
SkillsComp,
|
||||||
|
BattleMoveComp
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
this.remove(HeroViewComp);
|
this.remove(HeroViewComp);
|
||||||
this.remove(MoveToComp);
|
|
||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,18 +39,14 @@ export class Hero extends ecs.Entity {
|
|||||||
var path = "game/heros/"+HeroInfo[uuid].path;
|
var path = "game/heros/"+HeroInfo[uuid].path;
|
||||||
var prefab: Prefab = oops.res.get(path, Prefab)!;
|
var prefab: Prefab = oops.res.get(path, Prefab)!;
|
||||||
var node = instantiate(prefab);
|
var node = instantiate(prefab);
|
||||||
|
|
||||||
var scene = smc.map.MapView.scene;
|
var scene = smc.map.MapView.scene;
|
||||||
node.parent = scene.entityLayer!.node!
|
node.parent = scene.entityLayer!.node!
|
||||||
|
|
||||||
node.setPosition(pos)
|
node.setPosition(pos)
|
||||||
this.hero_init(uuid,node,scale,box_group,is_call,lv)
|
this.hero_init(uuid,node,scale,box_group,is_call,lv)
|
||||||
oops.message.dispatchEvent("hero_load",this)
|
oops.message.dispatchEvent("hero_load",this)
|
||||||
}
|
}
|
||||||
|
|
||||||
hero_init(uuid:number=1001,node:Node,scale:number=1,box_group=BoxSet.HERO,is_call:boolean=false,lv:number=1){
|
hero_init(uuid:number=1001,node:Node,scale:number=1,box_group=BoxSet.HERO,is_call:boolean=false,lv:number=1){
|
||||||
var hv = node.getComponent(HeroViewComp)!;
|
var hv = node.getComponent(HeroViewComp)!;
|
||||||
// console.log("hero_init",buff)
|
|
||||||
let hero= HeroInfo[uuid] // 共用英雄数据
|
let hero= HeroInfo[uuid] // 共用英雄数据
|
||||||
let role =smc.heros[uuid]
|
let role =smc.heros[uuid]
|
||||||
if(is_call){
|
if(is_call){
|
||||||
@@ -61,6 +54,7 @@ export class Hero extends ecs.Entity {
|
|||||||
}
|
}
|
||||||
let talents=Talents;
|
let talents=Talents;
|
||||||
hv.scale = scale;
|
hv.scale = scale;
|
||||||
|
hv.fac = 0;
|
||||||
hv.box_group = box_group;
|
hv.box_group = box_group;
|
||||||
hv.hero_uuid= uuid;
|
hv.hero_uuid= uuid;
|
||||||
hv.hero_name= hero.name;
|
hv.hero_name= hero.name;
|
||||||
@@ -74,13 +68,11 @@ export class Hero extends ecs.Entity {
|
|||||||
hv.cpw=hero.cpw;
|
hv.cpw=hero.cpw;
|
||||||
hv.dpw=hero.dpw;
|
hv.dpw=hero.dpw;
|
||||||
hv.dopw=hero.dopw;
|
hv.dopw=hero.dopw;
|
||||||
|
|
||||||
hv.lv = role.lv;
|
hv.lv = role.lv;
|
||||||
hv.type = hero.type;
|
hv.type = hero.type;
|
||||||
let slv= Math.floor(( hv.lv) / 5);
|
let slv= Math.floor(( hv.lv) / 5);
|
||||||
let sklv=slv
|
let sklv=slv
|
||||||
if(sklv >= 5) sklv=5;
|
if(sklv >= 5) sklv=5;
|
||||||
|
|
||||||
hv.sk1 = hero.sk1[sklv];
|
hv.sk1 = hero.sk1[sklv];
|
||||||
hv.sk2 = hero.sk2[sklv];
|
hv.sk2 = hero.sk2[sklv];
|
||||||
hv.sk3 = hero.sk3[sklv];
|
hv.sk3 = hero.sk3[sklv];
|
||||||
@@ -104,27 +96,17 @@ export class Hero extends ecs.Entity {
|
|||||||
hv.cexp=hero.cexp
|
hv.cexp=hero.cexp
|
||||||
hv.doexp=hero.doexp
|
hv.doexp=hero.doexp
|
||||||
hv.dexp=hero.dexp;
|
hv.dexp=hero.dexp;
|
||||||
|
|
||||||
this.add(hv);
|
this.add(hv);
|
||||||
|
|
||||||
|
// 初始化多个技能组件
|
||||||
|
const skills = this.get(SkillsComp);
|
||||||
|
|
||||||
|
// 初始化移动参数
|
||||||
|
const move = this.get(BattleMoveComp);
|
||||||
|
move.direction = 1; // 向右移动
|
||||||
|
move.targetX = 800; // 右边界
|
||||||
|
console.log("hero_init",skills,move);
|
||||||
|
|
||||||
}
|
}
|
||||||
set_ratio(uuid:number){
|
|
||||||
let ratio=1;
|
|
||||||
switch (HeroInfo[uuid].level) {
|
|
||||||
case 2:
|
|
||||||
ratio=1.05
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ratio=1.1
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
ratio=1.15
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
ratio=1.2
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ratio=1
|
|
||||||
}
|
|
||||||
return ratio;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -5,19 +5,8 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
|
|||||||
*/
|
*/
|
||||||
@ecs.register('HeroModel')
|
@ecs.register('HeroModel')
|
||||||
export class HeroModelComp extends ecs.Comp {
|
export class HeroModelComp extends ecs.Comp {
|
||||||
/** 角色编号 */
|
|
||||||
id: number = -1;
|
|
||||||
|
|
||||||
/** 角色名 */
|
|
||||||
name: string = "mon";
|
|
||||||
/** speed */
|
|
||||||
// speed: number = 0;
|
|
||||||
/** 动画名资源 */
|
|
||||||
anim: string = "mon";
|
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.id = -1;
|
|
||||||
// this.speed = 0;
|
|
||||||
this.name = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* @Author: dgflash
|
|
||||||
* @Date: 2021-11-18 17:42:59
|
|
||||||
* @LastEditors: dgflash
|
|
||||||
* @LastEditTime: 2022-08-17 12:36:18
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Vec3, _decorator , v3,Collider2D,Contact2DType,Label,RigidBody2D ,Node,Prefab,instantiate,ProgressBar, Component, Material, Sprite, math, clamp, Game, tween} from "cc";
|
import { Vec3, _decorator , v3,Collider2D,Contact2DType,Label,RigidBody2D ,Node,Prefab,instantiate,ProgressBar, Component, Material, Sprite, math, clamp, Game, tween} from "cc";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
@@ -42,11 +36,12 @@ export class HeroViewComp extends CCComp {
|
|||||||
slv:number =1;
|
slv:number =1;
|
||||||
scale: number = 1; /** 角色阵营 1:hero -1 :mon */
|
scale: number = 1; /** 角色阵营 1:hero -1 :mon */
|
||||||
type: number = 0; /**角色类型 0近战 1 远程 2 辅助 */
|
type: number = 0; /**角色类型 0近战 1 远程 2 辅助 */
|
||||||
|
fac:number=0; //阵营 0:hero 1:monster
|
||||||
box_group:number = BoxSet.HERO;
|
box_group:number = BoxSet.HERO;
|
||||||
atk_range:number = 150;
|
atk_range:number = 150;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
is_dead:boolean = false; //是否摧毁
|
is_dead:boolean = false; //是否摧毁
|
||||||
is_stop:boolean = false;
|
is_stop:boolean = false;
|
||||||
is_atking:boolean = false;
|
is_atking:boolean = false;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @Author: dgflash
|
* @Author: dgflash
|
||||||
* @Date: 2021-11-18 17:47:56
|
* @Date: 2021-11-18 17:47:56
|
||||||
@@ -20,6 +19,7 @@ import { HeroInfo } from "../common/config/heroSet";
|
|||||||
import { MoveToComp } from "../common/ecs/position/MoveTo";
|
import { MoveToComp } from "../common/ecs/position/MoveTo";
|
||||||
import { Talents } from "../common/config/TalentSet";
|
import { Talents } from "../common/config/TalentSet";
|
||||||
import { MonModelComp } from "./MonModelComp";
|
import { MonModelComp } from "./MonModelComp";
|
||||||
|
import { BattleMoveComp } from "../common/ecs/position/BattleMoveComp";
|
||||||
/** 角色实体 */
|
/** 角色实体 */
|
||||||
@ecs.register(`Monster`)
|
@ecs.register(`Monster`)
|
||||||
export class Monster extends ecs.Entity {
|
export class Monster extends ecs.Entity {
|
||||||
@@ -45,7 +45,7 @@ export class Monster extends ecs.Entity {
|
|||||||
scale=-1
|
scale=-1
|
||||||
let box_group=BoxSet.MONSTER
|
let box_group=BoxSet.MONSTER
|
||||||
console.log("mon load",uuid)
|
console.log("mon load",uuid)
|
||||||
this.addComponents<ecs.Comp>( MonModelComp);
|
this.addComponents<ecs.Comp>( MonModelComp, BattleMoveComp);
|
||||||
var path = "game/heros/"+HeroInfo[uuid].path;
|
var path = "game/heros/"+HeroInfo[uuid].path;
|
||||||
var prefab: Prefab = oops.res.get(path, Prefab)!;
|
var prefab: Prefab = oops.res.get(path, Prefab)!;
|
||||||
var node = instantiate(prefab);
|
var node = instantiate(prefab);
|
||||||
@@ -55,6 +55,11 @@ export class Monster extends ecs.Entity {
|
|||||||
node.setPosition(pos)
|
node.setPosition(pos)
|
||||||
this.hero_init(uuid,node,scale,box_group,is_boss,is_call,lv)
|
this.hero_init(uuid,node,scale,box_group,is_boss,is_call,lv)
|
||||||
oops.message.dispatchEvent("monster_load",this)
|
oops.message.dispatchEvent("monster_load",this)
|
||||||
|
|
||||||
|
// 初始化移动参数
|
||||||
|
const move = this.get(BattleMoveComp);
|
||||||
|
move.direction = -1; // 向左移动
|
||||||
|
move.targetX = -800; // 左边界
|
||||||
}
|
}
|
||||||
|
|
||||||
hero_init(uuid:number=1001,node:Node,scale:number=1,box_group=BoxSet.HERO,is_boss:boolean=false,is_call:boolean=false,lv:number=1) {
|
hero_init(uuid:number=1001,node:Node,scale:number=1,box_group=BoxSet.HERO,is_boss:boolean=false,is_call:boolean=false,lv:number=1) {
|
||||||
@@ -64,6 +69,7 @@ export class Monster extends ecs.Entity {
|
|||||||
let talent= smc.vmdata.talent //角色英雄数据
|
let talent= smc.vmdata.talent //角色英雄数据
|
||||||
let talents=Talents;
|
let talents=Talents;
|
||||||
hv.scale = scale;
|
hv.scale = scale;
|
||||||
|
hv.fac = 1;
|
||||||
hv.is_boss = is_boss;
|
hv.is_boss = is_boss;
|
||||||
hv.box_group = box_group;
|
hv.box_group = box_group;
|
||||||
hv.hero_uuid= uuid;
|
hv.hero_uuid= uuid;
|
||||||
|
|||||||
9
assets/script/game/module.meta
Normal file
9
assets/script/game/module.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "8003b099-fab7-454f-b142-3f767dc597ee",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.1.0",
|
"ver": "1.2.0",
|
||||||
"importer": "directory",
|
"importer": "directory",
|
||||||
"imported": true,
|
"imported": true,
|
||||||
"uuid": "a80a879f-d214-454c-a574-18f080ae0d91",
|
"uuid": "a80a879f-d214-454c-a574-18f080ae0d91",
|
||||||
|
|||||||
11
assets/script/game/skill/EcsSkillSystem.ts
Normal file
11
assets/script/game/skill/EcsSkillSystem.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
|
import { SkillSystem } from "./SkillSystem";
|
||||||
|
import { SkillAnimationSystem } from "./SkillAnimation";
|
||||||
|
export class EcsSkillSystem extends ecs.System {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.add(new SkillSystem());
|
||||||
|
this.add(new SkillAnimationSystem());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
assets/script/game/skill/EcsSkillSystem.ts.meta
Normal file
9
assets/script/game/skill/EcsSkillSystem.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "ea1f8dae-6593-46bf-b20b-a301b495a434",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
79
assets/script/game/skill/ProjectileComp.ts
Normal file
79
assets/script/game/skill/ProjectileComp.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { Vec3 } from "cc";
|
||||||
|
import { ecs } from "db://oops-framework/libs/ecs/ECS";
|
||||||
|
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||||
|
|
||||||
|
// 投射物组件
|
||||||
|
@ecs.register('Projectile')
|
||||||
|
export class ProjectileComp extends ecs.Comp {
|
||||||
|
speed: number = 500; // 飞行速度
|
||||||
|
direction: Vec3 = Vec3.RIGHT;// 飞行方向
|
||||||
|
maxDistance: number = 1000; // 最大射程
|
||||||
|
traveled: number = 0; // 已飞行距离
|
||||||
|
penetrate: number = 3; // 穿透次数
|
||||||
|
targets = new Set<ecs.Entity>(); // 已命中目标
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.speed = 500;
|
||||||
|
this.direction.set(Vec3.RIGHT);
|
||||||
|
this.maxDistance = 1000;
|
||||||
|
this.traveled = 0;
|
||||||
|
this.penetrate = 3;
|
||||||
|
this.targets.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 投射物系统
|
||||||
|
@ecs.register('ProjectileSystem')
|
||||||
|
export class ProjectileSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(ProjectileComp, HeroViewComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: ecs.Entity): void {
|
||||||
|
const proj = e.get(ProjectileComp);
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
|
||||||
|
// 移动计算
|
||||||
|
const delta = proj.direction.multiplyScalar(proj.speed * this.dt);
|
||||||
|
view.node.position = view.node.position.add(delta);
|
||||||
|
proj.traveled += delta.length();
|
||||||
|
|
||||||
|
// 碰撞检测(使用ECS组件检测)
|
||||||
|
this.checkCollision(e);
|
||||||
|
|
||||||
|
// 超出射程销毁
|
||||||
|
if (proj.traveled >= proj.maxDistance) {
|
||||||
|
e.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkCollision(e: ecs.Entity) {
|
||||||
|
const proj = e.get(ProjectileComp);
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
|
||||||
|
// 获取范围内所有敌人
|
||||||
|
// const enemies = ecs.getEntities(HeroViewComp).filter(entity => {
|
||||||
|
// const enemyView = entity.get(HeroViewComp);
|
||||||
|
// return enemyView.boxGroup !== view.boxGroup &&
|
||||||
|
// Vec3.distance(view.node.position, enemyView.node.position) <= 50; // 碰撞半径
|
||||||
|
// });
|
||||||
|
|
||||||
|
// enemies.forEach(enemy => {
|
||||||
|
// if (!proj.targets.has(enemy)) {
|
||||||
|
// this.applyDamage(e, enemy);
|
||||||
|
// proj.targets.add(enemy);
|
||||||
|
// proj.penetrate--;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
if (proj.penetrate <= 0) {
|
||||||
|
e.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyDamage(projectile: ecs.Entity, target: ecs.Entity) {
|
||||||
|
const projView = projectile.get(HeroViewComp);
|
||||||
|
const targetView = target.get(HeroViewComp);
|
||||||
|
// targetView.takeDamage(projView.attack);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
assets/script/game/skill/ProjectileComp.ts.meta
Normal file
9
assets/script/game/skill/ProjectileComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "f563271b-ee28-4cc0-86ec-6947e9fe454e",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
55
assets/script/game/skill/SkillAnimation.ts
Normal file
55
assets/script/game/skill/SkillAnimation.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { ecs ,} from "db://oops-framework/libs/ecs/ECS";
|
||||||
|
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||||
|
import { SkillsComp } from "./SkillSystem";
|
||||||
|
import { SkillSet } from "../common/config/SkillSet";
|
||||||
|
import { Node } from "cc";
|
||||||
|
|
||||||
|
// 动画组件
|
||||||
|
@ecs.register('SkillAnimation')
|
||||||
|
export class SkillAnimationComp extends ecs.Comp {
|
||||||
|
prefab: Node | null = null; // 预制体实例
|
||||||
|
damageTriggerTime = 0.3; // 伤害触发时间(秒)
|
||||||
|
elapsed = 0; // 已播放时间
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.prefab?.destroy();
|
||||||
|
this.prefab = null;
|
||||||
|
this.damageTriggerTime = 0.3;
|
||||||
|
this.elapsed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动画系统
|
||||||
|
@ecs.register('SkillAnimationSystem')
|
||||||
|
export class SkillAnimationSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(SkillAnimationComp, HeroViewComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: ecs.Entity): void {
|
||||||
|
const anim = e.get(SkillAnimationComp);
|
||||||
|
anim.elapsed += this.dt;
|
||||||
|
|
||||||
|
// 伤害触发检测
|
||||||
|
// if (!anim.hitted && anim.elapsed >= anim.hitTime) {
|
||||||
|
// this.applyDamage(e);
|
||||||
|
// anim.hitted = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 更新动画状态
|
||||||
|
// if (anim.elapsed >= anim.duration) {
|
||||||
|
// e.remove(SkillAnimationComp);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyDamage(e: ecs.Entity) {
|
||||||
|
const skill = e.get(SkillsComp);
|
||||||
|
const view = e.get(HeroViewComp);
|
||||||
|
|
||||||
|
// 添加伤害标记组件
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在角色组件中实现目标查找
|
||||||
|
|
||||||
|
}
|
||||||
9
assets/script/game/skill/SkillAnimation.ts.meta
Normal file
9
assets/script/game/skill/SkillAnimation.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "8c885682-d6d1-4bca-a06b-edb7e1389c08",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
187
assets/script/game/skill/SkillSystem.ts
Normal file
187
assets/script/game/skill/SkillSystem.ts
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
import { Node, Vec3 } from "cc";
|
||||||
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
|
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||||
|
import { SkillSet } from "../common/config/SkillSet";
|
||||||
|
import { SkillAnimationComp } from "./SkillAnimation";
|
||||||
|
import { ProjectileComp } from "./ProjectileComp";
|
||||||
|
|
||||||
|
/** 技能触发组件 */
|
||||||
|
@ecs.register('HerosSkills')
|
||||||
|
export class SkillsComp extends ecs.Comp {
|
||||||
|
/** 技能ID */
|
||||||
|
skillId: number = 0;
|
||||||
|
/** 目标位置/实体 */
|
||||||
|
target: Vec3 | Node | null = null;
|
||||||
|
/** 当前冷却时间 */
|
||||||
|
currentCooldown: number = 0;
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.skillId = 0;
|
||||||
|
this.target = null;
|
||||||
|
this.currentCooldown = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 技能系统 */
|
||||||
|
@ecs.register('SkillSystem')
|
||||||
|
export class SkillSystem extends ecs.ComblockSystem<ecs.Entity> implements ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(SkillsComp, HeroViewComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: ecs.Entity) {
|
||||||
|
let skill = e.get(SkillsComp);
|
||||||
|
let view = e.get(HeroViewComp);
|
||||||
|
|
||||||
|
if (this.canCastSkill(skill, view)) {
|
||||||
|
this.castSkill(e, skill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private canCastSkill(skill: SkillsComp, view: HeroViewComp): boolean {
|
||||||
|
return skill.currentCooldown <= 0 &&
|
||||||
|
view.pw >= view.pwm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private castSkill(entity: ecs.Entity, skill: SkillsComp) {
|
||||||
|
const skillData = SkillSet[skill.skillId];
|
||||||
|
|
||||||
|
// // 创建飞弹实体
|
||||||
|
// const projectile = ecs.createEntity();
|
||||||
|
// const projView = projectile.add(HeroViewComp);
|
||||||
|
// projView.node = instantiate(skillData.prefab);
|
||||||
|
// projView.node.setParent(entity.get(HeroViewComp).node.parent);
|
||||||
|
// projView.node.setPosition(entity.get(HeroViewComp).node.position);
|
||||||
|
|
||||||
|
// // 添加投射物组件
|
||||||
|
// projectile.add(ProjectileComp, {
|
||||||
|
// speed: skillData.speed,
|
||||||
|
// direction: entity.get(HeroViewComp).node.scale.x > 0 ? Vec3.RIGHT : Vec3.LEFT,
|
||||||
|
// maxDistance: skillData.range,
|
||||||
|
// penetrate: skillData.penetrate
|
||||||
|
// });
|
||||||
|
|
||||||
|
// 应用冷却时间
|
||||||
|
skill.currentCooldown = skillData.cooldown;
|
||||||
|
|
||||||
|
// 根据技能类型处理
|
||||||
|
switch(skillData.type) {
|
||||||
|
case 'damage':
|
||||||
|
this.handleDamage(entity, skillData);
|
||||||
|
break;
|
||||||
|
case 'heal':
|
||||||
|
this.handleHeal(entity, skillData);
|
||||||
|
break;
|
||||||
|
case 'projectile':
|
||||||
|
this.castProjectileSkill(entity, skillData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 播放动画(示例)
|
||||||
|
// entity.get(HeroViewComp).playAnimation(skillData.anim);
|
||||||
|
|
||||||
|
// 触发完成回调
|
||||||
|
entity.remove(SkillsComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleDamage(entity: ecs.Entity, data: any) {
|
||||||
|
const view = entity.get(HeroViewComp);
|
||||||
|
// 实现伤害逻辑...
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleHeal(entity: ecs.Entity, data: any) {
|
||||||
|
const view = entity.get(HeroViewComp);
|
||||||
|
// 实现治疗逻辑...
|
||||||
|
}
|
||||||
|
|
||||||
|
private castProjectileSkill(entity: ecs.Entity, skillData: any) {
|
||||||
|
const view = entity.get(HeroViewComp);
|
||||||
|
|
||||||
|
// 创建飞弹实体
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private exit(e: ecs.Entity) {
|
||||||
|
e.remove(SkillsComp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动画系统
|
||||||
|
@ecs.register('SkillAnimationSystem')
|
||||||
|
export class SkillAnimationSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(SkillAnimationComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: ecs.Entity): void {
|
||||||
|
const anim = e.get(SkillAnimationComp);
|
||||||
|
anim.elapsed += this.dt;
|
||||||
|
|
||||||
|
// 触发伤害检测
|
||||||
|
if (anim.elapsed >= anim.damageTriggerTime) {
|
||||||
|
e.add(DamageLineComp); // 添加伤害区域组件
|
||||||
|
e.remove(SkillAnimationComp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直线型伤害区域组件
|
||||||
|
@ecs.register('DamageLine')
|
||||||
|
export class DamageLineComp extends ecs.Comp {
|
||||||
|
startPos: Vec3 = new Vec3();
|
||||||
|
direction: Vec3 = Vec3.RIGHT;
|
||||||
|
length: number = 300;
|
||||||
|
width: number = 50;
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.startPos.set();
|
||||||
|
this.direction.set(Vec3.RIGHT);
|
||||||
|
this.length = 300;
|
||||||
|
this.width = 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直线伤害系统
|
||||||
|
@ecs.register('DamageLineSystem')
|
||||||
|
export class DamageLineSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(DamageLineComp, HeroViewComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: ecs.Entity): void {
|
||||||
|
const line = e.get(DamageLineComp);
|
||||||
|
const caster = e.get(HeroViewComp);
|
||||||
|
|
||||||
|
// 根据角色朝向调整方向
|
||||||
|
line.direction = caster.node.scale.x > 0 ? Vec3.RIGHT : new Vec3(-1, 0, 0);
|
||||||
|
|
||||||
|
// 获取直线区域内的目标
|
||||||
|
const targets = this.getTargetsInLine(
|
||||||
|
caster.node.worldPosition,
|
||||||
|
line.direction,
|
||||||
|
line.length,
|
||||||
|
line.width,
|
||||||
|
caster.box_group
|
||||||
|
);
|
||||||
|
|
||||||
|
// 应用伤害
|
||||||
|
targets.forEach(target => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
e.remove(DamageLineComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTargetsInLine(origin: Vec3, dir: Vec3, length: number, width: number, team: number): ecs.Entity[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private isInLine(origin: Vec3, dir: Vec3, target: Vec3, length: number, width: number): boolean {
|
||||||
|
return false; // 临时返回值保持类型安全
|
||||||
|
// const toTarget = target.subtract(origin);
|
||||||
|
// const projection = Vec3.project(toTarget, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
9
assets/script/game/skill/SkillSystem.ts.meta
Normal file
9
assets/script/game/skill/SkillSystem.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "c927f5c9-45cb-4400-8734-c706e615e4a4",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
357
ecs.md
Normal file
357
ecs.md
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
# 简介
|
||||||
|
libs/ecs 这是一个 Typescript 语言版的Entity-Component-System框架架。
|
||||||
|
|
||||||
|
# 使用说明
|
||||||
|
创建实体
|
||||||
|
```Typescript
|
||||||
|
ecs.getEntity<ecs.Entity>(ecs.Entity);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 组件
|
||||||
|
自定义组件必须继承ecs.Comp,并且需要使用ecs.register注册组件。
|
||||||
|
```TypeScript
|
||||||
|
@ecs.register('Hello')
|
||||||
|
export class HelloComponent extends ecs.Comp {
|
||||||
|
info: string;
|
||||||
|
data: number;
|
||||||
|
|
||||||
|
// 组件被回收前会调用这个方法。
|
||||||
|
reset() {
|
||||||
|
this.info = '';
|
||||||
|
this.data = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ecs.register功能
|
||||||
|
- 能通过```entity.Hello```获得组件对象;
|
||||||
|
- 将组件的构造函数存入ecs上下文中,并且给该类组件分配一个组件id。
|
||||||
|
|
||||||
|
## 实体
|
||||||
|
为了能利用Typescript的类型提示机制,在使用实体的时候需要用户自己继承ecs.Entity。
|
||||||
|
```TypeScript
|
||||||
|
ecs.register('HelloEntity')
|
||||||
|
export class HelloEntity extends ecs.Entity {
|
||||||
|
Hello: HelloComponent; // 这里的Hello要和ecs.register中填入的参数一致
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- 管理子实体
|
||||||
|
```TypeScript
|
||||||
|
// 添加子实体
|
||||||
|
entity.addChild(ecs.Entity);
|
||||||
|
|
||||||
|
// 移除子实体
|
||||||
|
entity.removeChild(ecs.Entity);
|
||||||
|
```
|
||||||
|
|
||||||
|
- 添加组件:
|
||||||
|
```TypeScript
|
||||||
|
entity.add(HelloComponent); // 添加组件时会优先从组件缓存池中获取无用的组件对象,如果没有才会新创建一个组件对象
|
||||||
|
```
|
||||||
|
|
||||||
|
- 添加组件对象:注意,外部创建的组件对象ecs系统不负责回收,需要用户自己管理该组件对象的声明周期。
|
||||||
|
```Typescript
|
||||||
|
let compObj = new HelloComponent();
|
||||||
|
entity.add(compObj)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 删除组件:
|
||||||
|
```TypeScript
|
||||||
|
entity.remove(HelloComponent); // 组件对象会从实体身上移除并放入组件缓存池中
|
||||||
|
```
|
||||||
|
|
||||||
|
- 删除组件但不删除组件对象身上:实际开发中,组件有很多属性,如果删除了后面再添加,属性值还原是个麻烦的问题,
|
||||||
|
remove方法可以删除组件,但是不真正从实体身上移除该组件对象,这样下次重新添加组件时还是会添加那个组件对象。
|
||||||
|
```Typescript
|
||||||
|
entity.remove(HelloComponent, false)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 获得组件对象
|
||||||
|
```TypeScript
|
||||||
|
entity.Hello; // 见上方自定义实体操作
|
||||||
|
|
||||||
|
entity.get(HelloComponent);
|
||||||
|
```
|
||||||
|
|
||||||
|
- 判断是否拥有组件:
|
||||||
|
```TypeScript
|
||||||
|
entity.has(HelloComponent);
|
||||||
|
|
||||||
|
!!entity.Hello;
|
||||||
|
```
|
||||||
|
|
||||||
|
- 销毁实体:
|
||||||
|
```TypeScript
|
||||||
|
entity.destroy() // 销毁实体时会先删除实体身上的所有组件,然后将实体放入实体缓存池中
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实体筛选
|
||||||
|
目前提供了四种类型的筛选能力,但是这四种筛选能力可以组合从而提供更强大的筛选功能。
|
||||||
|
- anyOf: 用来描述包含任意一个这些组件的实体;
|
||||||
|
- allOf: 用来;描述同时包含了这些组件的实体
|
||||||
|
- onlyOf: 用来描述只包含了这些组件的实体;不是特殊情况不建议使用onlyOf,因为onlyOf会监听所有组件的添加和删除事件;
|
||||||
|
- excludeOf: 表示不包含所有这里面的组件(与关系);
|
||||||
|
|
||||||
|
使用方式:
|
||||||
|
|
||||||
|
- 表示同时拥有多个组件
|
||||||
|
```TypeScript
|
||||||
|
ecs.allOf(AComponent, BComponent, CComponent);
|
||||||
|
```
|
||||||
|
- 表示拥有任意一个组件
|
||||||
|
```Typescript
|
||||||
|
ecs.anyOf(AComponent, BComponent);
|
||||||
|
```
|
||||||
|
- 表示拥有某些组件,并且不包含某些组件
|
||||||
|
```Typescript
|
||||||
|
// 不包含CComponent或者DComponent
|
||||||
|
ecs.allOf(AComponent, BComponent).excludeOf(CComponent, DComponent);
|
||||||
|
|
||||||
|
// 不同时包含CComponent和DComponent
|
||||||
|
ecs.allOf(AComponent, BComponent).excludeOf(CComponent).excludeOf(DComponent);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 直接查询并获得实体
|
||||||
|
```Typescript
|
||||||
|
ecs.query(ecs.allOf(Comp1, Comp2))
|
||||||
|
```
|
||||||
|
|
||||||
|
## 系统
|
||||||
|
- ecs.System: 用来组合某一功能所包含的System;
|
||||||
|
- ecs.RootSystem: System的root;
|
||||||
|
- ecs.ComblockSystem: 抽象类,组合式的System。默认情况,如果该System有实体,则每帧都会执行update方法;
|
||||||
|
- ecs.IEntityEnterSystem: 实现这个接口表示关注实体的首次进入;
|
||||||
|
- ecs.IEntityRemoveSystem: 实现这个接口表示关注实体的移除;
|
||||||
|
- ecs.ISystemFirstUpdate: 实现这个接口会在System第一次执行update前执行一次firstUpdate
|
||||||
|
- ecs.ISystemUpdate:实现这个接口会在System中每帧出发update方法
|
||||||
|
|
||||||
|
# 怎么使用
|
||||||
|
1、声明组件
|
||||||
|
```TypeScript
|
||||||
|
@ecs.register('Node')
|
||||||
|
export class NodeComponent extends ecs.Comp {
|
||||||
|
val: cc.Node = null;
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.val = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ecs.reigster('Move')
|
||||||
|
export class MoveComponent extends ecs.Comp {
|
||||||
|
heading: cc.Vec2 = cc.v2();
|
||||||
|
speed: number = 0;
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.heading.x = 0;
|
||||||
|
this.heading.y = 0;
|
||||||
|
this.speed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ecs.register('Transform')
|
||||||
|
export class TransformComponent extends ecs.Comp {
|
||||||
|
position: cc.Vec2 = cc.v2();
|
||||||
|
angle: number;
|
||||||
|
reset() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AvatarEntity extends ecs.Entity {
|
||||||
|
Node: NodeComponent;
|
||||||
|
Move: MoveComponent;
|
||||||
|
Transform: TransformComponent;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2、创建系统
|
||||||
|
```TypeScript
|
||||||
|
export class RoomSystem extends ecs.RootSystem {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.add(new MoveSystem());
|
||||||
|
this.add(new RenderSystem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MoveSystem extends ecs.ComblockSystem<AvatarEntity> implements ecs.IEntityEnterSystem, ecs.ISystemUpdate {
|
||||||
|
init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(MoveComponent, TransformComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实体第一次进入MoveSystem会进入此方法
|
||||||
|
entityEnter(e: AvatarEntity) {
|
||||||
|
e.Move.speed = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每帧都会更新
|
||||||
|
update(e: AvatarEntity) {
|
||||||
|
let moveComp = e.Move; // e.get(MoveComponent);
|
||||||
|
lel position = e.Transform.position;
|
||||||
|
|
||||||
|
position.x += moveComp.heading.x * moveComp.speed * this.dt;
|
||||||
|
position.y += moveComp.heading.y * moveComp.speed * this.dt;
|
||||||
|
|
||||||
|
e.Transform.angle = cc.misc.lerp(e.Transform.angle, Math.atan2(moveComp.speed.y, moveComp.speed.x) * cc.macro.DEG, dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RenderSystem extends ecs.ComblockSystem<AvatarEntity> implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem, ecs.ISystemUpdate {
|
||||||
|
filter(): ecs.IMatcher {
|
||||||
|
return ecs.allOf(NodeComponent, TransformComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实体第一次进入MoveSystem会进入此方法
|
||||||
|
entityEnter(e: AvatarEntity) {
|
||||||
|
e.Node.val.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
entityRemove(e: AvatarEntity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
update(e: AvatarEntity) {
|
||||||
|
e.Node.val.setPosition(e.Transform.position);
|
||||||
|
e.Node.val.angle = e.Transform.angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3、驱动ecs框架
|
||||||
|
```TypeScript
|
||||||
|
const { ccclass, property } = cc._decorator;
|
||||||
|
@ccclass
|
||||||
|
export class GameControllerBehaviour extends Component {
|
||||||
|
rootSystem: RootSystem = null;
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this.rootSystem = new RootSystem();
|
||||||
|
this.rootSystem.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
createAvatar(node: cc.Node) {
|
||||||
|
let entity = ecs.createEntityWithComps<AvatarEntity>(NodeComponent, TransformComponent, MoveComponent);
|
||||||
|
entity.Node.val = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(dt: number) {
|
||||||
|
this.rootSystem.execute(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# 和Cocos Creator的组件混合使用
|
||||||
|
## 创建基类
|
||||||
|
```Typescript
|
||||||
|
import { Component, _decorator } from "cc";
|
||||||
|
import { ecs } from "../../../Libs/ECS";
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
@ccclass('CCComp')
|
||||||
|
export abstract class CCComp extends Component implements ecs.IComp {
|
||||||
|
static tid: number = -1;
|
||||||
|
static compName: string;
|
||||||
|
|
||||||
|
canRecycle: boolean;
|
||||||
|
ent: ecs.Entity;
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this.ent = ecs.createEntity();
|
||||||
|
this.ent.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract reset(): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 创建ecs组件并且赋予序列化的功能,这样就能在Cocos Creator的“属性检查器”上修改参数
|
||||||
|
```Typescript
|
||||||
|
import { _decorator, toDegree, v3, Node, Vec3 } from "cc";
|
||||||
|
import { ecs } from "../../../Libs/ECS";
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
let outV3 = v3();
|
||||||
|
@ccclass('MovementComponent')
|
||||||
|
@ecs.register('Movement')
|
||||||
|
export class MovementComponent extends CCComp {
|
||||||
|
pos: Vec3 = v3();
|
||||||
|
angle: number = 0;
|
||||||
|
speed: number = 0;
|
||||||
|
|
||||||
|
@property
|
||||||
|
acceleration: number = 0;
|
||||||
|
|
||||||
|
@property
|
||||||
|
private _maxSpeed: number = 0;
|
||||||
|
@property
|
||||||
|
set maxSpeed(val: number) {
|
||||||
|
this._maxSpeed = val;
|
||||||
|
}
|
||||||
|
get maxSpeed() {
|
||||||
|
return this._maxSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
heading: Vec3 = v3();
|
||||||
|
|
||||||
|
@property
|
||||||
|
targetHeading: Vec3 = v3();
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
update(dt: number) {
|
||||||
|
if(!Vec3.equals(this.heading, this.targetHeading, 0.01)) {
|
||||||
|
Vec3.subtract(outV3, this.targetHeading, this.heading);
|
||||||
|
outV3.multiplyScalar(0.025);
|
||||||
|
this.heading.add(outV3);
|
||||||
|
this.heading.normalize();
|
||||||
|
this.angle = toDegree(Math.atan2(this.heading.y, this.heading.x)) - 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.speed = Math.min(this.speed + this.acceleration * dt, this._maxSpeed);
|
||||||
|
|
||||||
|
this.pos.add3f(this.heading.x * this.speed * dt, this.heading.y * this.speed * dt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
calcAngle() {
|
||||||
|
this.angle = toDegree(Math.atan2(this.heading.y, this.heading.x)) - 90;
|
||||||
|
return this.angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 创建面向Cocos Creator的组件
|
||||||
|
```Typescript
|
||||||
|
import { Component, _decorator } from "cc";
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
@ccclass('Player')
|
||||||
|
@ecs.register('Player', false)
|
||||||
|
export class Player extends CCComp {
|
||||||
|
@property({
|
||||||
|
type: MovementComponent
|
||||||
|
})
|
||||||
|
movement: MovementComponent;
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
super.onLoad();
|
||||||
|
|
||||||
|
// 添加MovementComponent组件对象
|
||||||
|
this.ent.add(this.movement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# 调试
|
||||||
|
添加如下代码
|
||||||
|
```TypeScript
|
||||||
|
windows['ecs'] = ecs;
|
||||||
Reference in New Issue
Block a user