This commit is contained in:
sli97 2022-12-03 21:28:38 +08:00
parent f3dc3ef7ba
commit a678a5b3fc
10 changed files with 76 additions and 32 deletions

2
.gitignore vendored
View File

@ -158,3 +158,5 @@ Thumbs.db
#////////////////////////// #//////////////////////////
.vscode/ .vscode/
apps/client/assets/Scripts/Common

View File

@ -4,7 +4,7 @@ import { ApiMsgEnum, EntityTypeEnum, IActor, InputTypeEnum, IVec2 } from '../../
import { EntityStateEnum } from '../../Enum'; import { EntityStateEnum } from '../../Enum';
import DataManager from '../../Global/DataManager'; import DataManager from '../../Global/DataManager';
import NetworkManager from '../../Global/NetworkManager'; import NetworkManager from '../../Global/NetworkManager';
import { rad2Angle } from '../../Utils'; import { rad2Angle, toFixed } from '../../Utils';
import { WeaponManager } from '../Weapon/WeaponManager'; import { WeaponManager } from '../Weapon/WeaponManager';
import { PlayerStateMachine } from './ActorStateMachine'; import { PlayerStateMachine } from './ActorStateMachine';
const { ccclass } = _decorator; const { ccclass } = _decorator;
@ -61,13 +61,15 @@ export class ActorManager extends EntityManager implements IActor {
const { x, y } = DataManager.Instance.jm.input const { x, y } = DataManager.Instance.jm.input
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, { NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
type: InputTypeEnum.ActorMove, input: {
id: this.id, type: InputTypeEnum.ActorMove,
direction: { id: this.id,
x, direction: {
y x: toFixed(x),
}, y: toFixed(y),
dt },
dt: toFixed(dt)
}
}) })
} }

View File

@ -5,6 +5,7 @@ import { EntityStateEnum, EventEnum } from '../../Enum'
import DataManager from '../../Global/DataManager' import DataManager from '../../Global/DataManager'
import EventManager from '../../Global/EventManager' import EventManager from '../../Global/EventManager'
import NetworkManager from '../../Global/NetworkManager' import NetworkManager from '../../Global/NetworkManager'
import { toFixed } from '../../Utils'
import { WeaponStateMachine } from './WeaponStateMachine' import { WeaponStateMachine } from './WeaponStateMachine'
const { ccclass } = _decorator const { ccclass } = _decorator
@ -61,16 +62,18 @@ export class WeaponManager extends EntityManager {
const directionVec2 = new Vec2(pointWorldPos.x - anchorWorldPos.x, pointWorldPos.y - anchorWorldPos.y).normalize() const directionVec2 = new Vec2(pointWorldPos.x - anchorWorldPos.x, pointWorldPos.y - anchorWorldPos.y).normalize()
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, { NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
type: InputTypeEnum.WeaponShoot, input: {
owner: this.owner, type: InputTypeEnum.WeaponShoot,
position: { owner: this.owner,
x: pointStagePos.x, position: {
y: pointStagePos.y x: toFixed(pointStagePos.x),
}, y: toFixed(pointStagePos.y),
direction: { },
x: directionVec2.x, direction: {
y: directionVec2.y x: toFixed(directionVec2.x),
}, y: toFixed(directionVec2.y),
},
}
}) })
} }
} }

View File

