mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 11:24:46 +00:00
update
This commit is contained in:
parent
72f3d7e880
commit
fb1696d079
@ -1,7 +1,7 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"__type__": "cc.Prefab",
|
"__type__": "cc.Prefab",
|
||||||
"_name": "RoleEntity",
|
"_name": "RolePVPEntity",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"_native": "",
|
"_native": "",
|
||||||
@ -13,7 +13,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Node",
|
"__type__": "cc.Node",
|
||||||
"_name": "RoleEntity",
|
"_name": "RolePVPEntity",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"__editorExtras__": {},
|
"__editorExtras__": {},
|
||||||
"_parent": null,
|
"_parent": null,
|
@ -8,6 +8,6 @@
|
|||||||
],
|
],
|
||||||
"subMetas": {},
|
"subMetas": {},
|
||||||
"userData": {
|
"userData": {
|
||||||
"syncNodeName": "RoleEntity"
|
"syncNodeName": "RolePVPEntity"
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
9
JisolGameCocos/assets/resources/proto.meta
Normal file
9
JisolGameCocos/assets/resources/proto.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "35e11e81-b6f9-4691-9b51-87135d43f671",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
12
JisolGameCocos/assets/resources/proto/GDemo.proto
Normal file
12
JisolGameCocos/assets/resources/proto/GDemo.proto
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option java_package = "cn.jisol.ngame.proto";
|
||||||
|
import "google/protobuf/any.proto";
|
||||||
|
|
||||||
|
//测试输入
|
||||||
|
message GDemoMessage {
|
||||||
|
//是否攻击
|
||||||
|
bool isAttack = 1;
|
||||||
|
//是否奔跑
|
||||||
|
bool isRun = 2;
|
||||||
|
}
|
11
JisolGameCocos/assets/resources/proto/GDemo.proto.meta
Normal file
11
JisolGameCocos/assets/resources/proto/GDemo.proto.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.2",
|
||||||
|
"importer": "text",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "c9f4975a-e568-4d6c-af34-98620327eaf1",
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
@ -23,7 +23,7 @@ class JNGLayer extends JNLayer{
|
|||||||
//重写Socket
|
//重写Socket
|
||||||
class JNGSocket extends JNSocket{
|
class JNGSocket extends JNSocket{
|
||||||
public url() {
|
public url() {
|
||||||
return "ws://localhost:8080/websocket";
|
return "ws://192.168.0.127:8080/websocket";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +71,7 @@ export class JNGLayerBase extends JNLayerBase{
|
|||||||
|
|
||||||
//重写Sync Base
|
//重写Sync Base
|
||||||
export class JNGSyncBase<T> extends JNSyncFrameComponent<T>{
|
export class JNGSyncBase<T> extends JNSyncFrameComponent<T>{
|
||||||
|
onSyncLoad() { }
|
||||||
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T) { }
|
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T) { }
|
||||||
protected getSync(): JNSyncFrame {
|
protected getSync(): JNSyncFrame {
|
||||||
return app.sync
|
return app.sync
|
||||||
@ -80,6 +81,7 @@ export class JNGSyncBase<T> extends JNSyncFrameComponent<T>{
|
|||||||
//重写Sync Proto Base
|
//重写Sync Proto Base
|
||||||
export abstract class JNGSyncProtoBase<T> extends JNSyncFrameProtoComponent<T>{
|
export abstract class JNGSyncProtoBase<T> extends JNSyncFrameProtoComponent<T>{
|
||||||
|
|
||||||
|
onSyncLoad() { }
|
||||||
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T) { }
|
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T) { }
|
||||||
protected getSync(): JNSyncFrame {
|
protected getSync(): JNSyncFrame {
|
||||||
return app.sync
|
return app.sync
|
||||||
@ -94,7 +96,7 @@ export const app = {
|
|||||||
event : EventDispatcher.getIns(), //通知
|
event : EventDispatcher.getIns(), //通知
|
||||||
proto : NGameMessage.getIns(), //消息
|
proto : NGameMessage.getIns(), //消息
|
||||||
api : axios.create({
|
api : axios.create({
|
||||||
baseURL: "http://localhost:8080",
|
baseURL: "http://192.168.0.127:8080",
|
||||||
}), //请求
|
}), //请求
|
||||||
battle : GBattleModeManager.getIns(), //战斗
|
battle : GBattleModeManager.getIns(), //战斗
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ import { _decorator, Component, director, instantiate, Node, Prefab } from 'cc';
|
|||||||
import { app } from './App';
|
import { app } from './App';
|
||||||
import { JNGame } from '../../extensions/ngame/assets/ngame/JNGame';
|
import { JNGame } from '../../extensions/ngame/assets/ngame/JNGame';
|
||||||
import { JNSyncAction } from '../../extensions/ngame/assets/ngame/sync/JNSyncAction';
|
import { JNSyncAction } from '../../extensions/ngame/assets/ngame/sync/JNSyncAction';
|
||||||
|
import JNFrameTween, { JTween } from '../../extensions/ngame/assets/ngame/sync/frame/game/tween/JNFrameTween';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('Main')
|
@ccclass('Main')
|
||||||
@ -15,8 +16,12 @@ export class Main extends Component {
|
|||||||
|
|
||||||
async onLoad(){
|
async onLoad(){
|
||||||
|
|
||||||
|
JTween().start();
|
||||||
|
|
||||||
//加载 APP
|
//加载 APP
|
||||||
await JNGame.Init(app);
|
await JNGame.Init(app,[
|
||||||
|
{path:"proto/GDemo"}
|
||||||
|
]);
|
||||||
|
|
||||||
//发生帧同步开始
|
//发生帧同步开始
|
||||||
app.socket.Send(JNSyncAction.NSyncFrameStart);
|
app.socket.Send(JNSyncAction.NSyncFrameStart);
|
||||||
|
@ -113,7 +113,6 @@ export default class GPVPMode extends GBaseMode{
|
|||||||
return Math.abs((playerXY.y * 1000) - (enumy1XY.y * 1000)) + Math.abs((playerXY.x - enumy1XY.x)) -
|
return Math.abs((playerXY.y * 1000) - (enumy1XY.y * 1000)) + Math.abs((playerXY.x - enumy1XY.x)) -
|
||||||
Math.abs((playerXY.y * 1000) - (enumy2XY.y * 1000)) + Math.abs((playerXY.x - enumy2XY.x))
|
Math.abs((playerXY.y * 1000) - (enumy2XY.y * 1000)) + Math.abs((playerXY.x - enumy2XY.x))
|
||||||
});
|
});
|
||||||
console.log(playerXY,sort[0].tactical.getXY(sort[0].tacticalIndex),);
|
|
||||||
return sort[0]
|
return sort[0]
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
import { Vec2 } from "cc";
|
||||||
import { JNGSyncProtoBase } from "../../App";
|
import { JNGSyncProtoBase } from "../../App";
|
||||||
import GBaseMode from "../GBaseMode";
|
import GBaseMode from "../GBaseMode";
|
||||||
|
import { v2 } from "cc";
|
||||||
|
|
||||||
|
|
||||||
export default class GObject<T> extends JNGSyncProtoBase<T>{
|
export default class GObject<T> extends JNGSyncProtoBase<T>{
|
||||||
@ -14,5 +16,17 @@ export default class GObject<T> extends JNGSyncProtoBase<T>{
|
|||||||
this._mode = value;
|
this._mode = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//设置镜像
|
||||||
|
static SetMirror(role:GObject<{}>,flipX:boolean = true,flipY:boolean = false){
|
||||||
|
let node = role.node;
|
||||||
|
node.setScale(flipX ? -Math.abs(node.scale.x) : Math.abs(node.scale.x),flipY ? -Math.abs(node.scale.y) : Math.abs(node.scale.y))
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取v2世界坐标
|
||||||
|
get v2World():Vec2{
|
||||||
|
let world = this.node.worldPosition;
|
||||||
|
return v2(world.x,world.y);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,11 +12,17 @@ export interface GFSMProcessInfo{
|
|||||||
//模式
|
//模式
|
||||||
mode?:GFSMProcessMode;
|
mode?:GFSMProcessMode;
|
||||||
//执行方法
|
//执行方法
|
||||||
execute?:() => number;
|
execute?:(dt:number,info:GFSMProcessInfo) => number;
|
||||||
//前往
|
//前往
|
||||||
to?:number[];
|
to?:number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//流程枚举
|
||||||
|
export enum GFSMProcessEnum{
|
||||||
|
Reset = -1,//重置
|
||||||
|
Wait = -2,//等待
|
||||||
|
}
|
||||||
|
|
||||||
//状态机基类
|
//状态机基类
|
||||||
export default class GFSMBase{
|
export default class GFSMBase{
|
||||||
|
|
||||||
@ -36,12 +42,12 @@ export default class GFSMBase{
|
|||||||
if(!this.current) this.current = 0;
|
if(!this.current) this.current = 0;
|
||||||
|
|
||||||
//运行流程
|
//运行流程
|
||||||
this.execute(this.process[this.current]);
|
this.execute(this.process[this.current],dt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行流程
|
//执行流程
|
||||||
execute(process:GFSMProcessInfo){
|
execute(process:GFSMProcessInfo,dt:number){
|
||||||
if(!process) return;
|
if(!process) return;
|
||||||
|
|
||||||
process.mode = process.mode || GFSMProcessMode.Execute;
|
process.mode = process.mode || GFSMProcessMode.Execute;
|
||||||
@ -54,26 +60,27 @@ export default class GFSMBase{
|
|||||||
switch(process.mode){
|
switch(process.mode){
|
||||||
case GFSMProcessMode.Execute:
|
case GFSMProcessMode.Execute:
|
||||||
//执行方法
|
//执行方法
|
||||||
next = process.to[process.execute()-1];
|
next = process.execute(dt,process);
|
||||||
break;
|
break;
|
||||||
case GFSMProcessMode.WaitExecute:
|
case GFSMProcessMode.WaitExecute:
|
||||||
//执行等待方法
|
//执行等待方法
|
||||||
let state = process.execute();
|
next = process.execute(dt,process);
|
||||||
//如果 状态 -1 则 不重置 下一次状态从当前开始流程执行
|
//如果 状态 Wait 则 不重置 下一次状态从当前开始流程执行
|
||||||
if(state == -1){
|
if(next == GFSMProcessEnum.Wait){
|
||||||
isReset = false;
|
isReset = false;
|
||||||
}else{
|
|
||||||
next = state;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(process.to.indexOf(next) == -1 && next != GFSMProcessEnum.Wait && next != GFSMProcessEnum.Reset){
|
||||||
|
console.log(`[GFSM]: 流程To中没有这个流程 请检查代码`,process,next);
|
||||||
|
}
|
||||||
if(!this.process[next]) next = null;
|
if(!this.process[next]) next = null;
|
||||||
|
|
||||||
if(next){
|
if(next){
|
||||||
this.current = next;
|
this.current = next;
|
||||||
//运行下一个流程
|
//运行下一个流程
|
||||||
this.execute(this.process[next]);
|
this.execute(this.process[next],dt);
|
||||||
}else{
|
}else{
|
||||||
if(isReset){
|
if(isReset){
|
||||||
//重置
|
//重置
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import GRoleBase from "../role/GRoleBase";
|
|
||||||
import GFSMBase, { GFSMProcessInfo } from "./GFSMBase";
|
|
||||||
|
|
||||||
|
|
||||||
export default abstract class GFSMBattle extends GFSMBase{
|
|
||||||
|
|
||||||
//流程图
|
|
||||||
process: { [key: number]: GFSMProcessInfo; } = {
|
|
||||||
0:{
|
|
||||||
title:"寻找敌人",
|
|
||||||
execute: this.onSeekEnemyProcess.bind(this),
|
|
||||||
to:[1]
|
|
||||||
},
|
|
||||||
1:{
|
|
||||||
title:"攻击敌人",
|
|
||||||
execute: this.onAttackProcess.bind(this),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//锁定的敌人
|
|
||||||
enemy:GRoleBase<any>;
|
|
||||||
|
|
||||||
|
|
||||||
abstract onSeekEnemy():GRoleBase<any>;
|
|
||||||
|
|
||||||
//寻敌流程
|
|
||||||
onSeekEnemyProcess():number{
|
|
||||||
|
|
||||||
if(this.enemy){
|
|
||||||
//如果有敌人 直接 攻击
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.enemy = this.onSeekEnemy()){
|
|
||||||
//如果有敌人 直接 攻击
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//负责继续寻敌
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract onAttack();
|
|
||||||
|
|
||||||
//攻击敌人
|
|
||||||
onAttackProcess(){
|
|
||||||
this.onAttack();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
import GRoleBase from "../../role/GRoleBase";
|
import GRoleBase from "../../role/GRoleBase";
|
||||||
import GRolePVPEntity from "../../role/PVP/GRolePVPEntity";
|
import GRolePVPEntity from "../../role/PVP/GRolePVPEntity";
|
||||||
import GFSMBattle from "../GFSMBattle";
|
import GFSMBattle from "../base/GFSMBattle/GFSMBattle";
|
||||||
|
|
||||||
|
|
||||||
//PVP 状态机
|
//PVP 状态机
|
||||||
@ -9,7 +9,7 @@ export default class GFSMPVP extends GFSMBattle{
|
|||||||
player:GRolePVPEntity;
|
player:GRolePVPEntity;
|
||||||
|
|
||||||
constructor(player:GRolePVPEntity){
|
constructor(player:GRolePVPEntity){
|
||||||
super();
|
super(player);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,8 +18,5 @@ export default class GFSMPVP extends GFSMBattle{
|
|||||||
return this.player.mode.getEnumy(this.player);
|
return this.player.mode.getEnumy(this.player);
|
||||||
}
|
}
|
||||||
|
|
||||||
//攻击
|
|
||||||
onAttack() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
import { GFSMBattleAmin } from "../base/GFSMBattle/GFSMBattleAmin";
|
||||||
|
|
||||||
|
export default class GFSMPVPAnim extends GFSMBattleAmin{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "3a061d5f-a202-4d3d-8758-1d1afbe1cd15",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
9
JisolGameCocos/assets/script/battle/base/fsm/base.meta
Normal file
9
JisolGameCocos/assets/script/battle/base/fsm/base.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "552fd09c-0320-46c9-ac7a-abe954b75093",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "05230b14-5c88-45fd-99c6-31b4b0513f45",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
import { Vec2 } from "cc";
|
||||||
|
import GRoleBase from "../../../role/GRoleBase";
|
||||||
|
import GFSMBase, { GFSMProcessEnum, GFSMProcessInfo, GFSMProcessMode } from "../../GFSMBase";
|
||||||
|
|
||||||
|
|
||||||
|
//流程枚举
|
||||||
|
enum ProcessEnum {
|
||||||
|
//寻找敌人
|
||||||
|
SeekEnemy = 0,
|
||||||
|
//移动到可攻击范围
|
||||||
|
MoveToAttackRange = 1,
|
||||||
|
//攻击敌人
|
||||||
|
AttackEnemy = 2,
|
||||||
|
//回阵型
|
||||||
|
MoveToTactical = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default abstract class GFSMBattle extends GFSMBase{
|
||||||
|
|
||||||
|
player:GRoleBase<{}>;
|
||||||
|
|
||||||
|
//流程图
|
||||||
|
process: { [key: number]: GFSMProcessInfo; } = {
|
||||||
|
[ProcessEnum.SeekEnemy]:{
|
||||||
|
title:"寻找敌人",
|
||||||
|
execute: this.onSeekEnemyProcess.bind(this),
|
||||||
|
// to:[ProcessEnum.MoveToAttackRange], //移动到可攻击范围
|
||||||
|
to:[ProcessEnum.AttackEnemy], //移动到可攻击范围
|
||||||
|
},
|
||||||
|
[ProcessEnum.MoveToAttackRange]:{
|
||||||
|
title:"移动到可攻击范围",
|
||||||
|
mode:GFSMProcessMode.WaitExecute,
|
||||||
|
execute: this.onMoveToAttackRangeProcess.bind(this),
|
||||||
|
to:[ProcessEnum.AttackEnemy,ProcessEnum.MoveToTactical] //攻击敌人 回阵型
|
||||||
|
},
|
||||||
|
[ProcessEnum.AttackEnemy]:{
|
||||||
|
title:"攻击敌人",
|
||||||
|
mode:GFSMProcessMode.WaitExecute,
|
||||||
|
execute: this.onAttackProcess.bind(this),
|
||||||
|
},
|
||||||
|
[ProcessEnum.MoveToTactical]:{
|
||||||
|
title:"移动回阵型",
|
||||||
|
mode:GFSMProcessMode.WaitExecute,
|
||||||
|
execute: this.onMoveToTacticalProcess.bind(this),
|
||||||
|
to:[ProcessEnum.SeekEnemy], //寻找敌人
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//锁定的敌人
|
||||||
|
enemy:GRoleBase<any>;
|
||||||
|
|
||||||
|
constructor(player:GRoleBase<{}>){
|
||||||
|
super();
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract onSeekEnemy():GRoleBase<any>;
|
||||||
|
|
||||||
|
//寻敌流程
|
||||||
|
onSeekEnemyProcess(dt:number):number{
|
||||||
|
|
||||||
|
if(this.enemy){
|
||||||
|
//如果有敌人 直接 攻击
|
||||||
|
return ProcessEnum.MoveToAttackRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.enemy = this.onSeekEnemy()){
|
||||||
|
//如果有敌人 直接 攻击
|
||||||
|
return ProcessEnum.MoveToAttackRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
//负责继续寻敌
|
||||||
|
return GFSMProcessEnum.Reset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//移动可攻击范围
|
||||||
|
onMoveToAttackRangeProcess(){
|
||||||
|
|
||||||
|
//如果没有敌人则回阵型
|
||||||
|
if(!this.enemy) return ProcessEnum.MoveToTactical;
|
||||||
|
|
||||||
|
let distance = Vec2.distance(this.player.v2World,this.enemy.v2World);
|
||||||
|
|
||||||
|
//如果在攻击范围则调用攻击 负责 靠近目标
|
||||||
|
if(distance < this.player.range){
|
||||||
|
return ProcessEnum.AttackEnemy;
|
||||||
|
}else{
|
||||||
|
//靠近目标
|
||||||
|
// this.player.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//移动回阵型
|
||||||
|
onMoveToTacticalProcess(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onAttack(dt:number){
|
||||||
|
this.player.onAttackUpdate(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
//攻击敌人
|
||||||
|
onAttackProcess(dt:number){
|
||||||
|
this.onAttack(dt);
|
||||||
|
return GFSMProcessEnum.Reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
"ver": "4.0.23",
|
"ver": "4.0.23",
|
||||||
"importer": "typescript",
|
"importer": "typescript",
|
||||||
"imported": true,
|
"imported": true,
|
||||||
"uuid": "ac1a0b3b-e57a-4718-a27f-39b8e072f74e",
|
"uuid": "8c02bc4d-30d6-47fe-82ff-e5496d4dca8f",
|
||||||
"files": [],
|
"files": [],
|
||||||
"subMetas": {},
|
"subMetas": {},
|
||||||
"userData": {}
|
"userData": {}
|
@ -0,0 +1,135 @@
|
|||||||
|
import { sp } from "cc";
|
||||||
|
import GFSMBase, { GFSMProcessEnum, GFSMProcessInfo, GFSMProcessMode } from "../../GFSMBase";
|
||||||
|
|
||||||
|
//角色动画名称枚举
|
||||||
|
export enum GFSMBattleAminEnum {
|
||||||
|
Wait = "std", //等待
|
||||||
|
Walk = "walk", //移动
|
||||||
|
Attack = "atk", //攻击
|
||||||
|
Fly = "jifei", //击飞
|
||||||
|
Skill = "jifei", //技能
|
||||||
|
}
|
||||||
|
|
||||||
|
//动画流程信息
|
||||||
|
export interface GFSMProcessAnimInfo extends GFSMProcessInfo{
|
||||||
|
//动画名称
|
||||||
|
animName:string;
|
||||||
|
//是否循环播放
|
||||||
|
isLoop?:boolean;
|
||||||
|
//与下一个动作的融合值
|
||||||
|
mixs?:number[];
|
||||||
|
//播放的轨道
|
||||||
|
track?:sp.spine.TrackEntry;
|
||||||
|
ifTo?:(() => boolean)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
//流程枚举
|
||||||
|
enum ProcessEnum {
|
||||||
|
//等待
|
||||||
|
Wait = 0,
|
||||||
|
//移动
|
||||||
|
Move = 1,
|
||||||
|
//攻击
|
||||||
|
Attack = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
//动画状态机基类
|
||||||
|
export class GFSMBattleAmin extends GFSMBase{
|
||||||
|
|
||||||
|
//是否攻击
|
||||||
|
isAttack:boolean = false;
|
||||||
|
|
||||||
|
//是否移动
|
||||||
|
isMove:boolean = false;
|
||||||
|
|
||||||
|
//轨道的索引
|
||||||
|
trackIndex:number;
|
||||||
|
|
||||||
|
//动画Root
|
||||||
|
spine:sp.Skeleton;
|
||||||
|
|
||||||
|
constructor(spine:sp.Skeleton,trackIndex?:number){
|
||||||
|
super();
|
||||||
|
this.spine = spine;
|
||||||
|
this.trackIndex = trackIndex || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 流程图
|
||||||
|
process: { [key: number]: GFSMProcessAnimInfo; } = {
|
||||||
|
[ProcessEnum.Wait]:{
|
||||||
|
title:"等待",
|
||||||
|
isLoop:true,
|
||||||
|
animName:GFSMBattleAminEnum.Wait,
|
||||||
|
mixs:[0.1,0.1],
|
||||||
|
to:[ProcessEnum.Move,ProcessEnum.Attack],
|
||||||
|
ifTo:[
|
||||||
|
() => this.isMove, //前往移动
|
||||||
|
() => this.isAttack //前往攻击
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[ProcessEnum.Move]:{
|
||||||
|
title:"移动",
|
||||||
|
animName:GFSMBattleAminEnum.Walk,
|
||||||
|
isLoop:true,
|
||||||
|
mixs:[0.1,0.1],
|
||||||
|
to:[ProcessEnum.Wait,ProcessEnum.Attack],
|
||||||
|
ifTo:[
|
||||||
|
() => !this.isMove, //前往等待
|
||||||
|
() => this.isAttack, //前往攻击
|
||||||
|
],
|
||||||
|
},
|
||||||
|
2:{
|
||||||
|
title:"攻击",
|
||||||
|
animName:GFSMBattleAminEnum.Attack,
|
||||||
|
isLoop:true,
|
||||||
|
mixs:[0.1,0.1],
|
||||||
|
to:[ProcessEnum.Wait,ProcessEnum.Move],
|
||||||
|
ifTo:[
|
||||||
|
() => !this.isAttack, //前往等待
|
||||||
|
() => !this.isAttack && this.isMove, //前往移动
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(process:GFSMProcessAnimInfo,dt:number){
|
||||||
|
process.mode = GFSMProcessMode.WaitExecute;
|
||||||
|
process.execute = this.tick.bind(this);
|
||||||
|
super.execute(process,dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-1 继续播放 0 重新执行流程 * 指定分支
|
||||||
|
tick(dt:number,info:GFSMProcessAnimInfo){
|
||||||
|
|
||||||
|
//判断是否会切换动画 (默认不切换)
|
||||||
|
let to = GFSMProcessEnum.Wait;
|
||||||
|
info.ifTo.forEach((run,index) => {
|
||||||
|
if(run()){
|
||||||
|
to = info.to[index];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(to >= 0) {
|
||||||
|
//和下一个动作融合
|
||||||
|
let mix = info.mixs[to - 1] || 0;
|
||||||
|
if(mix){
|
||||||
|
//设置融合
|
||||||
|
this.spine.setMix(info.animName,this.process[to].animName,mix);
|
||||||
|
}
|
||||||
|
info.track = null;
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
//播放动画
|
||||||
|
if(!info.track){
|
||||||
|
console.log("播放动画",info);
|
||||||
|
info.track = this.spine.setAnimation(this.trackIndex,info.animName,info.isLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return to;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "559e87e4-5a3f-4cc2-873d-e0fb5b61375b",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
@ -2,6 +2,10 @@ import { _decorator, sp } from "cc";
|
|||||||
import GObject from "../GObject";
|
import GObject from "../GObject";
|
||||||
import { JNFrameInfo } from "../../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame";
|
import { JNFrameInfo } from "../../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame";
|
||||||
import GFSMBase from "../fsm/GFSMBase";
|
import GFSMBase from "../fsm/GFSMBase";
|
||||||
|
import GFSMBattle from "../fsm/base/GFSMBattle/GFSMBattle";
|
||||||
|
import { GFSMBattleAmin } from "../fsm/base/GFSMBattle/GFSMBattleAmin";
|
||||||
|
import { Vec2 } from "cc";
|
||||||
|
import { v2 } from "cc";
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
//角色基类
|
//角色基类
|
||||||
@ -11,9 +15,31 @@ export default abstract class GRoleBase<T> extends GObject<T>{
|
|||||||
spine:sp.Skeleton;
|
spine:sp.Skeleton;
|
||||||
|
|
||||||
//状态机
|
//状态机
|
||||||
fsm:GFSMBase;
|
fsm:GFSMBattle;
|
||||||
|
|
||||||
|
//动画状态机
|
||||||
|
fsmAnim:GFSMBattleAmin;
|
||||||
|
|
||||||
|
//玩家是否镜像
|
||||||
|
_isMirror:boolean = false;
|
||||||
|
|
||||||
|
//玩家攻击范围
|
||||||
|
range:number = 10;
|
||||||
|
|
||||||
|
get isMirror(){
|
||||||
|
return this._isMirror;
|
||||||
|
}
|
||||||
|
set isMirror(value:boolean){
|
||||||
|
if(value){
|
||||||
|
GObject.SetMirror(this);
|
||||||
|
}else{
|
||||||
|
GObject.SetMirror(this,false);
|
||||||
|
}
|
||||||
|
this._isMirror = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSyncLoad(){
|
||||||
|
|
||||||
onLoad(){
|
|
||||||
if(!this.spine) this.spine = this.node.getComponent(sp.Skeleton);
|
if(!this.spine) this.spine = this.node.getComponent(sp.Skeleton);
|
||||||
//如果没有生成则直接销毁
|
//如果没有生成则直接销毁
|
||||||
if(!this.spine) {
|
if(!this.spine) {
|
||||||
@ -23,15 +49,26 @@ export default abstract class GRoleBase<T> extends GObject<T>{
|
|||||||
|
|
||||||
//创建角色状态机
|
//创建角色状态机
|
||||||
this.fsm = this.fsmCreate();
|
this.fsm = this.fsmCreate();
|
||||||
|
//创建角色动画状态机
|
||||||
|
this.fsmAnim = this.fsmAnimCreate();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//创建一个状态机
|
//创建一个状态机
|
||||||
protected abstract fsmCreate():GFSMBase;
|
protected abstract fsmCreate():GFSMBattle;
|
||||||
|
//创建一个动画状态机
|
||||||
|
protected abstract fsmAnimCreate():GFSMBattleAmin;
|
||||||
|
|
||||||
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T){
|
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: T){
|
||||||
//更新状态机
|
//更新状态机
|
||||||
this.fsm.onUpdate(dt);
|
this.fsm && this.fsm.onUpdate(dt);
|
||||||
|
this.fsmAnim && this.fsmAnim.onUpdate(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
//普攻更新
|
||||||
|
onAttackUpdate(dt:number){
|
||||||
|
|
||||||
|
this.fsmAnim.isAttack = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,19 +4,54 @@ import GFSMBase from "../../fsm/GFSMBase";
|
|||||||
import GFSMPVP from "../../fsm/PVP/GFSMPVP";
|
import GFSMPVP from "../../fsm/PVP/GFSMPVP";
|
||||||
import GPVPMode, { GPVPModePlayerEnum } from "../../../PVP/GPVPMode";
|
import GPVPMode, { GPVPModePlayerEnum } from "../../../PVP/GPVPMode";
|
||||||
import { GTactical } from "../../../entity/GTactical";
|
import { GTactical } from "../../../entity/GTactical";
|
||||||
|
import { GFSMBattleAmin } from "../../fsm/base/GFSMBattle/GFSMBattleAmin";
|
||||||
|
import { JNFrameInfo } from "../../../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame";
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
export interface GDemoMessage{
|
||||||
|
isAttack?:boolean;
|
||||||
|
isRun?:boolean;
|
||||||
|
}
|
||||||
|
|
||||||
//PVP 角色
|
//PVP 角色
|
||||||
@ccclass('GRolePVPEntity')
|
@ccclass('GRolePVPEntity')
|
||||||
export default class GRolePVPEntity extends GRoleBase<{}>{
|
export default class GRolePVPEntity extends GRoleBase<GDemoMessage>{
|
||||||
|
|
||||||
//所属阵容
|
//所属阵容
|
||||||
ones:GPVPModePlayerEnum;
|
_ones:GPVPModePlayerEnum;
|
||||||
|
|
||||||
|
get ones():GPVPModePlayerEnum{
|
||||||
|
return this._ones;
|
||||||
|
}
|
||||||
|
set ones(value:GPVPModePlayerEnum){
|
||||||
|
//如果是敌方则设置镜像
|
||||||
|
if(value == GPVPModePlayerEnum.ENEMY){
|
||||||
|
this.isMirror = true;
|
||||||
|
}else{
|
||||||
|
this.isMirror = false;
|
||||||
|
}
|
||||||
|
this._ones = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//攻击距离
|
||||||
|
|
||||||
//在阵容中的下标
|
//在阵容中的下标
|
||||||
tacticalIndex:number;
|
tacticalIndex:number;
|
||||||
tactical:GTactical;
|
tactical:GTactical;
|
||||||
|
|
||||||
|
getClassName():string{return "GDemoMessage"}
|
||||||
|
onSyncUpdate(dt: number,frame:JNFrameInfo, input?: GDemoMessage) {
|
||||||
|
super.onSyncUpdate(dt,frame,input);
|
||||||
|
if(input){
|
||||||
|
if(Object.prototype.hasOwnProperty.call(input,"isAttack")){
|
||||||
|
this.fsmAnim.isAttack = input.isAttack;
|
||||||
|
}
|
||||||
|
if(Object.prototype.hasOwnProperty.call(input,"isRun")){
|
||||||
|
this.fsmAnim.isMove = input.isRun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
get mode():GPVPMode{
|
get mode():GPVPMode{
|
||||||
return super.mode as GPVPMode;
|
return super.mode as GPVPMode;
|
||||||
@ -25,9 +60,13 @@ export default class GRolePVPEntity extends GRoleBase<{}>{
|
|||||||
this._mode = value;
|
this._mode = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fsmCreate(): GFSMBase {
|
protected fsmCreate(): GFSMPVP {
|
||||||
|
return null;
|
||||||
return new GFSMPVP(this);
|
return new GFSMPVP(this);
|
||||||
}
|
}
|
||||||
|
protected fsmAnimCreate(): GFSMBattleAmin {
|
||||||
|
return new GFSMBattleAmin(this.spine);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { _decorator, Component, Label, Node } from 'cc';
|
import { _decorator, Component, Label, Node } from 'cc';
|
||||||
import { app, JNGLayerBase } from '../../App';
|
import { app, JNGLayerBase } from '../../App';
|
||||||
|
import { director } from 'cc';
|
||||||
|
import GRolePVPEntity from '../../battle/base/role/PVP/GRolePVPEntity';
|
||||||
|
import { Toggle } from 'cc';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('HomeView')
|
@ccclass('HomeView')
|
||||||
@ -12,6 +15,21 @@ export class HomeView extends JNGLayerBase {
|
|||||||
this.frameText.string = `当前帧数: ${app.sync.frame}`;
|
this.frameText.string = `当前帧数: ${app.sync.frame}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//设置移动
|
||||||
|
setRoleMove(data:Toggle){
|
||||||
|
console.log("移动",data.isChecked);
|
||||||
|
director.getScene().getComponentsInChildren(GRolePVPEntity).forEach((role) => {
|
||||||
|
role.input.isRun = data.isChecked;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//设置攻击
|
||||||
|
setRoleAttack(data){
|
||||||
|
console.log("攻击",data.isChecked);
|
||||||
|
director.getScene().getComponentsInChildren(GRolePVPEntity).forEach((role) => {
|
||||||
|
role.input.isAttack = data.isChecked;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user