update
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"extends": "@antfu",
|
||||
"rules": {
|
||||
"curly": "off",
|
||||
"no-console": "off",
|
||||
"no-cond-assign": "off",
|
||||
"no-useless-call": "off",
|
||||
"@typescript-eslint/brace-style": "off",
|
||||
"@typescript-eslint/consistent-type-imports": "off"
|
||||
}
|
||||
}
|
@@ -1887,7 +1887,7 @@
|
||||
},
|
||||
"component": "",
|
||||
"_componentId": "a14b40zxfhFXKk12/1/OrYr",
|
||||
"handler": "createRoom",
|
||||
"handler": "handleCreateRoom",
|
||||
"customEventData": ""
|
||||
},
|
||||
{
|
||||
|
@@ -1255,7 +1255,7 @@
|
||||
}
|
||||
],
|
||||
"_interactable": true,
|
||||
"_transition": 0,
|
||||
"_transition": 3,
|
||||
"_normalColor": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 214,
|
||||
@@ -1301,7 +1301,7 @@
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_duration": 0.1,
|
||||
"_zoomScale": 1.2,
|
||||
"_zoomScale": 0.9,
|
||||
"_target": {
|
||||
"__id__": 30
|
||||
},
|
||||
@@ -1549,7 +1549,7 @@
|
||||
}
|
||||
],
|
||||
"_interactable": true,
|
||||
"_transition": 0,
|
||||
"_transition": 3,
|
||||
"_normalColor": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 214,
|
||||
@@ -1595,7 +1595,7 @@
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_duration": 0.1,
|
||||
"_zoomScale": 1.2,
|
||||
"_zoomScale": 0.9,
|
||||
"_target": {
|
||||
"__id__": 38
|
||||
},
|
||||
|
@@ -1,22 +1,21 @@
|
||||
import { _decorator, Component } from 'cc';
|
||||
import { EntityStateEnum } from '../Enum';
|
||||
import StateMachine from './StateMachine';
|
||||
import { _decorator, Component } from "cc";
|
||||
import { EntityStateEnum } from "../Enum";
|
||||
import StateMachine from "./StateMachine";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('EntityManager')
|
||||
@ccclass("EntityManager")
|
||||
export abstract class EntityManager extends Component {
|
||||
fsm: StateMachine
|
||||
private _state: EntityStateEnum
|
||||
fsm: StateMachine;
|
||||
private _state: EntityStateEnum;
|
||||
|
||||
get state() {
|
||||
return this._state
|
||||
return this._state;
|
||||
}
|
||||
|
||||
set state(newState) {
|
||||
this._state = newState
|
||||
this.fsm.setParams(newState, true)
|
||||
this._state = newState;
|
||||
this.fsm.setParams(newState, true);
|
||||
}
|
||||
|
||||
abstract init(...args: any[]): void
|
||||
abstract init(...args: any[]): void;
|
||||
}
|
||||
|
||||
|
@@ -1,13 +1,12 @@
|
||||
export default class Singleton {
|
||||
private static _instance: any = null
|
||||
private static _instance: any = null;
|
||||
|
||||
static GetInstance<T>(): T {
|
||||
if (this._instance === null) {
|
||||
this._instance = new this()
|
||||
this._instance = new this();
|
||||
}
|
||||
return this._instance
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
protected constructor() {
|
||||
}
|
||||
}
|
||||
protected constructor() {}
|
||||
}
|
||||
|
@@ -1,48 +1,45 @@
|
||||
import { animation, AnimationClip, Sprite, SpriteFrame } from 'cc'
|
||||
import DataManager from '../Global/DataManager'
|
||||
import { ResourceManager } from '../Global/ResourceManager'
|
||||
import { sortSpriteFrame } from '../Utils'
|
||||
import StateMachine from './StateMachine'
|
||||
import { animation, AnimationClip, Sprite, SpriteFrame } from "cc";
|
||||
import DataManager from "../Global/DataManager";
|
||||
import { ResourceManager } from "../Global/ResourceManager";
|
||||
import { sortSpriteFrame } from "../Utils";
|
||||
import StateMachine from "./StateMachine";
|
||||
|
||||
/***
|
||||
* unit:milisecond
|
||||
*/
|
||||
export const ANIMATION_SPEED = 1 / 10
|
||||
export const ANIMATION_SPEED = 1 / 10;
|
||||
|
||||
/***
|
||||
* 状态(每组动画的承载容器,持有SpriteAnimation组件执行播放)
|
||||
*/
|
||||
export default class State {
|
||||
private animationClip: AnimationClip
|
||||
private animationClip: AnimationClip;
|
||||
constructor(
|
||||
private fsm: StateMachine,
|
||||
private path: string,
|
||||
private wrapMode: AnimationClip.WrapMode = AnimationClip.WrapMode.Normal,
|
||||
private force: boolean = false,
|
||||
private force: boolean = false
|
||||
) {
|
||||
//生成动画轨道属性
|
||||
const track = new animation.ObjectTrack()
|
||||
track.path = new animation.TrackPath().toComponent(Sprite).toProperty('spriteFrame')
|
||||
const spriteFrames = DataManager.Instance.textureMap.get(this.path)
|
||||
const frames: Array<[number, SpriteFrame]> = sortSpriteFrame(spriteFrames).map((item, index) => [
|
||||
index * ANIMATION_SPEED,
|
||||
item,
|
||||
])
|
||||
track.channel.curve.assignSorted(frames)
|
||||
const track = new animation.ObjectTrack();
|
||||
track.path = new animation.TrackPath().toComponent(Sprite).toProperty("spriteFrame");
|
||||
const spriteFrames = DataManager.Instance.textureMap.get(this.path);
|
||||
const frames: Array<[number, SpriteFrame]> = sortSpriteFrame(spriteFrames).map((item, index) => [index * ANIMATION_SPEED, item]);
|
||||
track.channel.curve.assignSorted(frames);
|
||||
|
||||
//动画添加轨道
|
||||
this.animationClip = new AnimationClip()
|
||||
this.animationClip.name = this.path
|
||||
this.animationClip.duration = frames.length * ANIMATION_SPEED
|
||||
this.animationClip.addTrack(track)
|
||||
this.animationClip.wrapMode = this.wrapMode
|
||||
this.animationClip = new AnimationClip();
|
||||
this.animationClip.name = this.path;
|
||||
this.animationClip.duration = frames.length * ANIMATION_SPEED;
|
||||
this.animationClip.addTrack(track);
|
||||
this.animationClip.wrapMode = this.wrapMode;
|
||||
}
|
||||
|
||||
run() {
|
||||
if (this.fsm.animationComponent.defaultClip?.name === this.animationClip.name && !this.force) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.fsm.animationComponent.defaultClip = this.animationClip
|
||||
this.fsm.animationComponent.play()
|
||||
this.fsm.animationComponent.defaultClip = this.animationClip;
|
||||
this.fsm.animationComponent.play();
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,30 @@
|
||||
import { _decorator, Animation, Component } from 'cc'
|
||||
import { EntityTypeEnum } from '../Common'
|
||||
import { FsmParamTypeEnum } from '../Enum'
|
||||
const { ccclass } = _decorator
|
||||
import State from './State'
|
||||
import SubStateMachine from './SubStateMachine'
|
||||
import { _decorator, Animation, Component } from "cc";
|
||||
import { EntityTypeEnum } from "../Common";
|
||||
import { FsmParamTypeEnum } from "../Enum";
|
||||
const { ccclass } = _decorator;
|
||||
import State from "./State";
|
||||
import SubStateMachine from "./SubStateMachine";
|
||||
|
||||
type ParamsValueType = boolean | number
|
||||
type ParamsValueType = boolean | number;
|
||||
|
||||
export interface IParamsValue {
|
||||
type: FsmParamTypeEnum
|
||||
value: ParamsValueType
|
||||
type: FsmParamTypeEnum;
|
||||
value: ParamsValueType;
|
||||
}
|
||||
|
||||
export const getInitParamsTrigger = () => {
|
||||
return {
|
||||
type: FsmParamTypeEnum.Trigger,
|
||||
value: false,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const getInitParamsNumber = () => {
|
||||
return {
|
||||
type: FsmParamTypeEnum.Number,
|
||||
value: 0,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/***
|
||||
* 流动图
|
||||
@@ -39,47 +39,47 @@ export const getInitParamsNumber = () => {
|
||||
/***
|
||||
* 有限状态机基类
|
||||
*/
|
||||
@ccclass('StateMachine')
|
||||
@ccclass("StateMachine")
|
||||
export default abstract class StateMachine extends Component {
|
||||
private _currentState: State | SubStateMachine = null
|
||||
params: Map<string, IParamsValue> = new Map()
|
||||
stateMachines: Map<string, SubStateMachine | State> = new Map()
|
||||
animationComponent: Animation
|
||||
type: EntityTypeEnum
|
||||
private _currentState: State | SubStateMachine = null;
|
||||
params: Map<string, IParamsValue> = new Map();
|
||||
stateMachines: Map<string, SubStateMachine | State> = new Map();
|
||||
animationComponent: Animation;
|
||||
type: EntityTypeEnum;
|
||||
|
||||
getParams(paramName: string) {
|
||||
if (this.params.has(paramName)) {
|
||||
return this.params.get(paramName).value
|
||||
return this.params.get(paramName).value;
|
||||
}
|
||||
}
|
||||
|
||||
setParams(paramName: string, value: ParamsValueType) {
|
||||
if (this.params.has(paramName)) {
|
||||
this.params.get(paramName).value = value
|
||||
this.run()
|
||||
this.resetTrigger()
|
||||
this.params.get(paramName).value = value;
|
||||
this.run();
|
||||
this.resetTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
get currentState() {
|
||||
return this._currentState
|
||||
return this._currentState;
|
||||
}
|
||||
|
||||
set currentState(newState) {
|
||||
if (!newState) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this._currentState = newState
|
||||
this._currentState.run()
|
||||
this._currentState = newState;
|
||||
this._currentState.run();
|
||||
}
|
||||
|
||||
/***
|
||||
* 清空所有trigger
|
||||
*/
|
||||
* 清空所有trigger
|
||||
*/
|
||||
resetTrigger() {
|
||||
for (const [, value] of this.params) {
|
||||
if (value.type === FsmParamTypeEnum.Trigger) {
|
||||
value.value = false
|
||||
value.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,6 @@ export default abstract class StateMachine extends Component {
|
||||
/***
|
||||
* 由子类重写,方法目标是根据当前状态和参数修改currentState
|
||||
*/
|
||||
abstract init(...args: any[]): void
|
||||
abstract run(): void
|
||||
abstract init(...args: any[]): void;
|
||||
abstract run(): void;
|
||||
}
|
||||
|
@@ -1,30 +1,30 @@
|
||||
import State from './State'
|
||||
import StateMachine from './StateMachine'
|
||||
import State from "./State";
|
||||
import StateMachine from "./StateMachine";
|
||||
|
||||
/***
|
||||
* 子有限状态机基类
|
||||
* 用处:例如有个idle的state,但是有多个方向,为了让主状态机更整洁,可以把同类型的但具体不同的state都封装在子状态机中
|
||||
*/
|
||||
export default abstract class SubStateMachine {
|
||||
private _currentState: State = null
|
||||
stateMachines: Map<string, State> = new Map()
|
||||
private _currentState: State = null;
|
||||
stateMachines: Map<string, State> = new Map();
|
||||
|
||||
constructor(public fsm: StateMachine) {}
|
||||
|
||||
get currentState() {
|
||||
return this._currentState
|
||||
return this._currentState;
|
||||
}
|
||||
|
||||
set currentState(newState) {
|
||||
if (!newState) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this._currentState = newState
|
||||
this._currentState.run()
|
||||
this._currentState = newState;
|
||||
this._currentState.run();
|
||||
}
|
||||
|
||||
/***
|
||||
* 具体类实现
|
||||
*/
|
||||
abstract run(): void
|
||||
abstract run(): void;
|
||||
}
|
||||
|
@@ -1,147 +1,141 @@
|
||||
import { _decorator, instantiate, ProgressBar, Label, Vec3, Tween, tween, director } from 'cc';
|
||||
import { EntityManager } from '../../Base/EntityManager';
|
||||
import { ApiMsgEnum, EntityTypeEnum, IActor, InputTypeEnum, IVec2, toFixed } from '../../Common';
|
||||
import { EntityStateEnum, EventEnum, SceneEnum } from '../../Enum';
|
||||
import DataManager from '../../Global/DataManager';
|
||||
import EventManager from '../../Global/EventManager';
|
||||
import NetworkManager from '../../Global/NetworkManager';
|
||||
import { rad2Angle } from '../../Utils';
|
||||
import { WeaponManager } from '../Weapon/WeaponManager';
|
||||
import { PlayerStateMachine } from './ActorStateMachine';
|
||||
import { _decorator, instantiate, ProgressBar, Label, Vec3, Tween, tween } from "cc";
|
||||
import { EntityManager } from "../../Base/EntityManager";
|
||||
import { EntityTypeEnum, IActor, InputTypeEnum, IVec2, toFixed } from "../../Common";
|
||||
import { EntityStateEnum, EventEnum, SceneEnum } from "../../Enum";
|
||||
import DataManager from "../../Global/DataManager";
|
||||
import EventManager from "../../Global/EventManager";
|
||||
import { rad2Angle } from "../../Utils";
|
||||
import { WeaponManager } from "../Weapon/WeaponManager";
|
||||
import { ActorStateMachine } from "./ActorStateMachine";
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('ActorManager')
|
||||
@ccclass("ActorManager")
|
||||
export class ActorManager extends EntityManager implements IActor {
|
||||
//静态数据
|
||||
id: number
|
||||
nickname: string
|
||||
type: EntityTypeEnum
|
||||
weaponType: EntityTypeEnum
|
||||
bulletType: EntityTypeEnum
|
||||
//静态数据
|
||||
id: number;
|
||||
nickname: string;
|
||||
type: EntityTypeEnum;
|
||||
weaponType: EntityTypeEnum;
|
||||
bulletType: EntityTypeEnum;
|
||||
|
||||
//动态数据
|
||||
hp: number
|
||||
position: IVec2
|
||||
direction: IVec2
|
||||
//动态数据
|
||||
hp: number;
|
||||
position: IVec2;
|
||||
direction: IVec2;
|
||||
|
||||
private hpBar: ProgressBar
|
||||
private label: Label
|
||||
private weapon: WeaponManager
|
||||
private hpBar: ProgressBar;
|
||||
private label: Label;
|
||||
private weapon: WeaponManager;
|
||||
|
||||
private tw: Tween<any>
|
||||
private targetPos: Vec3
|
||||
private tw: Tween<unknown>;
|
||||
private targetPos: Vec3;
|
||||
private isDead = false;
|
||||
|
||||
private isDead = false
|
||||
init(data: IActor) {
|
||||
const { id, nickname, type, weaponType, bulletType } = data;
|
||||
this.id = id;
|
||||
this.nickname = nickname;
|
||||
this.type = type;
|
||||
this.weaponType = weaponType;
|
||||
this.bulletType = bulletType;
|
||||
|
||||
get isSelf() {
|
||||
return DataManager.Instance.myPlayerId === this.id
|
||||
this.hpBar = this.node.getComponentInChildren(ProgressBar);
|
||||
this.label = this.node.getComponentInChildren(Label);
|
||||
this.label.string = nickname;
|
||||
|
||||
this.fsm = this.addComponent(ActorStateMachine);
|
||||
this.fsm.init(type);
|
||||
this.state = EntityStateEnum.Idle;
|
||||
|
||||
const weaponPrefab = DataManager.Instance.prefabMap.get(this.weaponType);
|
||||
const weapon = instantiate(weaponPrefab);
|
||||
weapon.setParent(this.node);
|
||||
this.weapon = weapon.addComponent(WeaponManager);
|
||||
this.weapon.init(data);
|
||||
|
||||
this.targetPos = undefined;
|
||||
this.node.active = false;
|
||||
}
|
||||
|
||||
async tick(dt: number) {
|
||||
if (DataManager.Instance.myPlayerId !== this.id || this.isDead) {
|
||||
return;
|
||||
}
|
||||
|
||||
init(data: IActor) {
|
||||
const { id, nickname, type, weaponType, bulletType } = data
|
||||
this.id = id
|
||||
this.nickname = nickname
|
||||
this.type = type
|
||||
this.weaponType = weaponType
|
||||
this.bulletType = bulletType
|
||||
|
||||
this.hpBar = this.node.getComponentInChildren(ProgressBar)
|
||||
this.label = this.node.getComponentInChildren(Label)
|
||||
this.label.string = nickname
|
||||
|
||||
this.fsm = this.addComponent(PlayerStateMachine)
|
||||
this.fsm.init(type)
|
||||
this.state = EntityStateEnum.Idle
|
||||
|
||||
const weaponPrefab = DataManager.Instance.prefabMap.get(this.weaponType)
|
||||
const weapon = instantiate(weaponPrefab)
|
||||
weapon.setParent(this.node)
|
||||
this.weapon = weapon.addComponent(WeaponManager)
|
||||
this.weapon.init(data)
|
||||
|
||||
this.targetPos = undefined
|
||||
this.node.active = false
|
||||
if (this.hp <= 0) {
|
||||
EventManager.Instance.emit(EventEnum.GameEnd);
|
||||
this.isDead = true;
|
||||
return;
|
||||
}
|
||||
|
||||
async tick(dt: number) {
|
||||
if (!this.isSelf) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.hp <= 0 && !this.isDead) {
|
||||
EventManager.Instance.emit(EventEnum.GameEnd)
|
||||
this.isDead = true
|
||||
return
|
||||
}
|
||||
|
||||
if (DataManager.Instance.jm.input.length()) {
|
||||
const { x, y } = DataManager.Instance.jm.input
|
||||
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
|
||||
type: InputTypeEnum.ActorMove,
|
||||
id: this.id,
|
||||
direction: {
|
||||
x: toFixed(x),
|
||||
y: toFixed(y),
|
||||
},
|
||||
dt: toFixed(dt)
|
||||
})
|
||||
}
|
||||
|
||||
if (DataManager.Instance.jm.input.length()) {
|
||||
const { x, y } = DataManager.Instance.jm.input;
|
||||
EventManager.Instance.emit(EventEnum.ClientSync, {
|
||||
type: InputTypeEnum.ActorMove,
|
||||
id: this.id,
|
||||
direction: {
|
||||
x: toFixed(x),
|
||||
y: toFixed(y),
|
||||
},
|
||||
dt: toFixed(dt),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render(data: IActor) {
|
||||
this.renderHP(data)
|
||||
this.renderPosition(data)
|
||||
this.renderDirection(data)
|
||||
render(data: IActor) {
|
||||
this.renderHP(data);
|
||||
this.renderPosition(data);
|
||||
this.renderDirection(data);
|
||||
}
|
||||
|
||||
renderHP(data: IActor) {
|
||||
this.hp = data.hp;
|
||||
this.hpBar.progress = data.hp / this.hpBar.totalLength;
|
||||
}
|
||||
|
||||
renderPosition(data: IActor) {
|
||||
const newPos = new Vec3(data.position.x, data.position.y);
|
||||
if (!this.targetPos) {
|
||||
this.node.active = true;
|
||||
this.node.setPosition(newPos);
|
||||
this.targetPos = new Vec3(newPos);
|
||||
} else if (!this.targetPos.equals(newPos)) {
|
||||
this.tw?.stop();
|
||||
this.node.setPosition(this.targetPos);
|
||||
this.targetPos.set(newPos);
|
||||
this.state = EntityStateEnum.Run;
|
||||
this.tw = tween(this.node)
|
||||
.to(0.1, {
|
||||
position: this.targetPos,
|
||||
})
|
||||
.call(() => {
|
||||
this.state = EntityStateEnum.Idle;
|
||||
})
|
||||
.start();
|
||||
}
|
||||
// this.node.setPosition(data.position.x, data.position.y)
|
||||
}
|
||||
|
||||
renderHP(data: IActor) {
|
||||
this.hp = data.hp
|
||||
this.hpBar.progress = data.hp / this.hpBar.totalLength
|
||||
renderDirection(data: IActor) {
|
||||
const { x, y } = data.direction;
|
||||
if (x !== 0) {
|
||||
this.node.setScale(x > 0 ? 1 : -1, 1);
|
||||
this.label.node.setScale(x > 0 ? 1 : -1, 1);
|
||||
this.hpBar.node.setScale(x > 0 ? 1 : -1, 1);
|
||||
}
|
||||
const side = Math.sqrt(x * x + y * y);
|
||||
const angle = rad2Angle(Math.asin(y / side));
|
||||
this.weapon.node.setRotationFromEuler(0, 0, angle);
|
||||
|
||||
renderPosition(data: IActor) {
|
||||
const newPos = new Vec3(data.position.x, data.position.y)
|
||||
if (!this.targetPos) {
|
||||
this.node.active = true
|
||||
this.node.setPosition(newPos)
|
||||
this.targetPos = new Vec3(newPos)
|
||||
} else if (!this.targetPos.equals(newPos)) {
|
||||
this.tw?.stop()
|
||||
this.node.setPosition(this.targetPos)
|
||||
this.targetPos.set(newPos)
|
||||
this.state = EntityStateEnum.Run
|
||||
this.tw = tween(this.node).to(0.1, {
|
||||
position: this.targetPos
|
||||
}).call(() => {
|
||||
this.state = EntityStateEnum.Idle
|
||||
}).start()
|
||||
}
|
||||
|
||||
// this.node.setPosition(data.position.x, data.position.y)
|
||||
}
|
||||
|
||||
renderDirection(data: IActor) {
|
||||
const { x, y } = data.direction
|
||||
if (x !== 0) {
|
||||
this.node.setScale(x > 0 ? 1 : -1, 1)
|
||||
this.label.node.setScale(x > 0 ? 1 : -1, 1)
|
||||
this.hpBar.node.setScale(x > 0 ? 1 : -1, 1)
|
||||
}
|
||||
const side = Math.sqrt(x * x + y * y)
|
||||
const angle = rad2Angle(Math.asin(y / side))
|
||||
this.weapon.node.setRotationFromEuler(0, 0, angle)
|
||||
|
||||
// const { x, y } = joystick.input
|
||||
// let angle: number, sign: number
|
||||
// if (x !== 0) {
|
||||
// angle = rad2Angle(Math.atan(y / x))
|
||||
// sign = joystick.input.x > 0 ? 1 : -1
|
||||
// } else {
|
||||
// angle = rad2Angle(Math.PI / 2)
|
||||
// sign = joystick.input.y > 0 ? 1 : -1
|
||||
// }
|
||||
// this.node.setRotationFromEuler(0, 0, sign * angle)
|
||||
}
|
||||
// const { x, y } = joystick.input
|
||||
// let angle: number, sign: number
|
||||
// if (x !== 0) {
|
||||
// angle = rad2Angle(Math.atan(y / x))
|
||||
// sign = joystick.input.x > 0 ? 1 : -1
|
||||
// } else {
|
||||
// angle = rad2Angle(Math.PI / 2)
|
||||
// sign = joystick.input.y > 0 ? 1 : -1
|
||||
// }
|
||||
// this.node.setRotationFromEuler(0, 0, sign * angle)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,48 +1,47 @@
|
||||
import { _decorator, Animation, AnimationClip } from 'cc'
|
||||
import State from '../../Base/State'
|
||||
import StateMachine, { getInitParamsTrigger } from '../../Base/StateMachine'
|
||||
import { EntityTypeEnum } from '../../Common'
|
||||
import { EntityStateEnum, ParamsNameEnum } from '../../Enum'
|
||||
const { ccclass } = _decorator
|
||||
import { _decorator, Animation, AnimationClip } from "cc";
|
||||
import State from "../../Base/State";
|
||||
import StateMachine, { getInitParamsTrigger } from "../../Base/StateMachine";
|
||||
import { EntityTypeEnum } from "../../Common";
|
||||
import { EntityStateEnum, ParamsNameEnum } from "../../Enum";
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('PlayerStateMachine')
|
||||
export class PlayerStateMachine extends StateMachine {
|
||||
@ccclass("ActorStateMachine")
|
||||
export class ActorStateMachine extends StateMachine {
|
||||
init(type: EntityTypeEnum) {
|
||||
this.type = type
|
||||
this.animationComponent = this.node.addComponent(Animation)
|
||||
this.initParams()
|
||||
this.initStateMachines()
|
||||
this.initAnimationEvent()
|
||||
this.type = type;
|
||||
this.animationComponent = this.node.addComponent(Animation);
|
||||
this.initParams();
|
||||
this.initStateMachines();
|
||||
this.initAnimationEvent();
|
||||
}
|
||||
|
||||
initParams() {
|
||||
this.params.set(ParamsNameEnum.Idle, getInitParamsTrigger())
|
||||
this.params.set(ParamsNameEnum.Run, getInitParamsTrigger())
|
||||
this.params.set(ParamsNameEnum.Idle, getInitParamsTrigger());
|
||||
this.params.set(ParamsNameEnum.Run, getInitParamsTrigger());
|
||||
}
|
||||
|
||||
initStateMachines() {
|
||||
this.stateMachines.set(ParamsNameEnum.Idle, new State(this, `${this.type}${EntityStateEnum.Idle}`, AnimationClip.WrapMode.Loop))
|
||||
this.stateMachines.set(ParamsNameEnum.Run, new State(this, `${this.type}${EntityStateEnum.Run}`, AnimationClip.WrapMode.Loop))
|
||||
this.stateMachines.set(ParamsNameEnum.Idle, new State(this, `${this.type}${EntityStateEnum.Idle}`, AnimationClip.WrapMode.Loop));
|
||||
this.stateMachines.set(ParamsNameEnum.Run, new State(this, `${this.type}${EntityStateEnum.Run}`, AnimationClip.WrapMode.Loop));
|
||||
}
|
||||
|
||||
initAnimationEvent() {
|
||||
}
|
||||
initAnimationEvent() {}
|
||||
|
||||
run() {
|
||||
switch (this.currentState) {
|
||||
case this.stateMachines.get(ParamsNameEnum.Idle):
|
||||
case this.stateMachines.get(ParamsNameEnum.Run):
|
||||
if (this.params.get(ParamsNameEnum.Run).value) {
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Run)
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Run);
|
||||
} else if (this.params.get(ParamsNameEnum.Idle).value) {
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle)
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle);
|
||||
} else {
|
||||
this.currentState = this.currentState
|
||||
this.currentState = this.currentState;
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle)
|
||||
break
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,79 +1,83 @@
|
||||
import { Tween, tween, Vec3, _decorator } from 'cc'
|
||||
import { EntityManager } from '../../Base/EntityManager'
|
||||
import { EntityTypeEnum, IBullet, IVec2 } from '../../Common'
|
||||
import { EntityStateEnum, EventEnum } from '../../Enum'
|
||||
import DataManager from '../../Global/DataManager'
|
||||
import EventManager from '../../Global/EventManager'
|
||||
import ObjectPoolManager from '../../Global/ObjectPoolManager'
|
||||
import { rad2Angle } from '../../Utils'
|
||||
import { ExplosionManager } from '../Explosion/ExplosionManager'
|
||||
import { BulletStateMachine } from './BulletStateMachine'
|
||||
const { ccclass } = _decorator
|
||||
import { Tween, tween, Vec3, _decorator } from "cc";
|
||||
import { EntityManager } from "../../Base/EntityManager";
|
||||
import { EntityTypeEnum, IBullet, IVec2 } from "../../Common";
|
||||
import { EntityStateEnum, EventEnum } from "../../Enum";
|
||||
import DataManager from "../../Global/DataManager";
|
||||
import EventManager from "../../Global/EventManager";
|
||||
import ObjectPoolManager from "../../Global/ObjectPoolManager";
|
||||
import { rad2Angle } from "../../Utils";
|
||||
import { ExplosionManager } from "../Explosion/ExplosionManager";
|
||||
import { BulletStateMachine } from "./BulletStateMachine";
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('BulletManager')
|
||||
@ccclass("BulletManager")
|
||||
export class BulletManager extends EntityManager implements IBullet {
|
||||
//静态数据
|
||||
id: number
|
||||
owner: number
|
||||
type: EntityTypeEnum
|
||||
id: number;
|
||||
owner: number;
|
||||
type: EntityTypeEnum;
|
||||
|
||||
//动态数据
|
||||
position: IVec2
|
||||
direction: IVec2
|
||||
position: IVec2;
|
||||
direction: IVec2;
|
||||
|
||||
private angle: number
|
||||
private tw: Tween<any>
|
||||
private targetPos: Vec3
|
||||
private angle: number;
|
||||
private tw: Tween<any>;
|
||||
private targetPos: Vec3;
|
||||
|
||||
init({ id, owner, type }: IBullet) {
|
||||
this.id = id
|
||||
this.owner = owner
|
||||
this.type = type
|
||||
this.id = id;
|
||||
this.owner = owner;
|
||||
this.type = type;
|
||||
|
||||
this.fsm = this.addComponent(BulletStateMachine)
|
||||
this.fsm.init(type)
|
||||
this.state = EntityStateEnum.Idle
|
||||
this.node.active = false
|
||||
this.targetPos = undefined
|
||||
this.fsm = this.addComponent(BulletStateMachine);
|
||||
this.fsm.init(type);
|
||||
this.state = EntityStateEnum.Idle;
|
||||
|
||||
EventManager.Instance.on(EventEnum.ExplosionBorn, this.handleExplosion, this)
|
||||
this.node.active = false;
|
||||
this.targetPos = undefined;
|
||||
this.angle = undefined;
|
||||
|
||||
EventManager.Instance.on(EventEnum.ExplosionBorn, this.handleExplosion, this);
|
||||
}
|
||||
|
||||
handleExplosion(id: number, { x, y }: IVec2) {
|
||||
if (this.id !== id) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const explosion = ObjectPoolManager.Instance.get(EntityTypeEnum.Explosion)
|
||||
const explosionManager = explosion.getComponent(ExplosionManager) || explosion.addComponent(ExplosionManager)
|
||||
const explosion = ObjectPoolManager.Instance.get(EntityTypeEnum.Explosion);
|
||||
const explosionManager = explosion.getComponent(ExplosionManager) || explosion.addComponent(ExplosionManager);
|
||||
explosionManager.init(EntityTypeEnum.Explosion, {
|
||||
x, y,
|
||||
})
|
||||
x,
|
||||
y,
|
||||
});
|
||||
|
||||
EventManager.Instance.off(EventEnum.ExplosionBorn, this.handleExplosion, this)
|
||||
ObjectPoolManager.Instance.ret(this.node)
|
||||
DataManager.Instance.bulletMap.delete(this.id)
|
||||
this.angle = undefined
|
||||
EventManager.Instance.off(EventEnum.ExplosionBorn, this.handleExplosion, this);
|
||||
ObjectPoolManager.Instance.ret(this.node);
|
||||
DataManager.Instance.bulletMap.delete(this.id);
|
||||
}
|
||||
|
||||
render(data: IBullet) {
|
||||
this.renderPosition(data)
|
||||
this.renderDirection(data)
|
||||
this.renderPosition(data);
|
||||
this.renderDirection(data);
|
||||
}
|
||||
|
||||
renderPosition(data: IBullet) {
|
||||
const newPos = new Vec3(data.position.x, data.position.y)
|
||||
const newPos = new Vec3(data.position.x, data.position.y);
|
||||
if (!this.targetPos) {
|
||||
this.node.active = true
|
||||
this.node.setPosition(newPos)
|
||||
this.targetPos = new Vec3(newPos)
|
||||
this.node.active = true;
|
||||
this.node.setPosition(newPos);
|
||||
this.targetPos = new Vec3(newPos);
|
||||
} else if (!this.targetPos.equals(newPos)) {
|
||||
this.tw?.stop()
|
||||
this.node.setPosition(this.targetPos)
|
||||
this.targetPos.set(newPos)
|
||||
this.tw = tween(this.node).to(0.1, {
|
||||
position: this.targetPos
|
||||
}).start()
|
||||
this.tw?.stop();
|
||||
this.node.setPosition(this.targetPos);
|
||||
this.targetPos.set(newPos);
|
||||
this.tw = tween(this.node)
|
||||
.to(0.1, {
|
||||
position: this.targetPos,
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
// this.node.setPosition(data.position.x, data.position.y)
|
||||
@@ -81,12 +85,12 @@ export class BulletManager extends EntityManager implements IBullet {
|
||||
|
||||
renderDirection(data: IBullet) {
|
||||
if (this.angle === undefined) {
|
||||
const { x, y } = data.direction
|
||||
const side = Math.sqrt(x * x + y * y)
|
||||
this.angle = x > 0 ? rad2Angle(Math.asin(y / side)) : rad2Angle(Math.asin(- y / side)) + 180
|
||||
const { x, y } = data.direction;
|
||||
const side = Math.sqrt(x * x + y * y);
|
||||
this.angle = x > 0 ? rad2Angle(Math.asin(y / side)) : rad2Angle(Math.asin(-y / side)) + 180;
|
||||
}
|
||||
|
||||
this.node.setRotationFromEuler(0, 0, this.angle)
|
||||
this.node.setRotationFromEuler(0, 0, this.angle);
|
||||
|
||||
// let angle: number, sign: number
|
||||
// if (x !== 0) {
|
||||
|
@@ -1,45 +1,43 @@
|
||||
import { _decorator, Animation } from 'cc'
|
||||
import State from '../../Base/State'
|
||||
import StateMachine, { getInitParamsTrigger } from '../../Base/StateMachine'
|
||||
import { EntityTypeEnum } from '../../Common'
|
||||
import { EntityStateEnum, ParamsNameEnum } from '../../Enum'
|
||||
const { ccclass } = _decorator
|
||||
import { _decorator, Animation } from "cc";
|
||||
import State from "../../Base/State";
|
||||
import StateMachine, { getInitParamsTrigger } from "../../Base/StateMachine";
|
||||
import { EntityTypeEnum } from "../../Common";
|
||||
import { EntityStateEnum, ParamsNameEnum } from "../../Enum";
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('BulletStateMachine')
|
||||
@ccclass("BulletStateMachine")
|
||||
export class BulletStateMachine extends StateMachine {
|
||||
init(type: EntityTypeEnum) {
|
||||
this.type = type
|
||||
this.animationComponent = this.node.addComponent(Animation)
|
||||
this.type = type;
|
||||
this.animationComponent = this.node.addComponent(Animation);
|
||||
|
||||
this.initParams()
|
||||
this.initStateMachines()
|
||||
this.initAnimationEvent()
|
||||
this.initParams();
|
||||
this.initStateMachines();
|
||||
this.initAnimationEvent();
|
||||
}
|
||||
|
||||
initParams() {
|
||||
this.params.set(ParamsNameEnum.Idle, getInitParamsTrigger())
|
||||
this.params.set(ParamsNameEnum.Idle, getInitParamsTrigger());
|
||||
}
|
||||
|
||||
initStateMachines() {
|
||||
this.stateMachines.set(ParamsNameEnum.Idle, new State(this, `${this.type}${EntityStateEnum.Idle}`))
|
||||
this.stateMachines.set(ParamsNameEnum.Idle, new State(this, `${this.type}${EntityStateEnum.Idle}`));
|
||||
}
|
||||
|
||||
initAnimationEvent() {
|
||||
|
||||
}
|
||||
initAnimationEvent() {}
|
||||
|
||||
run() {
|
||||
switch (this.currentState) {
|
||||
case this.stateMachines.get(ParamsNameEnum.Idle):
|
||||
if (this.params.get(ParamsNameEnum.Idle).value) {
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle)
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle);
|
||||
} else {
|
||||
this.currentState = this.currentState
|
||||
this.currentState = this.currentState;
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle)
|
||||
break
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,16 @@
|
||||
import { _decorator } from 'cc'
|
||||
import { EntityManager } from '../../Base/EntityManager'
|
||||
import { EntityTypeEnum, IVec2 } from '../../Common'
|
||||
import { EntityStateEnum } from '../../Enum'
|
||||
import { ExplosionStateMachine } from './ExplosionStateMachine'
|
||||
const { ccclass, property } = _decorator
|
||||
import { _decorator } from "cc";
|
||||
import { EntityManager } from "../../Base/EntityManager";
|
||||
import { EntityTypeEnum, IVec2 } from "../../Common";
|
||||
import { EntityStateEnum } from "../../Enum";
|
||||
import { ExplosionStateMachine } from "./ExplosionStateMachine";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('ExplosionManager')
|
||||
@ccclass("ExplosionManager")
|
||||
export class ExplosionManager extends EntityManager {
|
||||
|
||||
init(type: EntityTypeEnum, { x, y }: IVec2) {
|
||||
this.node.setPosition(x, y)
|
||||
this.fsm = this.addComponent(ExplosionStateMachine)
|
||||
this.fsm.init(type)
|
||||
this.state = EntityStateEnum.Idle
|
||||
this.node.setPosition(x, y);
|
||||
this.fsm = this.addComponent(ExplosionStateMachine);
|
||||
this.fsm.init(type);
|
||||
this.state = EntityStateEnum.Idle;
|
||||
}
|
||||
}
|
||||
|
@@ -1,52 +1,52 @@
|
||||
import { _decorator, Animation } from 'cc'
|
||||
import State from '../../Base/State'
|
||||
import StateMachine, { getInitParamsTrigger } from '../../Base/StateMachine'
|
||||
import { EntityTypeEnum } from '../../Common'
|
||||
import { EntityStateEnum, ParamsNameEnum } from '../../Enum'
|
||||
import ObjectPoolManager from '../../Global/ObjectPoolManager'
|
||||
const { ccclass, property } = _decorator
|
||||
import { _decorator, Animation } from "cc";
|
||||
import State from "../../Base/State";
|
||||
import StateMachine, { getInitParamsTrigger } from "../../Base/StateMachine";
|
||||
import { EntityTypeEnum } from "../../Common";
|
||||
import { EntityStateEnum, ParamsNameEnum } from "../../Enum";
|
||||
import ObjectPoolManager from "../../Global/ObjectPoolManager";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('ExplosionStateMachine')
|
||||
@ccclass("ExplosionStateMachine")
|
||||
export class ExplosionStateMachine extends StateMachine {
|
||||
init(type: EntityTypeEnum) {
|
||||
this.type = type
|
||||
this.animationComponent = this.node.addComponent(Animation)
|
||||
this.type = type;
|
||||
this.animationComponent = this.node.addComponent(Animation);
|
||||
|
||||
this.initParams()
|
||||
this.initStateMachines()
|
||||
this.initAnimationEvent()
|
||||
this.initParams();
|
||||
this.initStateMachines();
|
||||
this.initAnimationEvent();
|
||||
}
|
||||
|
||||
initParams() {
|
||||
this.params.set(ParamsNameEnum.Idle, getInitParamsTrigger())
|
||||
this.params.set(ParamsNameEnum.Idle, getInitParamsTrigger());
|
||||
}
|
||||
|
||||
initStateMachines() {
|
||||
this.stateMachines.set(ParamsNameEnum.Idle, new State(this, `${this.type}${EntityStateEnum.Idle}`))
|
||||
this.stateMachines.set(ParamsNameEnum.Idle, new State(this, `${this.type}${EntityStateEnum.Idle}`));
|
||||
}
|
||||
|
||||
initAnimationEvent() {
|
||||
this.animationComponent.on(Animation.EventType.FINISHED, () => {
|
||||
const whiteList = [EntityStateEnum.Idle]
|
||||
const name = this.animationComponent.defaultClip.name
|
||||
if (whiteList.some(v => name.includes(v))) {
|
||||
ObjectPoolManager.Instance.ret(this.node)
|
||||
const whiteList = [EntityStateEnum.Idle];
|
||||
const name = this.animationComponent.defaultClip.name;
|
||||
if (whiteList.some((v) => name.includes(v))) {
|
||||
ObjectPoolManager.Instance.ret(this.node);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
run() {
|
||||
switch (this.currentState) {
|
||||
case this.stateMachines.get(ParamsNameEnum.Idle):
|
||||
if (this.params.get(ParamsNameEnum.Idle).value) {
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle)
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle);
|
||||
} else {
|
||||
this.currentState = this.currentState
|
||||
this.currentState = this.currentState;
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle)
|
||||
break
|
||||
this.currentState = this.stateMachines.get(ParamsNameEnum.Idle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,66 +1,61 @@
|
||||
import { _decorator, Node, Vec2, UITransform } from 'cc'
|
||||
import { EntityManager } from '../../Base/EntityManager'
|
||||
import { ApiMsgEnum, EntityTypeEnum, InputTypeEnum, toFixed } from '../../Common'
|
||||
import { EntityStateEnum, EventEnum } from '../../Enum'
|
||||
import DataManager from '../../Global/DataManager'
|
||||
import EventManager from '../../Global/EventManager'
|
||||
import NetworkManager from '../../Global/NetworkManager'
|
||||
import { WeaponStateMachine } from './WeaponStateMachine'
|
||||
const { ccclass } = _decorator
|
||||
import { _decorator, Node, Vec2, UITransform } from "cc";
|
||||
import { EntityManager } from "../../Base/EntityManager";
|
||||
import { EntityTypeEnum, InputTypeEnum, toFixed } from "../../Common";
|
||||
import { EntityStateEnum, EventEnum } from "../../Enum";
|
||||
import DataManager from "../../Global/DataManager";
|
||||
import EventManager from "../../Global/EventManager";
|
||||
import { WeaponStateMachine } from "./WeaponStateMachine";
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('WeaponManager')
|
||||
@ccclass("WeaponManager")
|
||||
export class WeaponManager extends EntityManager {
|
||||
owner: number
|
||||
type: EntityTypeEnum
|
||||
owner: number;
|
||||
type: EntityTypeEnum;
|
||||
|
||||
private body: Node
|
||||
private anchor: Node
|
||||
private point: Node
|
||||
private body: Node;
|
||||
private anchor: Node;
|
||||
private point: Node;
|
||||
|
||||
get isSelf() {
|
||||
return DataManager.Instance.myPlayerId === this.owner
|
||||
}
|
||||
init({ id, weaponType }: { id: number; weaponType: EntityTypeEnum }) {
|
||||
this.owner = id;
|
||||
this.type = weaponType;
|
||||
|
||||
init({ id, weaponType }: { id: number, weaponType: EntityTypeEnum }) {
|
||||
this.owner = id
|
||||
this.type = weaponType
|
||||
this.node.setSiblingIndex(0);
|
||||
this.body = this.node.getChildByName("Body");
|
||||
this.anchor = this.body.getChildByName("Anchor");
|
||||
this.point = this.anchor.getChildByName("Point");
|
||||
|
||||
this.node.setSiblingIndex(0)
|
||||
this.body = this.node.getChildByName("Body")
|
||||
this.anchor = this.body.getChildByName("Anchor")
|
||||
this.point = this.anchor.getChildByName("Point")
|
||||
this.fsm = this.body.addComponent(WeaponStateMachine);
|
||||
this.fsm.init(weaponType);
|
||||
this.state = EntityStateEnum.Idle;
|
||||
|
||||
this.fsm = this.body.addComponent(WeaponStateMachine)
|
||||
this.fsm.init(weaponType)
|
||||
this.state = EntityStateEnum.Idle
|
||||
|
||||
EventManager.Instance.on(EventEnum.WeaponShoot, this.handleWeaponShoot, this)
|
||||
EventManager.Instance.on(EventEnum.BulletBorn, this.handleBulletBorn, this)
|
||||
EventManager.Instance.on(EventEnum.WeaponShoot, this.handleWeaponShoot, this);
|
||||
EventManager.Instance.on(EventEnum.BulletBorn, this.handleBulletBorn, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
EventManager.Instance.off(EventEnum.WeaponShoot, this.handleWeaponShoot, this)
|
||||
EventManager.Instance.off(EventEnum.BulletBorn, this.handleBulletBorn, this)
|
||||
EventManager.Instance.off(EventEnum.WeaponShoot, this.handleWeaponShoot, this);
|
||||
EventManager.Instance.off(EventEnum.BulletBorn, this.handleBulletBorn, this);
|
||||
}
|
||||
|
||||
handleBulletBorn(owner: number) {
|
||||
if (this.owner !== owner) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = EntityStateEnum.Attack
|
||||
this.state = EntityStateEnum.Attack;
|
||||
}
|
||||
|
||||
handleWeaponShoot() {
|
||||
if (!this.isSelf) {
|
||||
return
|
||||
if (DataManager.Instance.myPlayerId !== this.owner) {
|
||||
return;
|
||||
}
|
||||
const pointWorldPos = this.point.getWorldPosition()
|
||||
const pointWorldPos = this.point.getWorldPosition();
|
||||
const pointStagePos = DataManager.Instance.stage.getComponent(UITransform).convertToNodeSpaceAR(pointWorldPos);
|
||||
const anchorWorldPos = this.anchor.getWorldPosition()
|
||||
const directionVec2 = new Vec2(pointWorldPos.x - anchorWorldPos.x, pointWorldPos.y - anchorWorldPos.y).normalize()
|
||||
const anchorWorldPos = this.anchor.getWorldPosition();
|
||||
const directionVec2 = new Vec2(pointWorldPos.x - anchorWorldPos.x, pointWorldPos.y - anchorWorldPos.y).normalize();
|
||||
|
||||
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
|
||||
EventManager.Instance.emit(EventEnum.ClientSync, {
|
||||
type: InputTypeEnum.WeaponShoot,
|
||||
owner: this.owner,
|
||||
position: {
|
||||
@@ -71,6 +66,6 @@ export class WeaponManager extends EntityManager {
|
||||
x: toFixed(directionVec2.x),
|
||||
y: toFixed(directionVec2.y),
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,59 +1,60 @@
|
||||
export enum FsmParamTypeEnum {
|
||||
Number = 'Number',
|
||||
Trigger = 'Trigger',
|
||||
}
|
||||
|
||||
export enum EntityStateEnum {
|
||||
Idle = 'Idle',
|
||||
Run = 'Run',
|
||||
Attack = 'Attack',
|
||||
Number = "Number",
|
||||
Trigger = "Trigger",
|
||||
}
|
||||
|
||||
export enum ParamsNameEnum {
|
||||
Idle = 'Idle',
|
||||
Run = 'Run',
|
||||
Attack = 'Attack',
|
||||
Idle = "Idle",
|
||||
Run = "Run",
|
||||
Attack = "Attack",
|
||||
}
|
||||
|
||||
export enum EntityStateEnum {
|
||||
Idle = "Idle",
|
||||
Run = "Run",
|
||||
Attack = "Attack",
|
||||
}
|
||||
|
||||
export enum EventEnum {
|
||||
WeaponShoot = 'WeaponShoot',
|
||||
BulletBorn = 'BulletBorn',
|
||||
ExplosionBorn = 'ExplosionBorn',
|
||||
RoomJoin = 'RoomJoin',
|
||||
GameStart = 'GameStart',
|
||||
GameEnd = 'GameEnd',
|
||||
WeaponShoot = "WeaponShoot",
|
||||
BulletBorn = "BulletBorn",
|
||||
ExplosionBorn = "ExplosionBorn",
|
||||
RoomJoin = "RoomJoin",
|
||||
GameStart = "GameStart",
|
||||
GameEnd = "GameEnd",
|
||||
ClientSync = "ClientSync",
|
||||
}
|
||||
|
||||
export enum PrefabPathEnum {
|
||||
Map1 = 'prefab/Map1',
|
||||
Actor1 = 'prefab/Actor',
|
||||
Actor2 = 'prefab/Actor',
|
||||
Weapon1 = 'prefab/Weapon1',
|
||||
Weapon2 = 'prefab/Weapon2',
|
||||
Bullet1 = 'prefab/Bullet',
|
||||
Bullet2 = 'prefab/Bullet',
|
||||
Explosion = 'prefab/Explosion',
|
||||
JoyStick = 'prefab/JoyStick',
|
||||
Shoot = 'prefab/Shoot',
|
||||
Map1 = "prefab/Map1",
|
||||
Actor1 = "prefab/Actor",
|
||||
Actor2 = "prefab/Actor",
|
||||
Weapon1 = "prefab/Weapon1",
|
||||
Weapon2 = "prefab/Weapon2",
|
||||
Bullet1 = "prefab/Bullet",
|
||||
Bullet2 = "prefab/Bullet",
|
||||
Explosion = "prefab/Explosion",
|
||||
JoyStick = "prefab/JoyStick",
|
||||
Shoot = "prefab/Shoot",
|
||||
}
|
||||
|
||||
export enum TexturePathEnum {
|
||||
Actor1Idle = 'texture/actor/actor1/idle',
|
||||
Actor1Run = 'texture/actor/actor1/run',
|
||||
Actor2Idle = 'texture/actor/actor2/idle',
|
||||
Actor2Run = 'texture/actor/actor2/run',
|
||||
Weapon1Idle = 'texture/weapon/weapon1/idle',
|
||||
Weapon1Attack = 'texture/weapon/weapon1/attack',
|
||||
Weapon2Idle = 'texture/weapon/weapon2/idle',
|
||||
Weapon2Attack = 'texture/weapon/weapon2/attack',
|
||||
Bullet1Idle = 'texture/bullet/bullet1',
|
||||
Bullet2Idle = 'texture/bullet/bullet2',
|
||||
ExplosionIdle = 'texture/explosion',
|
||||
Actor1Idle = "texture/actor/actor1/idle",
|
||||
Actor1Run = "texture/actor/actor1/run",
|
||||
Actor2Idle = "texture/actor/actor2/idle",
|
||||
Actor2Run = "texture/actor/actor2/run",
|
||||
Weapon1Idle = "texture/weapon/weapon1/idle",
|
||||
Weapon1Attack = "texture/weapon/weapon1/attack",
|
||||
Weapon2Idle = "texture/weapon/weapon2/idle",
|
||||
Weapon2Attack = "texture/weapon/weapon2/attack",
|
||||
Bullet1Idle = "texture/bullet/bullet1",
|
||||
Bullet2Idle = "texture/bullet/bullet2",
|
||||
ExplosionIdle = "texture/explosion",
|
||||
}
|
||||
|
||||
export enum SceneEnum {
|
||||
Login = 'Login',
|
||||
Hall = 'Hall',
|
||||
Room = 'Room',
|
||||
Battle = 'Battle',
|
||||
}
|
||||
Login = "Login",
|
||||
Hall = "Hall",
|
||||
Room = "Room",
|
||||
Battle = "Battle",
|
||||
}
|
||||
|
@@ -1,151 +1,160 @@
|
||||
import { Node, Prefab, SpriteFrame, clamp } from 'cc'
|
||||
import Singleton from '../Base/Singleton'
|
||||
import { EntityTypeEnum, IBullet, IClientInput, InputTypeEnum, IRoom, IState, toFixed } from '../Common'
|
||||
import { ActorManager } from '../Entity/Actor/ActorManager'
|
||||
import { BulletManager } from '../Entity/Bullet/BulletManager'
|
||||
import { EventEnum } from '../Enum'
|
||||
import { JoyStickManager } from '../UI/JoyStickManager'
|
||||
import EventManager from './EventManager'
|
||||
import { Node, Prefab, SpriteFrame, clamp } from "cc";
|
||||
import Singleton from "../Base/Singleton";
|
||||
import { EntityTypeEnum, IBullet, IClientInput, InputTypeEnum, IRoom, IState, toFixed } from "../Common";
|
||||
import { ActorManager } from "../Entity/Actor/ActorManager";
|
||||
import { BulletManager } from "../Entity/Bullet/BulletManager";
|
||||
import { EventEnum } from "../Enum";
|
||||
import { JoyStickManager } from "../UI/JoyStickManager";
|
||||
import EventManager from "./EventManager";
|
||||
|
||||
const PLAYER_SPEED = 100;
|
||||
const BULLET_SPEED = 600;
|
||||
|
||||
const PLAYER_SPEED = 100
|
||||
const BULLET_SPEED = 600
|
||||
const WEAPON_DAMAGE = 5;
|
||||
|
||||
const WEAPON_DAMAGE = 5
|
||||
const PLAYER_RADIUS = 50;
|
||||
const BULLET_RADIUS = 10;
|
||||
|
||||
const PLAYER_RADIUS = 50
|
||||
const BULLET_RADIUS = 10
|
||||
|
||||
const mapW = 960
|
||||
const mapH = 640
|
||||
const mapW = 960;
|
||||
const mapH = 640;
|
||||
|
||||
export default class DataManager extends Singleton {
|
||||
static get Instance() {
|
||||
return super.GetInstance<DataManager>()
|
||||
return super.GetInstance<DataManager>();
|
||||
}
|
||||
|
||||
//登陆数据
|
||||
myPlayerId = 1
|
||||
myPlayerId = 1;
|
||||
|
||||
//大厅数据
|
||||
roomInfo: IRoom
|
||||
roomInfo: IRoom;
|
||||
|
||||
//游戏数据
|
||||
stage: Node
|
||||
jm: JoyStickManager
|
||||
prefabMap: Map<string, Prefab> = new Map()
|
||||
textureMap: Map<string, SpriteFrame[]> = new Map()
|
||||
actorMap: Map<number, ActorManager> = new Map()
|
||||
bulletMap: Map<number, BulletManager> = new Map()
|
||||
stage: Node;
|
||||
jm: JoyStickManager;
|
||||
prefabMap: Map<string, Prefab> = new Map();
|
||||
textureMap: Map<string, SpriteFrame[]> = new Map();
|
||||
actorMap: Map<number, ActorManager> = new Map();
|
||||
bulletMap: Map<number, BulletManager> = new Map();
|
||||
|
||||
reset() {
|
||||
this.stage = null
|
||||
this.jm = null
|
||||
this.actorMap.clear()
|
||||
this.bulletMap.clear()
|
||||
this.prefabMap.clear()
|
||||
this.textureMap.clear()
|
||||
this.frameId = 0;
|
||||
this.stage = null;
|
||||
this.jm = null;
|
||||
this.actorMap.clear();
|
||||
this.bulletMap.clear();
|
||||
this.prefabMap.clear();
|
||||
this.textureMap.clear();
|
||||
}
|
||||
|
||||
frameId = 0;
|
||||
lastState: IState;
|
||||
state: IState = {
|
||||
players: [{
|
||||
id: 2,
|
||||
nickname: "哈哈1",
|
||||
position: {
|
||||
x: -200,
|
||||
y: -200
|
||||
actors: [
|
||||
{
|
||||
id: 2,
|
||||
nickname: "哈哈1",
|
||||
position: {
|
||||
x: -200,
|
||||
y: -200,
|
||||
},
|
||||
direction: {
|
||||
x: 1,
|
||||
y: 0,
|
||||
},
|
||||
hp: 100,
|
||||
type: EntityTypeEnum.Actor1,
|
||||
weaponType: EntityTypeEnum.Weapon1,
|
||||
bulletType: EntityTypeEnum.Bullet1,
|
||||
},
|
||||
direction: {
|
||||
x: 1,
|
||||
y: 0
|
||||
{
|
||||
id: 1,
|
||||
nickname: "哈哈2",
|
||||
position: {
|
||||
x: 200,
|
||||
y: 200,
|
||||
},
|
||||
direction: {
|
||||
x: 0,
|
||||
y: -1,
|
||||
},
|
||||
hp: 100,
|
||||
type: EntityTypeEnum.Actor2,
|
||||
weaponType: EntityTypeEnum.Weapon2,
|
||||
bulletType: EntityTypeEnum.Bullet2,
|
||||
},
|
||||
hp: 100,
|
||||
type: EntityTypeEnum.Actor1,
|
||||
weaponType: EntityTypeEnum.Weapon1,
|
||||
bulletType: EntityTypeEnum.Bullet1,
|
||||
}, {
|
||||
id: 1,
|
||||
nickname: "哈哈2",
|
||||
position: {
|
||||
x: 200,
|
||||
y: 200
|
||||
},
|
||||
direction: {
|
||||
x: 0,
|
||||
y: -1
|
||||
},
|
||||
hp: 100,
|
||||
type: EntityTypeEnum.Actor2,
|
||||
weaponType: EntityTypeEnum.Weapon2,
|
||||
bulletType: EntityTypeEnum.Bullet2,
|
||||
}],
|
||||
],
|
||||
bullets: [],
|
||||
nextBulletId: 1
|
||||
}
|
||||
nextBulletId: 1,
|
||||
};
|
||||
|
||||
applyInput(input: IClientInput) {
|
||||
switch (input.type) {
|
||||
case InputTypeEnum.ActorMove: {
|
||||
const { direction: { x, y }, dt, id } = input
|
||||
const player = this.state.players.find(e => e.id === id)
|
||||
const {
|
||||
direction: { x, y },
|
||||
dt,
|
||||
id,
|
||||
} = input;
|
||||
const player = this.state.actors.find((e) => e.id === id);
|
||||
if (!player) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
player.position.x += toFixed(x * PLAYER_SPEED * dt)
|
||||
player.position.y += toFixed(y * PLAYER_SPEED * dt)
|
||||
player.position.x += toFixed(x * PLAYER_SPEED * dt);
|
||||
player.position.y += toFixed(y * PLAYER_SPEED * dt);
|
||||
|
||||
player.position.x = clamp(player.position.x, -mapW / 2, mapW / 2)
|
||||
player.position.y = clamp(player.position.y, -mapH / 2, mapH / 2)
|
||||
player.position.x = clamp(player.position.x, -mapW / 2, mapW / 2);
|
||||
player.position.y = clamp(player.position.y, -mapH / 2, mapH / 2);
|
||||
|
||||
player.direction = { x, y }
|
||||
break
|
||||
player.direction = { x, y };
|
||||
break;
|
||||
}
|
||||
case InputTypeEnum.WeaponShoot: {
|
||||
const { owner, position, direction } = input
|
||||
const { owner, position, direction } = input;
|
||||
const bullet: IBullet = {
|
||||
id: this.state.nextBulletId++,
|
||||
owner,
|
||||
position,
|
||||
direction,
|
||||
type: this.actorMap.get(owner).bulletType
|
||||
}
|
||||
this.state.bullets.push(bullet)
|
||||
type: this.actorMap.get(owner).bulletType,
|
||||
};
|
||||
this.state.bullets.push(bullet);
|
||||
|
||||
EventManager.Instance.emit(EventEnum.BulletBorn, owner)
|
||||
break
|
||||
EventManager.Instance.emit(EventEnum.BulletBorn, owner);
|
||||
break;
|
||||
}
|
||||
case InputTypeEnum.TimePast: {
|
||||
const { dt } = input
|
||||
const { bullets, players } = this.state
|
||||
const { dt } = input;
|
||||
const { bullets, actors } = this.state;
|
||||
|
||||
for (let i = bullets.length - 1; i >= 0; i--) {
|
||||
const bullet = bullets[i];
|
||||
for (let j = players.length - 1; j >= 0; j--) {
|
||||
const player = players[j];
|
||||
if (((player.position.x - bullet.position.x) ** 2 + (player.position.y - bullet.position.y) ** 2) < (PLAYER_RADIUS + BULLET_RADIUS) ** 2) {
|
||||
for (let j = actors.length - 1; j >= 0; j--) {
|
||||
const player = actors[j];
|
||||
if ((player.position.x - bullet.position.x) ** 2 + (player.position.y - bullet.position.y) ** 2 < (PLAYER_RADIUS + BULLET_RADIUS) ** 2) {
|
||||
EventManager.Instance.emit(EventEnum.ExplosionBorn, bullet.id, {
|
||||
x: toFixed((player.position.x + bullet.position.x) / 2),
|
||||
y: toFixed((player.position.y + bullet.position.y) / 2),
|
||||
})
|
||||
});
|
||||
|
||||
player.hp -= WEAPON_DAMAGE
|
||||
bullets.splice(i, 1)
|
||||
break
|
||||
player.hp -= WEAPON_DAMAGE;
|
||||
bullets.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Math.abs(bullet.position.x) > mapW / 2 || Math.abs(bullet.position.y) > mapH / 2) {
|
||||
EventManager.Instance.emit(EventEnum.ExplosionBorn, bullet.id, {
|
||||
x: bullet.position.x,
|
||||
y: bullet.position.y,
|
||||
})
|
||||
bullets.splice(i, 1)
|
||||
});
|
||||
bullets.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (const bullet of this.state.bullets) {
|
||||
bullet.position.x += toFixed(bullet.direction.x * BULLET_SPEED * dt)
|
||||
bullet.position.y += toFixed(bullet.direction.y * BULLET_SPEED * dt)
|
||||
bullet.position.x += toFixed(bullet.direction.x * BULLET_SPEED * dt);
|
||||
bullet.position.y += toFixed(bullet.direction.y * BULLET_SPEED * dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import Singleton from '../Base/Singleton'
|
||||
import { EventEnum } from '../Enum';
|
||||
import Singleton from "../Base/Singleton";
|
||||
import { EventEnum } from "../Enum";
|
||||
|
||||
interface IItem {
|
||||
cb: Function;
|
||||
@@ -23,7 +23,7 @@ export default class EventManager extends Singleton {
|
||||
|
||||
off(event: EventEnum, cb: Function, ctx: unknown) {
|
||||
if (this.map.has(event)) {
|
||||
const index = this.map.get(event).findIndex(i => cb === i.cb && i.ctx === ctx);
|
||||
const index = this.map.get(event).findIndex((i) => cb === i.cb && i.ctx === ctx);
|
||||
index > -1 && this.map.get(event).splice(index, 1);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ export default class EventManager extends Singleton {
|
||||
emit(event: EventEnum, ...params: unknown[]) {
|
||||
if (this.map.has(event)) {
|
||||
this.map.get(event).forEach(({ cb, ctx }) => {
|
||||
cb.apply(ctx, params)
|
||||
cb.apply(ctx, params);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import Singleton from '../Base/Singleton'
|
||||
import { ApiMsgEnum, IModel } from '../Common';
|
||||
import { binaryEncode, binaryDecode } from '../Common/Binary';
|
||||
import Singleton from "../Base/Singleton";
|
||||
import { ApiMsgEnum, IModel } from "../Common";
|
||||
import { binaryEncode, binaryDecode } from "../Common/Binary";
|
||||
|
||||
const TIMEOUT = 5000
|
||||
const TIMEOUT = 5000;
|
||||
|
||||
interface IItem {
|
||||
cb: Function;
|
||||
@@ -12,109 +12,107 @@ interface IItem {
|
||||
export interface ICallApiRet<T> {
|
||||
success: boolean;
|
||||
error?: Error;
|
||||
res?: T
|
||||
res?: T;
|
||||
}
|
||||
|
||||
type aaa = keyof IModel
|
||||
export default class NetworkManager extends Singleton {
|
||||
static get Instance() {
|
||||
return super.GetInstance<NetworkManager>()
|
||||
return super.GetInstance<NetworkManager>();
|
||||
}
|
||||
|
||||
ws: WebSocket
|
||||
port = 8888
|
||||
maps: Map<ApiMsgEnum, Array<IItem>> = new Map()
|
||||
isConnected = false
|
||||
ws: WebSocket;
|
||||
port = 8888;
|
||||
maps: Map<ApiMsgEnum, Array<IItem>> = new Map();
|
||||
isConnected = false;
|
||||
|
||||
connect() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.isConnected) {
|
||||
resolve(true)
|
||||
return
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
this.ws = new WebSocket(`ws://localhost:${this.port}`)
|
||||
this.ws = new WebSocket(`ws://localhost:${this.port}`);
|
||||
//onmessage接受的数据类型,只有在后端返回字节数组的时候才有效果
|
||||
this.ws.binaryType = 'arraybuffer';
|
||||
this.ws.binaryType = "arraybuffer";
|
||||
|
||||
this.ws.onopen = () => {
|
||||
this.isConnected = true
|
||||
resolve(true)
|
||||
}
|
||||
this.isConnected = true;
|
||||
resolve(true);
|
||||
};
|
||||
|
||||
this.ws.onerror = (e) => {
|
||||
this.isConnected = false
|
||||
console.log(e)
|
||||
reject("ws onerror")
|
||||
}
|
||||
this.isConnected = false;
|
||||
console.log(e);
|
||||
reject("ws onerror");
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
this.isConnected = false
|
||||
reject("ws onclose")
|
||||
}
|
||||
this.isConnected = false;
|
||||
reject("ws onclose");
|
||||
};
|
||||
|
||||
this.ws.onmessage = (e) => {
|
||||
try {
|
||||
const json = binaryDecode(e.data)
|
||||
const { name, data } = json
|
||||
const json = binaryDecode(e.data);
|
||||
const { name, data } = json;
|
||||
try {
|
||||
if (this.maps.has(name) && this.maps.get(name).length) {
|
||||
console.log(json);
|
||||
this.maps.get(name).forEach(({ cb, ctx }) => cb.call(ctx, data))
|
||||
this.maps.get(name).forEach(({ cb, ctx }) => cb.call(ctx, data));
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("onmessage:", error)
|
||||
console.log("onmessage:", error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('解析失败,不是合法的JSON格式', error)
|
||||
console.log("解析失败,不是合法的JSON格式", error);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
callApi<T extends keyof IModel['api']>(name: T, data: IModel['api'][T]['req']): Promise<ICallApiRet<IModel['api'][T]['res']>> {
|
||||
callApi<T extends keyof IModel["api"]>(name: T, data: IModel["api"][T]["req"]): Promise<ICallApiRet<IModel["api"][T]["res"]>> {
|
||||
return new Promise((resolve) => {
|
||||
try {
|
||||
// 超时处理
|
||||
const timer = setTimeout(() => {
|
||||
resolve({ success: false, error: new Error('timeout') })
|
||||
this.unlistenMsg(name as any, cb, null)
|
||||
}, TIMEOUT)
|
||||
resolve({ success: false, error: new Error("timeout") });
|
||||
this.unlistenMsg(name as any, cb, null);
|
||||
}, TIMEOUT);
|
||||
|
||||
// 回调处理
|
||||
const cb = (res) => {
|
||||
resolve(res)
|
||||
clearTimeout(timer)
|
||||
this.unlistenMsg(name as any, cb, null)
|
||||
}
|
||||
this.listenMsg(name as any, cb, null)
|
||||
resolve(res);
|
||||
clearTimeout(timer);
|
||||
this.unlistenMsg(name as any, cb, null);
|
||||
};
|
||||
this.listenMsg(name as any, cb, null);
|
||||
|
||||
this.sendMsg(name as any, data)
|
||||
this.sendMsg(name as any, data);
|
||||
} catch (error) {
|
||||
resolve({ success: false, error: error as Error })
|
||||
resolve({ success: false, error: error as Error });
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
async sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) {
|
||||
const view = binaryEncode(name, data)
|
||||
let delay = parseInt(new URLSearchParams(location.search).get('delay') || '0') || 0;
|
||||
await new Promise((r) => setTimeout(r, delay))
|
||||
this.ws.send(view.buffer)
|
||||
async sendMsg<T extends keyof IModel["msg"]>(name: T, data: IModel["msg"][T]) {
|
||||
const view = binaryEncode(name, data);
|
||||
let delay = parseInt(new URLSearchParams(location.search).get("delay") || "0") || 0;
|
||||
await new Promise((r) => setTimeout(r, delay));
|
||||
this.ws.send(view.buffer);
|
||||
}
|
||||
|
||||
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
|
||||
listenMsg<T extends keyof IModel["msg"]>(name: T, cb: (args: IModel["msg"][T]) => void, ctx: unknown) {
|
||||
if (this.maps.has(name)) {
|
||||
this.maps.get(name).push({ ctx, cb })
|
||||
this.maps.get(name).push({ ctx, cb });
|
||||
} else {
|
||||
this.maps.set(name, [{ ctx, cb }])
|
||||
this.maps.set(name, [{ ctx, cb }]);
|
||||
}
|
||||
}
|
||||
|
||||
unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
|
||||
unlistenMsg<T extends keyof IModel["msg"]>(name: T, cb: (args: IModel["msg"][T]) => void, ctx: unknown) {
|
||||
if (this.maps.has(name)) {
|
||||
const items = this.maps.get(name)
|
||||
const index = items.findIndex(i => cb === i.cb && i.ctx === ctx);
|
||||
index > -1 && items.splice(index, 1)
|
||||
const items = this.maps.get(name);
|
||||
const index = items.findIndex((i) => cb === i.cb && i.ctx === ctx);
|
||||
index > -1 && items.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,55 +1,55 @@
|
||||
import Singleton from '../Base/Singleton'
|
||||
import { instantiate, Node } from 'cc'
|
||||
import DataManager from './DataManager'
|
||||
import { EntityTypeEnum } from '../Common'
|
||||
import Singleton from "../Base/Singleton";
|
||||
import { instantiate, Node } from "cc";
|
||||
import DataManager from "./DataManager";
|
||||
import { EntityTypeEnum } from "../Common";
|
||||
|
||||
export default class ObjectPoolManager extends Singleton {
|
||||
static get Instance() {
|
||||
return super.GetInstance<ObjectPoolManager>()
|
||||
return super.GetInstance<ObjectPoolManager>();
|
||||
}
|
||||
|
||||
private objectPool: Node = null
|
||||
private map: Map<EntityTypeEnum, Node[]> = new Map()
|
||||
private objectPool: Node = null;
|
||||
private map: Map<EntityTypeEnum, Node[]> = new Map();
|
||||
|
||||
private getContainerName(objectName: EntityTypeEnum) {
|
||||
return objectName + 'Pool'
|
||||
return objectName + "Pool";
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.objectPool = null
|
||||
this.map.clear()
|
||||
this.objectPool = null;
|
||||
this.map.clear();
|
||||
}
|
||||
|
||||
get(objectName: EntityTypeEnum) {
|
||||
if (this.objectPool === null) {
|
||||
this.objectPool = new Node("ObjectPool")
|
||||
this.objectPool.setParent(DataManager.Instance.stage)
|
||||
this.objectPool = new Node("ObjectPool");
|
||||
this.objectPool.setParent(DataManager.Instance.stage);
|
||||
}
|
||||
|
||||
if (!this.map.has(objectName)) {
|
||||
this.map.set(objectName, [])
|
||||
const container = new Node(this.getContainerName(objectName))
|
||||
container.setParent(this.objectPool)
|
||||
this.map.set(objectName, []);
|
||||
const container = new Node(this.getContainerName(objectName));
|
||||
container.setParent(this.objectPool);
|
||||
}
|
||||
|
||||
let node: Node
|
||||
const nodes = this.map.get(objectName)
|
||||
let node: Node;
|
||||
const nodes = this.map.get(objectName);
|
||||
|
||||
if (!nodes.length) {
|
||||
const prefab = DataManager.Instance.prefabMap.get(objectName)
|
||||
node = instantiate(prefab)
|
||||
node.name = objectName
|
||||
node.setParent(this.objectPool.getChildByName(this.getContainerName(objectName)))
|
||||
const prefab = DataManager.Instance.prefabMap.get(objectName);
|
||||
node = instantiate(prefab);
|
||||
node.name = objectName;
|
||||
node.setParent(this.objectPool.getChildByName(this.getContainerName(objectName)));
|
||||
} else {
|
||||
node = nodes.pop()
|
||||
node = nodes.pop();
|
||||
}
|
||||
node.active = true
|
||||
return node
|
||||
node.active = true;
|
||||
return node;
|
||||
}
|
||||
|
||||
ret(object: Node) {
|
||||
object.active = false
|
||||
const objectName = object.name as EntityTypeEnum
|
||||
this.map.get(objectName).push(object)
|
||||
object.active = false;
|
||||
const objectName = object.name as EntityTypeEnum;
|
||||
this.map.get(objectName).push(object);
|
||||
}
|
||||
}
|
||||
|
@@ -1,32 +1,32 @@
|
||||
import { _decorator, resources, Asset } from 'cc'
|
||||
import Singleton from '../Base/Singleton'
|
||||
import { _decorator, resources, Asset } from "cc";
|
||||
import Singleton from "../Base/Singleton";
|
||||
|
||||
export class ResourceManager extends Singleton {
|
||||
static get Instance() {
|
||||
return super.GetInstance<ResourceManager>()
|
||||
return super.GetInstance<ResourceManager>();
|
||||
}
|
||||
|
||||
loadRes<T extends Asset>(path: string, type: new (...args: any[]) => T) {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
resources.load(path, type, (err, res) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadDir<T extends Asset>(path: string, type: new (...args: any[]) => T) {
|
||||
return new Promise<T[]>((resolve, reject) => {
|
||||
resources.loadDir(path, type, (err, res) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,192 +1,218 @@
|
||||
import { _decorator, Component, Node, Prefab, instantiate, SpriteFrame, director } from 'cc';
|
||||
import { ActorManager } from '../Entity/Actor/ActorManager';
|
||||
import DataManager from '../Global/DataManager';
|
||||
import { JoyStickManager } from '../UI/JoyStickManager';
|
||||
import { ResourceManager } from '../Global/ResourceManager';
|
||||
import { EventEnum, PrefabPathEnum, SceneEnum, TexturePathEnum } from '../Enum';
|
||||
import NetworkManager from '../Global/NetworkManager';
|
||||
import ObjectPoolManager from '../Global/ObjectPoolManager';
|
||||
import { BulletManager } from '../Entity/Bullet/BulletManager';
|
||||
import { ApiMsgEnum, EntityTypeEnum, IMsgServerSync, InputTypeEnum } from '../Common';
|
||||
import EventManager from '../Global/EventManager';
|
||||
import { _decorator, Component, Node, Prefab, instantiate, SpriteFrame, director } from "cc";
|
||||
import { ActorManager } from "../Entity/Actor/ActorManager";
|
||||
import DataManager from "../Global/DataManager";
|
||||
import { JoyStickManager } from "../UI/JoyStickManager";
|
||||
import { ResourceManager } from "../Global/ResourceManager";
|
||||
import { EventEnum, PrefabPathEnum, SceneEnum, TexturePathEnum } from "../Enum";
|
||||
import NetworkManager from "../Global/NetworkManager";
|
||||
import ObjectPoolManager from "../Global/ObjectPoolManager";
|
||||
import { BulletManager } from "../Entity/Bullet/BulletManager";
|
||||
import { ApiMsgEnum, EntityTypeEnum, IClientInput, IMsgServerSync, InputTypeEnum, toFixed } from "../Common";
|
||||
import EventManager from "../Global/EventManager";
|
||||
import { deepClone } from "../Utils";
|
||||
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass('BattleManager')
|
||||
@ccclass("BattleManager")
|
||||
export class BattleManager extends Component {
|
||||
private stage: Node
|
||||
private ui: Node
|
||||
private shouldUpdate = false
|
||||
private stage: Node;
|
||||
private ui: Node;
|
||||
private shouldUpdate = false;
|
||||
private pendingMsg = [];
|
||||
|
||||
async start() {
|
||||
//清空
|
||||
this.clearGame()
|
||||
async start() {
|
||||
//清空
|
||||
this.clearGame();
|
||||
|
||||
//资源加载和网络连接同步执行
|
||||
await Promise.all([this.loadRes(), this.connectServer()])
|
||||
//资源加载和网络连接同步执行
|
||||
await Promise.all([this.loadRes(), this.connectServer()]);
|
||||
|
||||
this.initGame()
|
||||
this.initGame();
|
||||
|
||||
// 在场景初始化完毕之前,卡主别的玩家,准备好以后再告知服务器,等所有玩家都准备好以后才开始,这里就不做了
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync, this.handleSync, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameEnd, this.leaveGame, this);
|
||||
EventManager.Instance.on(EventEnum.GameEnd, this.handleGameEnd, this)
|
||||
// 在场景初始化完毕之前,卡主别的玩家,准备好以后再告知服务器,等所有玩家都准备好以后才开始,这里就不做了
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync, this.listenServerSync, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameEnd, this.listenGameEnd, this);
|
||||
EventManager.Instance.on(EventEnum.ClientSync, this.handleClientSync, this);
|
||||
EventManager.Instance.on(EventEnum.GameEnd, this.handleGameEnd, this);
|
||||
}
|
||||
|
||||
clearGame() {
|
||||
//事件
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgServerSync, this.listenServerSync, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameEnd, this.listenGameEnd, this);
|
||||
EventManager.Instance.off(EventEnum.ClientSync, this.handleClientSync, this);
|
||||
EventManager.Instance.off(EventEnum.GameEnd, this.handleGameEnd, this);
|
||||
|
||||
//数据
|
||||
this.shouldUpdate = false;
|
||||
ObjectPoolManager.Instance.reset();
|
||||
DataManager.Instance.reset();
|
||||
|
||||
//节点
|
||||
this.stage = DataManager.Instance.stage = this.node.getChildByName("Stage");
|
||||
this.ui = this.node.getChildByName("UI");
|
||||
this.stage.destroyAllChildren();
|
||||
this.ui.destroyAllChildren();
|
||||
}
|
||||
|
||||
async loadRes() {
|
||||
const list = [];
|
||||
for (const type in PrefabPathEnum) {
|
||||
const p = ResourceManager.Instance.loadRes(PrefabPathEnum[type], Prefab).then((prefab) => {
|
||||
DataManager.Instance.prefabMap.set(type, prefab);
|
||||
});
|
||||
list.push(p);
|
||||
}
|
||||
|
||||
clearGame() {
|
||||
//监听
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgServerSync, this.handleSync, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameEnd, this.leaveGame, this);
|
||||
EventManager.Instance.off(EventEnum.GameEnd, this.handleGameEnd, this)
|
||||
|
||||
//数据
|
||||
this.shouldUpdate = false
|
||||
ObjectPoolManager.Instance.reset()
|
||||
DataManager.Instance.reset()
|
||||
|
||||
//节点
|
||||
this.stage = DataManager.Instance.stage = this.node.getChildByName("Stage")
|
||||
this.ui = this.node.getChildByName("UI")
|
||||
this.stage.destroyAllChildren()
|
||||
this.ui.destroyAllChildren()
|
||||
for (const type in TexturePathEnum) {
|
||||
const p = ResourceManager.Instance.loadDir(TexturePathEnum[type], SpriteFrame).then((spriteFrames) => {
|
||||
DataManager.Instance.textureMap.set(type, spriteFrames);
|
||||
});
|
||||
list.push(p);
|
||||
}
|
||||
await Promise.all(list);
|
||||
}
|
||||
|
||||
async loadRes() {
|
||||
const list = []
|
||||
for (const type in PrefabPathEnum) {
|
||||
const p = ResourceManager.Instance.loadRes(PrefabPathEnum[type], Prefab).then((prefab) => {
|
||||
DataManager.Instance.prefabMap.set(type, prefab)
|
||||
})
|
||||
list.push(p)
|
||||
}
|
||||
for (const type in TexturePathEnum) {
|
||||
const p = ResourceManager.Instance.loadDir(TexturePathEnum[type], SpriteFrame).then((spriteFrames) => {
|
||||
DataManager.Instance.textureMap.set(type, spriteFrames)
|
||||
})
|
||||
list.push(p)
|
||||
}
|
||||
await Promise.all(list)
|
||||
async connectServer() {
|
||||
if (!(await NetworkManager.Instance.connect().catch(() => false))) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
await this.connectServer();
|
||||
}
|
||||
}
|
||||
|
||||
async connectServer() {
|
||||
if (!await NetworkManager.Instance.connect().catch(() => false)) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
await this.connectServer()
|
||||
}
|
||||
async initGame() {
|
||||
this.initJoyStick();
|
||||
this.initShoot();
|
||||
this.initMap();
|
||||
this.shouldUpdate = true;
|
||||
}
|
||||
|
||||
initJoyStick() {
|
||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.JoyStick);
|
||||
const joySitck = instantiate(prefab);
|
||||
joySitck.setParent(this.ui);
|
||||
const jm = (DataManager.Instance.jm = joySitck.getComponent(JoyStickManager));
|
||||
jm.init();
|
||||
}
|
||||
|
||||
initShoot() {
|
||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Shoot);
|
||||
const shoot = instantiate(prefab);
|
||||
shoot.setParent(this.ui);
|
||||
}
|
||||
|
||||
initMap() {
|
||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Map1);
|
||||
const map = instantiate(prefab);
|
||||
map.setParent(this.stage);
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
if (!this.shouldUpdate) {
|
||||
return;
|
||||
}
|
||||
this.render();
|
||||
this.tick(dt);
|
||||
}
|
||||
|
||||
leaveGame() {
|
||||
this.clearGame()
|
||||
director.loadScene(SceneEnum.Hall);
|
||||
tick(dt: number) {
|
||||
this.tickPlayer(dt);
|
||||
// this.tickGlobal(dt)
|
||||
}
|
||||
|
||||
tickPlayer(dt: number) {
|
||||
for (const p of DataManager.Instance.state.actors) {
|
||||
const playerManager = DataManager.Instance.actorMap.get(p.id);
|
||||
if (!playerManager) {
|
||||
return;
|
||||
}
|
||||
playerManager.tick(dt);
|
||||
}
|
||||
}
|
||||
|
||||
async handleGameEnd() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiGameEnd, { rid: DataManager.Instance.roomInfo.id })
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
// tickGlobal(dt: number) {
|
||||
// DataManager.Instance.applyInput({
|
||||
// type: InputTypeEnum.TimePast,
|
||||
// dt: toFixed(dt),
|
||||
// })
|
||||
// }
|
||||
|
||||
render() {
|
||||
this.renderPlayer();
|
||||
this.renderBullet();
|
||||
}
|
||||
|
||||
renderPlayer() {
|
||||
for (const p of DataManager.Instance.state.actors) {
|
||||
let actorManager = DataManager.Instance.actorMap.get(p.id);
|
||||
if (!actorManager) {
|
||||
const playerPrefab = DataManager.Instance.prefabMap.get(p.type);
|
||||
const player = instantiate(playerPrefab);
|
||||
player.setParent(this.stage);
|
||||
actorManager = player.addComponent(ActorManager);
|
||||
DataManager.Instance.actorMap.set(p.id, actorManager);
|
||||
actorManager.init(p);
|
||||
} else {
|
||||
actorManager.render(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async initGame() {
|
||||
this.initJoyStick()
|
||||
this.initShoot()
|
||||
this.initMap()
|
||||
this.shouldUpdate = true
|
||||
renderBullet() {
|
||||
for (const b of DataManager.Instance.state.bullets) {
|
||||
let bulletManager = DataManager.Instance.bulletMap.get(b.id);
|
||||
if (!bulletManager) {
|
||||
const bullet = ObjectPoolManager.Instance.get(b.type);
|
||||
bulletManager = bullet.getComponent(BulletManager) || bullet.addComponent(BulletManager);
|
||||
DataManager.Instance.bulletMap.set(b.id, bulletManager);
|
||||
bulletManager.init(b);
|
||||
} else {
|
||||
bulletManager.render(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initJoyStick() {
|
||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.JoyStick)
|
||||
const joySitck = instantiate(prefab)
|
||||
joySitck.setParent(this.ui)
|
||||
const jm = DataManager.Instance.jm = joySitck.getComponent(JoyStickManager)
|
||||
jm.init()
|
||||
handleClientSync(input: IClientInput) {
|
||||
const msg = {
|
||||
frameId: DataManager.Instance.frameId++,
|
||||
input,
|
||||
};
|
||||
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, msg);
|
||||
|
||||
//移动才做预测,射击不做
|
||||
if (input.type === InputTypeEnum.ActorMove) {
|
||||
DataManager.Instance.applyInput(input);
|
||||
this.pendingMsg.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
initShoot() {
|
||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Shoot)
|
||||
const shoot = instantiate(prefab)
|
||||
shoot.setParent(this.ui)
|
||||
listenServerSync({ lastFrameId, inputs }: IMsgServerSync) {
|
||||
//回滚上次服务器状态
|
||||
DataManager.Instance.state = DataManager.Instance.lastState;
|
||||
//应用服务器输入
|
||||
for (const input of inputs) {
|
||||
DataManager.Instance.applyInput(input);
|
||||
}
|
||||
//记录最新的服务器状态
|
||||
DataManager.Instance.lastState = deepClone(DataManager.Instance.state);
|
||||
|
||||
initMap() {
|
||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Map1)
|
||||
const map = instantiate(prefab)
|
||||
map.setParent(this.stage)
|
||||
//过滤本地输入
|
||||
this.pendingMsg = this.pendingMsg.filter((msg) => msg.frameId > lastFrameId);
|
||||
//应用本地输入
|
||||
for (const msg of this.pendingMsg) {
|
||||
DataManager.Instance.applyInput(msg.input);
|
||||
}
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
if (!this.shouldUpdate) {
|
||||
return
|
||||
}
|
||||
this.render()
|
||||
this.tick(dt)
|
||||
}
|
||||
|
||||
tick(dt: number) {
|
||||
this.tickPlayer(dt)
|
||||
// this.tickGlobal(dt)
|
||||
}
|
||||
|
||||
tickPlayer(dt: number) {
|
||||
for (const p of DataManager.Instance.state.players) {
|
||||
const playerManager = DataManager.Instance.actorMap.get(p.id)
|
||||
if (!playerManager) {
|
||||
return
|
||||
}
|
||||
playerManager.tick(dt)
|
||||
}
|
||||
}
|
||||
|
||||
// tickGlobal(dt: number) {
|
||||
// NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
|
||||
// input: {
|
||||
// type: InputTypeEnum.TimePast,
|
||||
// dt: toFixed(dt),
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
render() {
|
||||
this.renderPlayer()
|
||||
this.renderBullet()
|
||||
}
|
||||
|
||||
renderPlayer() {
|
||||
for (const p of DataManager.Instance.state.players) {
|
||||
let playerManager = DataManager.Instance.actorMap.get(p.id)
|
||||
if (!playerManager) {
|
||||
const playerPrefab = DataManager.Instance.prefabMap.get(p.type)
|
||||
const player = instantiate(playerPrefab)
|
||||
player.setParent(this.stage)
|
||||
playerManager = player.addComponent(ActorManager)
|
||||
DataManager.Instance.actorMap.set(p.id, playerManager)
|
||||
playerManager.init(p)
|
||||
} else {
|
||||
playerManager.render(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderBullet() {
|
||||
for (const b of DataManager.Instance.state.bullets) {
|
||||
let bulletManager = DataManager.Instance.bulletMap.get(b.id)
|
||||
if (!bulletManager) {
|
||||
const bullet = ObjectPoolManager.Instance.get(b.type)
|
||||
bulletManager = bullet.getComponent(BulletManager) || bullet.addComponent(BulletManager)
|
||||
DataManager.Instance.bulletMap.set(b.id, bulletManager)
|
||||
bulletManager.init(b)
|
||||
} else {
|
||||
bulletManager.render(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleSync(inputs: IMsgServerSync) {
|
||||
for (const input of inputs) {
|
||||
DataManager.Instance.applyInput(input)
|
||||
}
|
||||
async handleGameEnd() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiGameEnd, { rid: DataManager.Instance.roomInfo.id });
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
listenGameEnd() {
|
||||
this.clearGame();
|
||||
director.loadScene(SceneEnum.Hall);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,121 +1,122 @@
|
||||
import { _decorator, Component, Node, Prefab, director, instantiate } from 'cc';
|
||||
import { ApiMsgEnum, IApiPlayerListRes, IApiRoomListRes, IMsgPlayerList, IMsgRoomList } from '../Common';
|
||||
import { EventEnum, SceneEnum } from '../Enum';
|
||||
import DataManager from '../Global/DataManager';
|
||||
import EventManager from '../Global/EventManager';
|
||||
import NetworkManager from '../Global/NetworkManager';
|
||||
import { PlayerManager } from '../UI/PlayerManager';
|
||||
import { RoomManager } from '../UI/RoomManager';
|
||||
import { _decorator, Component, Node, Prefab, director, instantiate } from "cc";
|
||||
import { ApiMsgEnum, IApiPlayerListRes, IApiRoomListRes, IMsgPlayerList, IMsgRoomList } from "../Common";
|
||||
import { EventEnum, SceneEnum } from "../Enum";
|
||||
import DataManager from "../Global/DataManager";
|
||||
import EventManager from "../Global/EventManager";
|
||||
import NetworkManager from "../Global/NetworkManager";
|
||||
import { PlayerManager } from "../UI/PlayerManager";
|
||||
import { RoomManager } from "../UI/RoomManager";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('HallManager')
|
||||
@ccclass("HallManager")
|
||||
export class HallManager extends Component {
|
||||
@property(Node)
|
||||
playerContainer: Node = null;
|
||||
@property(Node)
|
||||
playerContainer: Node = null;
|
||||
|
||||
@property(Prefab)
|
||||
playerPrefab: Prefab = null;
|
||||
@property(Prefab)
|
||||
playerPrefab: Prefab = null;
|
||||
|
||||
@property(Node)
|
||||
roomContainer: Node = null;
|
||||
@property(Node)
|
||||
roomContainer: Node = null;
|
||||
|
||||
@property(Prefab)
|
||||
roomPrefab: Prefab = null;
|
||||
@property(Prefab)
|
||||
roomPrefab: Prefab = null;
|
||||
|
||||
onLoad() {
|
||||
director.preloadScene(SceneEnum.Room);
|
||||
EventManager.Instance.on(EventEnum.RoomJoin, this.joinRoom, this)
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms, this);
|
||||
onLoad() {
|
||||
director.preloadScene(SceneEnum.Room);
|
||||
EventManager.Instance.on(EventEnum.RoomJoin, this.handleJoinRoom, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
EventManager.Instance.off(EventEnum.RoomJoin, this.handleJoinRoom, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms, this);
|
||||
}
|
||||
|
||||
start() {
|
||||
this.playerContainer.destroyAllChildren();
|
||||
this.roomContainer.destroyAllChildren();
|
||||
this.getPlayers();
|
||||
this.getRooms();
|
||||
}
|
||||
|
||||
async getPlayers() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiPlayerList, {});
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
EventManager.Instance.off(EventEnum.RoomJoin, this.joinRoom, this)
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms, this);
|
||||
this.renderPlayers(res);
|
||||
}
|
||||
|
||||
renderPlayers({ list }: IApiPlayerListRes | IMsgPlayerList) {
|
||||
for (const item of this.playerContainer.children) {
|
||||
item.active = false;
|
||||
}
|
||||
while (this.playerContainer.children.length < list.length) {
|
||||
const playerItem = instantiate(this.playerPrefab);
|
||||
playerItem.active = false;
|
||||
playerItem.setParent(this.playerContainer);
|
||||
}
|
||||
|
||||
start() {
|
||||
this.getPlayers()
|
||||
this.getRooms()
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const data = list[i];
|
||||
const node = this.playerContainer.children[i];
|
||||
const playerManager = node.getComponent(PlayerManager);
|
||||
playerManager.init(data);
|
||||
}
|
||||
}
|
||||
|
||||
async getRooms() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomList, {});
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
async getPlayers() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiPlayerList, {});
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
this.renderRooms(res);
|
||||
}
|
||||
|
||||
this.renderPlayers(res)
|
||||
renderRooms = ({ list }: IApiRoomListRes | IMsgRoomList) => {
|
||||
for (const item of this.roomContainer.children) {
|
||||
item.active = false;
|
||||
}
|
||||
while (this.roomContainer.children.length < list.length) {
|
||||
const roomItem = instantiate(this.roomPrefab);
|
||||
roomItem.active = false;
|
||||
roomItem.setParent(this.roomContainer);
|
||||
}
|
||||
|
||||
renderPlayers = ({ list }: IApiPlayerListRes | IMsgPlayerList) => {
|
||||
for (const item of this.playerContainer.children) {
|
||||
item.active = false
|
||||
}
|
||||
while (this.playerContainer.children.length < list.length) {
|
||||
const playerItem = instantiate(this.playerPrefab);
|
||||
playerItem.active = false
|
||||
playerItem.setParent(this.playerContainer)
|
||||
}
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const data = list[i];
|
||||
const node = this.roomContainer.children[i];
|
||||
const roomItemManager = node.getComponent(RoomManager);
|
||||
roomItemManager.init(data);
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const data = list[i];
|
||||
const node = this.playerContainer.children[i]
|
||||
const playerItemManager = node.getComponent(PlayerManager)
|
||||
playerItemManager.init(data)
|
||||
}
|
||||
async handleCreateRoom() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomCreate, {});
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
async getRooms() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomList, {});
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
DataManager.Instance.roomInfo = res.room;
|
||||
director.loadScene(SceneEnum.Room);
|
||||
}
|
||||
|
||||
this.renderRooms(res)
|
||||
async handleJoinRoom(rid: number) {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomJoin, { rid });
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
renderRooms = ({ list }: IApiRoomListRes | IMsgRoomList) => {
|
||||
for (const item of this.roomContainer.children) {
|
||||
item.active = false
|
||||
}
|
||||
while (this.roomContainer.children.length < list.length) {
|
||||
const roomItem = instantiate(this.roomPrefab);
|
||||
roomItem.active = false
|
||||
roomItem.setParent(this.roomContainer)
|
||||
}
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const data = list[i];
|
||||
const node = this.roomContainer.children[i]
|
||||
const roomItemManager = node.getComponent(RoomManager)
|
||||
roomItemManager.init(data)
|
||||
}
|
||||
}
|
||||
|
||||
async createRoom() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomCreate, {});
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
|
||||
DataManager.Instance.roomInfo = res.room
|
||||
director.loadScene(SceneEnum.Room);
|
||||
}
|
||||
|
||||
async joinRoom(rid: number) {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomJoin, { rid });
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
|
||||
DataManager.Instance.roomInfo = res.room
|
||||
director.loadScene(SceneEnum.Room);
|
||||
}
|
||||
DataManager.Instance.roomInfo = res.room;
|
||||
director.loadScene(SceneEnum.Room);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,45 +1,44 @@
|
||||
import { _decorator, Component, EditBox, director } from 'cc';
|
||||
import { ApiMsgEnum } from '../Common';
|
||||
import { SceneEnum } from '../Enum';
|
||||
import DataManager from '../Global/DataManager';
|
||||
import NetworkManager from '../Global/NetworkManager';
|
||||
import { _decorator, Component, EditBox, director } from "cc";
|
||||
import { ApiMsgEnum } from "../Common";
|
||||
import { SceneEnum } from "../Enum";
|
||||
import DataManager from "../Global/DataManager";
|
||||
import NetworkManager from "../Global/NetworkManager";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('LoginManager')
|
||||
@ccclass("LoginManager")
|
||||
export class LoginManager extends Component {
|
||||
input: EditBox
|
||||
input: EditBox;
|
||||
|
||||
onLoad() {
|
||||
this.input = this.node.getChildByName('Input').getComponent(EditBox)
|
||||
director.preloadScene(SceneEnum.Hall);
|
||||
onLoad() {
|
||||
this.input = this.node.getChildByName("Input").getComponent(EditBox);
|
||||
director.preloadScene(SceneEnum.Hall);
|
||||
}
|
||||
|
||||
async start() {
|
||||
await NetworkManager.Instance.connect();
|
||||
console.log("服务连接成功!");
|
||||
}
|
||||
|
||||
async handleClick() {
|
||||
if (!NetworkManager.Instance.isConnected) {
|
||||
console.log("未连接!");
|
||||
await NetworkManager.Instance.connect();
|
||||
}
|
||||
const nickname = this.input.string;
|
||||
if (!nickname) {
|
||||
console.log("请输入昵称!");
|
||||
return;
|
||||
}
|
||||
let { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiPlayerJoin, {
|
||||
nickname,
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
async start() {
|
||||
await NetworkManager.Instance.connect();
|
||||
console.log("服务连接成功!");
|
||||
}
|
||||
|
||||
async handleClick() {
|
||||
if (!NetworkManager.Instance.isConnected) {
|
||||
console.log("未连接!");
|
||||
await NetworkManager.Instance.connect();
|
||||
}
|
||||
const nickname = this.input.string;
|
||||
if (!nickname) {
|
||||
console.log("请输入昵称!")
|
||||
return;
|
||||
}
|
||||
let { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiPlayerJoin, {
|
||||
nickname,
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
DataManager.Instance.myPlayerId = res.player.id;
|
||||
director.loadScene(SceneEnum.Hall);
|
||||
}
|
||||
DataManager.Instance.myPlayerId = res.player.id;
|
||||
director.loadScene(SceneEnum.Hall);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,76 +1,77 @@
|
||||
import { _decorator, Component, Node, Prefab, director, instantiate } from 'cc';
|
||||
import { ApiMsgEnum, IMsgGameStart, IMsgRoom } from '../Common';
|
||||
import { SceneEnum } from '../Enum';
|
||||
import DataManager from '../Global/DataManager';
|
||||
import NetworkManager from '../Global/NetworkManager';
|
||||
import { PlayerManager } from '../UI/PlayerManager';
|
||||
import { _decorator, Component, Node, Prefab, director, instantiate } from "cc";
|
||||
import { ApiMsgEnum, IMsgGameStart, IMsgRoom } from "../Common";
|
||||
import { SceneEnum } from "../Enum";
|
||||
import DataManager from "../Global/DataManager";
|
||||
import NetworkManager from "../Global/NetworkManager";
|
||||
import { PlayerManager } from "../UI/PlayerManager";
|
||||
import { deepClone } from "../Utils";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('RoomManager')
|
||||
@ccclass("RoomManager")
|
||||
export class RoomManager extends Component {
|
||||
@property(Node)
|
||||
playerContainer: Node = null;
|
||||
@property(Node)
|
||||
playerContainer: Node = null;
|
||||
|
||||
@property(Prefab)
|
||||
playerPrefab: Prefab = null;
|
||||
@property(Prefab)
|
||||
playerPrefab: Prefab = null;
|
||||
|
||||
onLoad() {
|
||||
director.preloadScene(SceneEnum.Battle);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameStart, this.handleGameStart, this);
|
||||
onLoad() {
|
||||
director.preloadScene(SceneEnum.Battle);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers, this);
|
||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameStart, this.handleGameStart, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameStart, this.handleGameStart, this);
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.renderPlayers({
|
||||
room: DataManager.Instance.roomInfo,
|
||||
});
|
||||
}
|
||||
|
||||
renderPlayers({ room: { players: list } }: IMsgRoom) {
|
||||
for (const item of this.playerContainer.children) {
|
||||
item.active = false;
|
||||
}
|
||||
while (this.playerContainer.children.length < list.length) {
|
||||
const playerItem = instantiate(this.playerPrefab);
|
||||
playerItem.active = false;
|
||||
playerItem.setParent(this.playerContainer);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers, this);
|
||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameStart, this.handleGameStart, this);
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const data = list[i];
|
||||
const node = this.playerContainer.children[i];
|
||||
const playerItemManager = node.getComponent(PlayerManager);
|
||||
playerItemManager.init(data);
|
||||
}
|
||||
}
|
||||
|
||||
async handleLeave() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomLeave, {});
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.renderPlayers({
|
||||
room: DataManager.Instance.roomInfo
|
||||
})
|
||||
DataManager.Instance.roomInfo = null;
|
||||
director.loadScene(SceneEnum.Hall);
|
||||
}
|
||||
|
||||
async handleStart() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiGameStart, { rid: DataManager.Instance.roomInfo.id });
|
||||
if (!success) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
renderPlayers({ room: { players: list } }: IMsgRoom) {
|
||||
for (const item of this.playerContainer.children) {
|
||||
item.active = false
|
||||
}
|
||||
while (this.playerContainer.children.length < list.length) {
|
||||
const playerItem = instantiate(this.playerPrefab);
|
||||
playerItem.active = false
|
||||
playerItem.setParent(this.playerContainer)
|
||||
}
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const data = list[i];
|
||||
const node = this.playerContainer.children[i]
|
||||
const playerItemManager = node.getComponent(PlayerManager)
|
||||
playerItemManager.init(data)
|
||||
}
|
||||
}
|
||||
|
||||
async handleLeave() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiRoomLeave, {});
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
|
||||
DataManager.Instance.roomInfo = null
|
||||
director.loadScene(SceneEnum.Hall);
|
||||
}
|
||||
|
||||
async handleStart() {
|
||||
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiGameStart, { rid: DataManager.Instance.roomInfo.id });
|
||||
if (!success) {
|
||||
console.log(error)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleGameStart({ state }: IMsgGameStart) {
|
||||
DataManager.Instance.state = state
|
||||
director.loadScene(SceneEnum.Battle);
|
||||
}
|
||||
handleGameStart({ state }: IMsgGameStart) {
|
||||
DataManager.Instance.state = state;
|
||||
DataManager.Instance.lastState = deepClone(DataManager.Instance.state);
|
||||
director.loadScene(SceneEnum.Battle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,57 +1,55 @@
|
||||
import { _decorator, Component, Node, input, Input, EventTouch, Vec2, Vec3, UITransform } from 'cc';
|
||||
import { _decorator, Component, Node, input, Input, EventTouch, Vec2, Vec3, UITransform } from "cc";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('JoyStickManager')
|
||||
@ccclass("JoyStickManager")
|
||||
export class JoyStickManager extends Component {
|
||||
input: Vec2 = Vec2.ZERO
|
||||
input: Vec2 = Vec2.ZERO;
|
||||
|
||||
private body: Node
|
||||
private stick: Node
|
||||
private touchStartPos: Vec2
|
||||
private defaultPos: Vec2
|
||||
private radius: number = 0
|
||||
private body: Node;
|
||||
private stick: Node;
|
||||
private touchStartPos: Vec2;
|
||||
private defaultPos: Vec2;
|
||||
private radius: number = 0;
|
||||
|
||||
init() {
|
||||
this.body = this.node.getChildByName("Body")
|
||||
this.stick = this.body.getChildByName("Stick")
|
||||
const { x, y } = this.body.position
|
||||
this.defaultPos = new Vec2(x, y)
|
||||
this.radius = this.body.getComponent(UITransform).contentSize.x / 2
|
||||
init() {
|
||||
this.body = this.node.getChildByName("Body");
|
||||
this.stick = this.body.getChildByName("Stick");
|
||||
const { x, y } = this.body.position;
|
||||
this.defaultPos = new Vec2(x, y);
|
||||
this.radius = this.body.getComponent(UITransform).contentSize.x / 2;
|
||||
|
||||
input.on(Input.EventType.TOUCH_START, this.onTouchMove, this);
|
||||
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
||||
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
input.on(Input.EventType.TOUCH_START, this.onTouchMove, this);
|
||||
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
||||
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
input.off(Input.EventType.TOUCH_START, this.onTouchMove, this);
|
||||
input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
||||
input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
}
|
||||
|
||||
onTouchMove(e: EventTouch) {
|
||||
const touchPos = e.touch.getUILocation();
|
||||
if (!this.touchStartPos) {
|
||||
this.touchStartPos = touchPos.clone();
|
||||
this.body.setPosition(this.touchStartPos.x, this.touchStartPos.y);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
input.off(Input.EventType.TOUCH_START, this.onTouchMove, this);
|
||||
input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
||||
input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
const stickPos = new Vec2(touchPos.x - this.touchStartPos.x, touchPos.y - this.touchStartPos.y);
|
||||
const len = stickPos.length();
|
||||
if (len > this.radius) {
|
||||
stickPos.multiplyScalar(this.radius / len);
|
||||
}
|
||||
|
||||
onTouchMove(e: EventTouch) {
|
||||
const touchPos = e.touch.getUILocation()
|
||||
if (!this.touchStartPos) {
|
||||
this.touchStartPos = touchPos.clone()
|
||||
this.body.setPosition(this.touchStartPos.x, this.touchStartPos.y);
|
||||
}
|
||||
this.stick.setPosition(stickPos.x, stickPos.y);
|
||||
this.input = stickPos.clone().normalize();
|
||||
}
|
||||
|
||||
const stickPos = new Vec2(touchPos.x - this.touchStartPos.x, touchPos.y - this.touchStartPos.y)
|
||||
const len = stickPos.length()
|
||||
if (len > this.radius) {
|
||||
stickPos.multiplyScalar(this.radius / len)
|
||||
}
|
||||
|
||||
this.stick.setPosition(stickPos.x, stickPos.y)
|
||||
this.input = stickPos.clone().normalize()
|
||||
}
|
||||
|
||||
onTouchEnd() {
|
||||
this.body.setPosition(this.defaultPos.x, this.defaultPos.y)
|
||||
this.stick.setPosition(0, 0)
|
||||
this.touchStartPos = undefined
|
||||
this.input = Vec2.ZERO
|
||||
}
|
||||
onTouchEnd() {
|
||||
this.body.setPosition(this.defaultPos.x, this.defaultPos.y);
|
||||
this.stick.setPosition(0, 0);
|
||||
this.touchStartPos = undefined;
|
||||
this.input = Vec2.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,22 +1,19 @@
|
||||
import { _decorator, Component, Node, Label } from 'cc';
|
||||
import { EventEnum } from '../Enum';
|
||||
import DataManager from '../Global/DataManager';
|
||||
import EventManager from '../Global/EventManager';
|
||||
import { _decorator, Component, Node, Label } from "cc";
|
||||
import DataManager from "../Global/DataManager";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('PlayerManager')
|
||||
@ccclass("PlayerManager")
|
||||
export class PlayerManager extends Component {
|
||||
init({ id, nickname, rid }: { id: number, nickname: string, rid: number }) {
|
||||
const label = this.getComponent(Label)
|
||||
let str = nickname
|
||||
init({ id, nickname, rid }: { id: number; nickname: string; rid: number }) {
|
||||
const label = this.getComponent(Label);
|
||||
let str = nickname;
|
||||
if (DataManager.Instance.myPlayerId === id) {
|
||||
str += `(我)`
|
||||
str += `(我)`;
|
||||
}
|
||||
if (rid !== -1) {
|
||||
str += `(房间${rid})`
|
||||
str += `(房间${rid})`;
|
||||
}
|
||||
label.string = str
|
||||
this.node.active = true
|
||||
label.string = str;
|
||||
this.node.active = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,20 +1,19 @@
|
||||
import { _decorator, Component, Node, Label } from 'cc';
|
||||
import { EventEnum } from '../Enum';
|
||||
import EventManager from '../Global/EventManager';
|
||||
import { _decorator, Component, Node, Label } from "cc";
|
||||
import { EventEnum } from "../Enum";
|
||||
import EventManager from "../Global/EventManager";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('RoomManager')
|
||||
@ccclass("RoomManager")
|
||||
export class RoomManager extends Component {
|
||||
id: number
|
||||
init({ id, players }: { id: number, players: Array<{ id: number, nickname: string }> }) {
|
||||
this.id = id
|
||||
const label = this.getComponent(Label)
|
||||
label.string = `房间id:${id},当前人数:${players.length}`
|
||||
this.node.active = true
|
||||
id: number;
|
||||
init({ id, players }: { id: number; players: Array<{ id: number; nickname: string }> }) {
|
||||
this.id = id;
|
||||
const label = this.getComponent(Label);
|
||||
label.string = `房间id:${id},当前人数:${players.length}`;
|
||||
this.node.active = true;
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
EventManager.Instance.emit(EventEnum.RoomJoin, this.id)
|
||||
EventManager.Instance.emit(EventEnum.RoomJoin, this.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,13 +1,11 @@
|
||||
import { _decorator, Component, Node } from 'cc';
|
||||
import { EventEnum } from '../Enum';
|
||||
import EventManager from '../Global/EventManager';
|
||||
import { _decorator, Component, Node } from "cc";
|
||||
import { EventEnum } from "../Enum";
|
||||
import EventManager from "../Global/EventManager";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('ShootManager')
|
||||
@ccclass("ShootManager")
|
||||
export class ShootManager extends Component {
|
||||
shoot() {
|
||||
EventManager.Instance.emit(EventEnum.WeaponShoot)
|
||||
}
|
||||
|
||||
shoot() {
|
||||
EventManager.Instance.emit(EventEnum.WeaponShoot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,25 @@
|
||||
import { SpriteFrame } from "cc"
|
||||
import { ApiMsgEnum, InputTypeEnum, strdecode } from "../Common"
|
||||
import { SpriteFrame } from "cc";
|
||||
|
||||
const INDEX_REG = /\((\d+)\)/
|
||||
const INDEX_REG = /\((\d+)\)/;
|
||||
|
||||
const getNumberWithinString = (str: string) => parseInt(str.match(INDEX_REG)?.[1] || '0')
|
||||
const getNumberWithinString = (str: string) => parseInt(str.match(INDEX_REG)?.[1] || "0");
|
||||
|
||||
export const sortSpriteFrame = (spriteFrame: Array<SpriteFrame>) =>
|
||||
spriteFrame.sort((a, b) => getNumberWithinString(a.name) - getNumberWithinString(b.name))
|
||||
spriteFrame.sort((a, b) => getNumberWithinString(a.name) - getNumberWithinString(b.name));
|
||||
|
||||
export const rad2Angle = (rad: number) => rad / Math.PI * 180
|
||||
export const rad2Angle = (rad: number) => (rad / Math.PI) * 180;
|
||||
|
||||
export const deepClone = (obj: any) => {
|
||||
if (typeof obj !== "object" || obj === null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
const res = Array.isArray(obj) ? [] : {};
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
res[key] = deepClone(obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
Reference in New Issue
Block a user