@ -22,6 +22,10 @@ export default class NetworkManager extends Singleton {
connect() { connect() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this.isConnected) {
resolve(true)
return
}
this.ws = new WebSocket(`ws://localhost:${this.port}`) this.ws = new WebSocket(`ws://localhost:${this.port}`)
this.ws.onopen = () => { this.ws.onopen = () => {
console.log("ws onopen") console.log("ws onopen")

View File

@ -7,7 +7,8 @@ import { PrefabPathEnum, TexturePathEnum } from '../Enum';
import NetworkManager from '../Global/NetworkManager'; import NetworkManager from '../Global/NetworkManager';
import ObjectPoolManager from '../Global/ObjectPoolManager'; import ObjectPoolManager from '../Global/ObjectPoolManager';
import { BulletManager } from '../Entity/Bullet/BulletManager'; import { BulletManager } from '../Entity/Bullet/BulletManager';
import { EntityTypeEnum, InputTypeEnum } from '../Common'; import { ApiMsgEnum, EntityTypeEnum, IMsgServerSync, InputTypeEnum } from '../Common';
import { toFixed } from '../Utils';
const { ccclass } = _decorator; const { ccclass } = _decorator;
@ -26,6 +27,7 @@ export class BattleManager extends Component {
await this.loadRes() await this.loadRes()
this.initScene() this.initScene()
await this.connectServer() await this.connectServer()
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync, this.handleSync);
this.isInited = true this.isInited = true
} }
@ -84,6 +86,12 @@ export class BattleManager extends Component {
map.setParent(this.stage) map.setParent(this.stage)
} }
handleSync({ inputs }: IMsgServerSync) {
for (const input of inputs) {
DataManager.Instance.applyInput(input)
}
}
update(dt: number) { update(dt: number) {
if (!this.isInited) { if (!this.isInited) {
return return
@ -108,9 +116,11 @@ export class BattleManager extends Component {
} }
tickGlobal(dt: number) { tickGlobal(dt: number) {
DataManager.Instance.applyInput({ NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
type: InputTypeEnum.TimePast, input: {
dt type: InputTypeEnum.TimePast,
dt: toFixed(dt),
}
}) })
} }

View File

@ -9,3 +9,4 @@ export const sortSpriteFrame = (spriteFrame: Array<SpriteFrame>) =>
export const rad2Angle = (rad: number) => rad / Math.PI * 180 export const rad2Angle = (rad: number) => rad / Math.PI * 180
export const toFixed = (num: number, digit: number = 4): number => Math.floor(num * 10 ** digit) / 10 ** digit

View File

@ -1,5 +1,5 @@
import { IPlayer, IRoom } from "./Model" import { IPlayer, IRoom } from "./Model"
import { IState } from "./State" import { IClientInput, IState } from "./State"
export interface IMsgPlayerList { export interface IMsgPlayerList {
list: Array<IPlayer> list: Array<IPlayer>
@ -21,3 +21,11 @@ export interface IMsgGameStart {
export interface IMsgGameStart { export interface IMsgGameStart {
state: IState state: IState
} }
export interface IMsgClientSync {
input: IClientInput
}
export interface IMsgServerSync {
inputs: Array<IClientInput>
}

View File

@ -1,4 +1,4 @@
import { ApiMsgEnum, EntityTypeEnum, IState } from '../Common' import { ApiMsgEnum, EntityTypeEnum, IClientInput, IState } from '../Common'
import type Player from './Player' import type Player from './Player'
import PlayerManager from './PlayerManager' import PlayerManager from './PlayerManager'
import RoomManager from './RoomManager' import RoomManager from './RoomManager'
@ -11,7 +11,7 @@ export default class Room {
this.id = rid this.id = rid
} }
private inputs = [] private inputs: Array<IClientInput> = []
join(uid: number) { join(uid: number) {
const player = PlayerManager.Instance.getPlayerById(uid) const player = PlayerManager.Instance.getPlayerById(uid)
@ -69,12 +69,26 @@ export default class Room {
}) })
} }
this.listenPlayer() this.listenPlayer()
setInterval(() => {
this.syncInput()
}, 300)
} }
listenPlayer() { listenPlayer() {
for (const player of this.players) { for (const player of this.players) {
player.connection.listenMsg(ApiMsgEnum.MsgClientSync, () => { } player.connection.listenMsg(ApiMsgEnum.MsgClientSync, ({ input }) => {
) this.inputs.push(input)
})
}
}
syncInput() {
const inputs = this.inputs
this.inputs = []
for (const player of this.players) {
player.connection.sendMsg(ApiMsgEnum.MsgServerSync, {
inputs
})
} }
} }
} }

View File

@ -1,6 +1,6 @@
import { IApiGameStartReq, IApiGameStartRes, IApiPlayerJoinReq, IApiPlayerJoinRes, IApiPlayerListReq, IApiPlayerListRes, IApiRoomCreateReq, IApiRoomCreateRes, IApiRoomJoinReq, IApiRoomJoinRes, IApiRoomLeaveReq, IApiRoomLeaveRes, IApiRoomListReq, IApiRoomListRes } from './Api' import { IApiGameStartReq, IApiGameStartRes, IApiPlayerJoinReq, IApiPlayerJoinRes, IApiPlayerListReq, IApiPlayerListRes, IApiRoomCreateReq, IApiRoomCreateRes, IApiRoomJoinReq, IApiRoomJoinRes, IApiRoomLeaveReq, IApiRoomLeaveRes, IApiRoomListReq, IApiRoomListRes } from './Api'
import { ApiMsgEnum } from './Enum' import { ApiMsgEnum } from './Enum'
import { IMsgGameStart, IMsgPlayerList, IMsgRoom, IMsgRoomList } from './Msg' import { IMsgClientSync, IMsgGameStart, IMsgPlayerList, IMsgRoom, IMsgRoomList, IMsgServerSync } from './Msg'
import { IClientInput } from './State' import { IClientInput } from './State'
export * from './Api' export * from './Api'
export * from './Msg' export * from './Msg'
@ -44,8 +44,8 @@ export interface IModel {
[ApiMsgEnum.MsgRoomList]: IMsgRoomList, [ApiMsgEnum.MsgRoomList]: IMsgRoomList,
[ApiMsgEnum.MsgRoom]: IMsgRoom, [ApiMsgEnum.MsgRoom]: IMsgRoom,
[ApiMsgEnum.MsgGameStart]: IMsgGameStart, [ApiMsgEnum.MsgGameStart]: IMsgGameStart,
[ApiMsgEnum.MsgClientSync]: IClientInput, [ApiMsgEnum.MsgClientSync]: IMsgClientSync,
[ApiMsgEnum.MsgServerSync]: IMsgGameStart, [ApiMsgEnum.MsgServerSync]: IMsgServerSync,
} }
} }

View File

@ -54,7 +54,7 @@ export default class Connection extends EventEmitter {
}) })
} }
listenMsg(name: string, cb: Function) { listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void) {
if (this.msgMap.has(name)) { if (this.msgMap.has(name)) {
this.msgMap.get(name)?.push(cb) this.msgMap.get(name)?.push(cb)
} else { } else {
@ -62,7 +62,7 @@ export default class Connection extends EventEmitter {
} }
} }
unlistenMsg(name: string, cb: Function) { unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void) {
if (this.msgMap.has(name)) { if (this.msgMap.has(name)) {
const index = this.msgMap.get(name)?.indexOf(cb) || -1 const index = this.msgMap.get(name)?.indexOf(cb) || -1
index > -1 && this.msgMap.get(name)?.splice(index, 1) index > -1 && this.msgMap.get(name)?.splice(index, 1)