import { _decorator, sp } from "cc"; import GObject, { GTowards } from "../GObject"; import { JNFrameInfo } from "../../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame"; import GFSMBattle from "../fsm/base/GFSMBattle/GFSMBattle"; import { GFSMBattleAmin, GFSMBattleAminEnum } from "../fsm/base/GFSMBattle/GFSMBattleAmin"; import { Vec2 } from "cc"; import { v3 } from "cc"; import { GTactical } from "../../entity/GTactical"; import { JEasing, JTween } from "../../../../../extensions/ngame/assets/ngame/sync/frame/game/tween/JNFrameTween"; import { v2 } from "cc"; import GRole from "../../entity/GRole"; import { app } from "../../../App"; import { TableGRoleAttack } from "../../../../resources/config/ts/TableGRoleAttack"; import { GAttack, GAttackBase } from "../attack/GAttack"; const { ccclass, property } = _decorator; export enum GRoleAnimEvent{ Attack = "attack", //普通攻击 } //角色基类 export default abstract class GRoleBase extends GObject{ @property(sp.Skeleton) spine:sp.Skeleton; //角色 role:GRole //状态机 fsm:GFSMBattle; //动画状态机 fsmAnim:GFSMBattleAmin; //玩家攻击范围 range:number = 100; //移动速度 moveSpeed:number = 80; //在阵容中的下标 tacticalIndex:number; //阵容 _tactical:GTactical; get tactical(){return this._tactical}; set tactical(value:GTactical){ this.setTowards(value.towards); this._tactical = value; } //阵容位置 _tacticalPos:Vec2; get tacticalPos(){ return this._tacticalPos} set tacticalPos(value:Vec2){ this._tacticalPos = value} //血量 blood:number = 100; fullBlood:number = 100; //是否死亡 _isDie:boolean = false; get isDie(){ return this._isDie} set isDie(value:boolean){ this._isDie = value; //设置死亡状态 this.fsmAnim.isDie = value; } get():GRoleBase{ if(this.isDie) return null; return this; } onSyncLoad(){ if(!this.spine) this.spine = this.node.getComponent(sp.Skeleton); //如果没有生成则直接销毁 if(!this.spine) { this.node.removeFromParent(); return; } this.spine.debugBones = true; this.bind(this.role); //创建角色状态机 this.fsm = this.fsmCreate(); //创建角色动画状态机 this.fsmAnim = this.fsmAnimCreate(); //监听攻击 this.fsmAnim.addEventListener(GRoleAnimEvent.Attack,this.onAttack.bind(this)); //监听死亡击飞 this.fsmAnim.addStartListener(GFSMBattleAminEnum.Fly,this.onFly.bind(this)); } //设置角色 bind(role:GRole){ if(this.spine) this.spine.skeletonData = app.role.skData[role.id]; this.range = role.range; //设置攻击范围 this.role = role; } //创建一个状态机 protected abstract fsmCreate():GFSMBattle; //创建一个动画状态机 protected abstract fsmAnimCreate():GFSMBattleAmin; onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T){ //更新状态机 this.fsm && this.fsm.onUpdate(dt / 1000); this.fsmAnim && this.fsmAnim.onUpdate(dt / 1000); } //向目标点移动 onMoveTarget(target:Vec2,dt:number){ //获取两个坐标差值向量 let mins = this.v2World.subtract(target); let normal = this.v2World.subtract(target).normalize(); //设置朝向 if(normal.x != 0){ if(normal.x < 0){ this.setTowards(GTowards.RIGHT) }else{ this.setTowards(GTowards.LEFT) } } if(Vec2.len(normal) >= Vec2.len(mins)){ this.node.setWorldPosition(Object.assign(v3(),target.clone())); return true; }else{ //移动 this.node.worldPosition = this.node.worldPosition.subtract(v3(normal.x*dt*this.moveSpeed,normal.y*dt*this.moveSpeed,0)) return false; } } //攻击 onAttack(){ //敌人扣血 let info = TableGRoleAttack.getConfig(this.role.id); (new GAttack[info.attackWay]()).attack(this,info); } //受击 onHit(){ this.blood-=50; //检测是否死亡 if(this.blood <= 0){ //关闭状态机 this.fsm.close(); //设置死亡 this.isDie = true; } } //击飞 onFly(){ console.log("onFly"); let vWorld = this.node.worldPosition; let vEndWorld = this.getWorldBackLen(v2(800,500)); JTween(vWorld) .to({x:vEndWorld.x},500) .onUpdate(pos => this.node.worldPosition = vWorld) .start(); JTween(vWorld) .to({y:vEndWorld.y},500) .easing(JEasing.Circular.Out) .onUpdate(pos => this.node.worldPosition = vWorld) .start(); } //恢复阵容朝向 onRecoverTacticalTowards(){ this.setTowards(this.tactical.towards); } }