diff --git a/examples/cocos-creator-multiplayer/backend/src/api/ApiJoin.ts b/examples/cocos-creator-multiplayer/backend/src/api/ApiJoin.ts new file mode 100644 index 0000000..f03b9ce --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/api/ApiJoin.ts @@ -0,0 +1,12 @@ +import { ApiCallWs } from "tsrpc"; +import { roomInstance } from ".."; +import { ReqJoin, ResJoin } from "../shared/protocols/PtlJoin"; + +export async function ApiJoin(call: ApiCallWs) { + let playerId = roomInstance.join(call.req, call.conn); + + call.succ({ + playerId: playerId, + gameState: roomInstance.gameSystem.state + }) +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/api/ApiJoinRoom.ts b/examples/cocos-creator-multiplayer/backend/src/api/ApiJoinRoom.ts deleted file mode 100644 index e64e371..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/api/ApiJoinRoom.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ApiCallWs } from "tsrpc"; -import { roomInstance } from ".."; -import { ReqJoinRoom, ResJoinRoom } from "../shared/protocols/PtlJoinRoom"; - -export async function ApiJoinRoom(call: ApiCallWs) { - let uid = roomInstance.join(call.req, call.conn); - - call.succ({ - uid: uid, - roomState: roomInstance.state - }) -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/index.ts b/examples/cocos-creator-multiplayer/backend/src/index.ts index 9b7d41a..46a6315 100644 --- a/examples/cocos-creator-multiplayer/backend/src/index.ts +++ b/examples/cocos-creator-multiplayer/backend/src/index.ts @@ -1,17 +1,36 @@ import 'k8w-extend-native'; import * as path from "path"; -import { WsServer } from "tsrpc"; +import { WsConnection, WsServer } from "tsrpc"; import { Room } from './models/Room'; -import { serviceProto } from './shared/protocols/serviceProto'; +import { serviceProto, ServiceType } from './shared/protocols/serviceProto'; // Create the Server export const server = new WsServer(serviceProto, { port: 3000, // Remove this to use binary mode (remove from the client too) - json: true + // json: true }); -// 测试,只有一个房间 +// 断开连接后退出房间 +server.flows.postDisconnectFlow.push(v => { + let conn = v.conn as WsConnection; + if (conn.playerId) { + roomInstance.leave(conn.playerId, conn); + } + + return v; +}) + +// 模拟网络延迟 +server.flows.preRecvDataFlow.push(async v => { + await new Promise(rs => { setTimeout(rs, 300) }) + return v; +}) +server.flows.preSendDataFlow.push(async v => { + await new Promise(rs => { setTimeout(rs, 300) }) + return v; +}) + export const roomInstance = new Room(server); // Initialize before server start diff --git a/examples/cocos-creator-multiplayer/backend/src/models/Room.ts b/examples/cocos-creator-multiplayer/backend/src/models/Room.ts index 3dd5783..e60e3e4 100644 --- a/examples/cocos-creator-multiplayer/backend/src/models/Room.ts +++ b/examples/cocos-creator-multiplayer/backend/src/models/Room.ts @@ -1,102 +1,100 @@ import { WsConnection, WsServer } from "tsrpc"; -import { ReqJoinRoom } from "../shared/protocols/PtlJoinRoom"; -import { MsgFrame } from "../shared/protocols/serverMsgs/MsgFrame"; +import { GameSystem, GameSystemInput, PlayerJoin } from "../shared/game/GameSystem"; +import { ReqJoin } from "../shared/protocols/PtlJoin"; import { ServiceType } from "../shared/protocols/serviceProto"; -import { applyPlayerInput, PlayerInput, PlayerState } from "../shared/states/Player"; -import { RoomState } from "../shared/states/RoomState"; /** * 服务端 - 房间 - 逻辑系统 */ export class Room { - state: RoomState = { - players: [] - } - // 次数/秒 - syncRate = 10; - lastUid = 0; + syncRate = 3; + nextPlayerId = 1; + + gameSystem = new GameSystem(); server: WsServer; - conns: WsConnection[] = []; - - pendingInputs: MsgFrame['inputs'] = []; + conns: WsConnection[] = []; + pendingInputs: GameSystemInput[] = []; + playerLastSn: { [playerId: number]: number | undefined } = {}; + lastSyncTime?: number; constructor(server: WsServer) { this.server = server; - setInterval(() => { this.sendSyncFrame() }, 1000 / this.syncRate); - } - - sendSyncFrame() { - // 发送同步帧 - this.server.broadcastMsg('serverMsgs/Frame', { - inputs: this.pendingInputs - }, this.conns); - this.pendingInputs = []; + setInterval(() => { this.sync() }, 1000 / this.syncRate); } /** 加入房间 */ - join(req: ReqJoinRoom, conn: WsConnection) { - let player: PlayerState = { - ...req, - uid: ++this.lastUid, + join(req: ReqJoin, conn: WsConnection) { + let input: PlayerJoin = { + type: 'PlayerJoin', + playerId: this.nextPlayerId++, // 初始位置随机 pos: { x: Math.random() * 10, y: Math.random() * 10 } } - this.conns.push(conn); - this.state.players.push(player); + this.applyInput(input); - conn.uid = player.uid; - conn.listenMsg('clientMsgs/Input', call => { - this.pendingInputs.push({ - uid: player.uid, - msgInput: call.msg - }); - this.applyInput({ - uid: player.uid, - input: call.msg - }); + this.conns.push(conn); + conn.playerId = input.playerId; + conn.listenMsg('client/ClientInput', call => { + this.playerLastSn[input.playerId] = call.msg.sn; + call.msg.inputs.forEach(v => { + this.applyInput({ + ...v, + playerId: input.playerId + }); + }) }); - this.server.broadcastMsg('serverMsgs/Join', { - player: player - }, this.conns); + return input.playerId; + } - return player.uid; + applyInput(input: GameSystemInput) { + this.pendingInputs.push(input); + } + + sync() { + let inputs = this.pendingInputs; + this.pendingInputs = []; + + // Apply inputs + inputs.forEach(v => { + this.gameSystem.applyInput(v) + }); + + // TimePast + let now = process.uptime(); + this.applyInput({ + type: 'TimePast', + dt: now - (this.lastSyncTime ?? now) + }); + this.lastSyncTime = now; + + // 发送同步帧 + this.conns.forEach(v => { + v.sendMsg('server/Frame', { + inputs: inputs, + lastSn: this.playerLastSn[v.playerId!] + }) + }); } /** 离开房间 */ - leave(uid: number, conn: WsConnection) { - this.conns.removeOne(v => v.uid === uid); - this.state.players.removeOne(v => v.uid === uid); - - conn.unlistenMsgAll('clientMsgs/Input'); - - this.server.broadcastMsg('serverMsgs/Leave', { - uid: uid - }, this.conns); + leave(playerId: number, conn: WsConnection) { + this.conns.removeOne(v => v.playerId === playerId); + this.applyInput({ + type: 'PlayerLeave', + playerId: playerId + }); } - - applyInput(input: RoomInput) { - let playerIndex = this.state.players.findIndex(v => v.uid === input.uid); - if (playerIndex > -1) { - this.state.players[playerIndex] = applyPlayerInput(this.state.players[playerIndex], input.input); - } - } - -} - -export interface RoomInput { - uid: number, - input: PlayerInput } declare module 'tsrpc' { export interface WsConnection { - uid?: number; + playerId?: number; } } \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/game/GameSystem.ts b/examples/cocos-creator-multiplayer/backend/src/shared/game/GameSystem.ts new file mode 100644 index 0000000..2c4bba0 --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/game/GameSystem.ts @@ -0,0 +1,124 @@ +import { gameConfig } from "./gameConfig"; +import { ArrowState } from "./state/ArrowState"; +import { PlayerState } from "./state/PlayerState"; + +export interface GameSystemState { + now: number, + players: PlayerState[], + arrow: ArrowState[], + nextArrowId: number +} + +export class GameSystem { + + // State (Render Pull) + private _state: GameSystemState = { + now: 0, + players: [], + arrow: [], + nextArrowId: 1 + } + get state(): Readonly { + return this._state + } + + reset(state: GameSystemState) { + this._state = Object.merge({}, state); + } + + // Input + applyInput(input: GameSystemInput) { + if (input.type === 'PlayerMove') { + let player = this._state.players.find(v => v.id === input.playerId); + if (!player) { + return; + } + + if (player.dizzyEndTime && player.dizzyEndTime > this._state.now) { + return; + } + player.pos.x += input.speed.x * input.dt; + player.pos.y += input.speed.y * input.dt; + } + else if (input.type === 'PlayerAttack') { + let player = this._state.players.find(v => v.id === input.playerId); + if (player) { + this._state.arrow.push({ + id: this._state.nextArrowId++, + fromPlayerId: input.playerId, + startPos: { ...player.pos }, + startTime: this._state.now, + targetPos: { + x: player.pos.x + input.direction.x * gameConfig.arrowDistance, + y: player.pos.y + input.direction.y * gameConfig.arrowDistance + }, + targetTime: this._state.now + gameConfig.arrowFlyTime + }); + } + } + else if (input.type === 'PlayerJoin') { + this.state.players.push({ + id: input.playerId, + pos: { ...input.pos } + }) + } + else if (input.type === 'PlayerLeave') { + this.state.players.remove(v => v.id === input.playerId); + } + else if (input.type === 'TimePast') { + this._state.now += input.dt; + + // 落地的 Arrow + for (let i = this._state.arrow.length - 1; i > -1; --i) { + let arrow = this._state.arrow[i]; + if (arrow.targetTime <= this._state.now) { + // 伤害判定 + let damagedPlayers = this._state.players.filter(v => { + return (v.pos.x - arrow.targetPos.x) * (v.pos.x - arrow.targetPos.x) + (v.pos.y - arrow.targetPos.y) * (v.pos.y - arrow.targetPos.y) <= gameConfig.arrowDistance * gameConfig.arrowDistance + }); + damagedPlayers.forEach(p => { + // 设置击晕状态 + p.dizzyEndTime = this._state.now + gameConfig.arrowDizzyTime; + + // Event + this.onDamage.forEach(h => h({ + fromPlayerId: arrow.fromPlayerId, + toPlayerId: p.id + })) + }) + } + } + } + } + + // Events (Game Push) + onDamage: ((e: { fromPlayerId: number, toPlayerId: number }) => void)[] = []; + +} + +export interface PlayerMove { + type: 'PlayerMove', + playerId: number, + speed: { x: number, y: number }, + // 移动的时间 (秒) + dt: number, +} +export interface PlayerAttack { + type: 'PlayerAttack', + playerId: number, + direction: { x: number, y: number }, +} +export interface PlayerJoin { + type: 'PlayerJoin', + playerId: number, + pos: { x: number, y: number } +} +export interface PlayerLeave { + type: 'PlayerLeave', + playerId: number +} +export interface TimePast { + type: 'TimePast', + dt: number +} +export type GameSystemInput = PlayerMove | PlayerAttack | PlayerJoin | PlayerLeave | TimePast; \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/game/gameConfig.ts b/examples/cocos-creator-multiplayer/backend/src/shared/game/gameConfig.ts new file mode 100644 index 0000000..71b2b39 --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/game/gameConfig.ts @@ -0,0 +1,10 @@ +export const gameConfig = { + // 攻击技能的冷却时间(毫秒) + attackCD: 1000, + + moveSpeed: 10, + + arrowFlyTime: 1000, + arrowDistance: 2, + arrowDizzyTime: 1000 +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/game/state/ArrowState.ts b/examples/cocos-creator-multiplayer/backend/src/shared/game/state/ArrowState.ts new file mode 100644 index 0000000..e746b7b --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/game/state/ArrowState.ts @@ -0,0 +1,8 @@ +export type ArrowState = { + id: number, + fromPlayerId: number, + startTime: number, + startPos: { x: number, y: number }, + targetTime: number, + targetPos: { x: number, y: number } +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/game/state/PlayerState.ts b/examples/cocos-creator-multiplayer/backend/src/shared/game/state/PlayerState.ts new file mode 100644 index 0000000..8004d39 --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/game/state/PlayerState.ts @@ -0,0 +1,7 @@ +export interface PlayerState { + id: number, + // 位置 + pos: { x: number, y: number }, + // 晕眩结束时间 + dizzyEndTime?: number, +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/PtlJoin.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/PtlJoin.ts new file mode 100644 index 0000000..0f85d8a --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/PtlJoin.ts @@ -0,0 +1,12 @@ +import { GameSystemState } from "../game/GameSystem"; + +export interface ReqJoin { + +} + +export interface ResJoin { + playerId: number, + gameState: GameSystemState +} + +// export const conf = {} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/PtlJoinRoom.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/PtlJoinRoom.ts deleted file mode 100644 index 46b96b0..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/PtlJoinRoom.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { PlayerState } from "../states/Player"; -import { RoomState } from "../states/RoomState"; - -export interface ReqJoinRoom { - nickname: string; - skinId: number; -} - -export interface ResJoinRoom { - uid: number, - roomState: RoomState -} - -// export const conf = {} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/client/MsgClientInput.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/client/MsgClientInput.ts new file mode 100644 index 0000000..b5cfba2 --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/client/MsgClientInput.ts @@ -0,0 +1,8 @@ +import { PlayerAttack, PlayerMove } from "../../game/GameSystem"; + +export interface MsgClientInput { + sn: number, + inputs: ClientInput[] +}; + +export type ClientInput = Omit | Omit; \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/clientMsgs/MsgInput.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/clientMsgs/MsgInput.ts deleted file mode 100644 index ae0ae07..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/clientMsgs/MsgInput.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PlayerInput } from "../../states/Player"; - -export type MsgInput = { sn: number } & PlayerInput; \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/server/MsgFrame.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/server/MsgFrame.ts new file mode 100644 index 0000000..081e125 --- /dev/null +++ b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/server/MsgFrame.ts @@ -0,0 +1,6 @@ +import { GameSystemInput } from "../../game/GameSystem"; + +export interface MsgFrame { + inputs: GameSystemInput[], + lastSn?: number +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgFrame.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgFrame.ts deleted file mode 100644 index b7716b2..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgFrame.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { MsgInput } from "../clientMsgs/MsgInput"; - -export interface MsgFrame { - inputs: { - uid: number, - msgInput: MsgInput - }[] -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgJoin.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgJoin.ts deleted file mode 100644 index 34429ae..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgJoin.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PlayerState } from "../../states/Player"; - -export interface MsgJoin { - player: PlayerState; -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgLeave.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgLeave.ts deleted file mode 100644 index adf0df5..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serverMsgs/MsgLeave.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface MsgLeave { - uid: number; -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serviceProto.ts b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serviceProto.ts index 5e2448c..fc9b4ff 100644 --- a/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serviceProto.ts +++ b/examples/cocos-creator-multiplayer/backend/src/shared/protocols/serviceProto.ts @@ -1,66 +1,128 @@ import { ServiceProto } from 'tsrpc-proto'; -import { MsgInput } from './clientMsgs/MsgInput'; -import { ReqJoinRoom, ResJoinRoom } from './PtlJoinRoom'; -import { MsgFrame } from './serverMsgs/MsgFrame'; -import { MsgJoin } from './serverMsgs/MsgJoin'; -import { MsgLeave } from './serverMsgs/MsgLeave'; +import { MsgClientInput } from './client/MsgClientInput'; +import { ReqJoin, ResJoin } from './PtlJoin'; +import { MsgFrame } from './server/MsgFrame'; export interface ServiceType { api: { - "JoinRoom": { - req: ReqJoinRoom, - res: ResJoinRoom + "Join": { + req: ReqJoin, + res: ResJoin } }, msg: { - "clientMsgs/Input": MsgInput, - "serverMsgs/Frame": MsgFrame, - "serverMsgs/Join": MsgJoin, - "serverMsgs/Leave": MsgLeave + "client/ClientInput": MsgClientInput, + "server/Frame": MsgFrame } } export const serviceProto: ServiceProto = { - "version": 3, "services": [ { - "id": 2, - "name": "clientMsgs/Input", + "id": 0, + "name": "client/ClientInput", "type": "msg" }, { - "id": 3, - "name": "JoinRoom", + "id": 1, + "name": "Join", "type": "api" }, { - "id": 7, - "name": "serverMsgs/Frame", - "type": "msg" - }, - { - "id": 4, - "name": "serverMsgs/Join", - "type": "msg" - }, - { - "id": 5, - "name": "serverMsgs/Leave", + "id": 2, + "name": "server/Frame", "type": "msg" } ], "types": { - "clientMsgs/MsgInput/MsgInput": { - "type": "Intersection", + "client/MsgClientInput/MsgClientInput": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "sn", + "type": { + "type": "Number" + } + }, + { + "id": 1, + "name": "inputs", + "type": { + "type": "Array", + "elementType": { + "type": "Reference", + "target": "client/MsgClientInput/ClientInput" + } + } + } + ] + }, + "client/MsgClientInput/ClientInput": { + "type": "Union", "members": [ { "id": 0, + "type": { + "target": { + "type": "Reference", + "target": "../game/GameSystem/PlayerMove" + }, + "keys": [ + "playerId" + ], + "type": "Omit" + } + }, + { + "id": 1, + "type": { + "target": { + "type": "Reference", + "target": "../game/GameSystem/PlayerAttack" + }, + "keys": [ + "playerId" + ], + "type": "Omit" + } + } + ] + }, + "../game/GameSystem/PlayerMove": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "type", + "type": { + "type": "Literal", + "literal": "PlayerMove" + } + }, + { + "id": 1, + "name": "playerId", + "type": { + "type": "Number" + } + }, + { + "id": 2, + "name": "speed", "type": { "type": "Interface", "properties": [ { "id": 0, - "name": "sn", + "name": "x", + "type": { + "type": "Number" + } + }, + { + "id": 1, + "name": "y", "type": { "type": "Number" } @@ -69,19 +131,15 @@ export const serviceProto: ServiceProto = { } }, { - "id": 1, + "id": 3, + "name": "dt", "type": { - "type": "Reference", - "target": "../states/Player/PlayerInput" + "type": "Number" } } ] }, - "../states/Player/PlayerInput": { - "type": "Reference", - "target": "../states/Player/PlayerMove" - }, - "../states/Player/PlayerMove": { + "../game/GameSystem/PlayerAttack": { "type": "Interface", "properties": [ { @@ -89,12 +147,19 @@ export const serviceProto: ServiceProto = { "name": "type", "type": { "type": "Literal", - "literal": "move" + "literal": "PlayerAttack" } }, { "id": 1, - "name": "offset", + "name": "playerId", + "type": { + "type": "Number" + } + }, + { + "id": 2, + "name": "direction", "type": { "type": "Interface", "properties": [ @@ -117,87 +182,276 @@ export const serviceProto: ServiceProto = { } ] }, - "PtlJoinRoom/ReqJoinRoom": { + "PtlJoin/ReqJoin": { + "type": "Interface" + }, + "PtlJoin/ResJoin": { "type": "Interface", "properties": [ { "id": 0, - "name": "nickname", + "name": "playerId", "type": { - "type": "String" + "type": "Number" } }, { "id": 1, - "name": "skinId", + "name": "gameState", "type": { - "type": "Number" + "type": "Reference", + "target": "../game/GameSystem/GameSystemState" } } ] }, - "PtlJoinRoom/ResJoinRoom": { + "../game/GameSystem/GameSystemState": { "type": "Interface", "properties": [ { "id": 0, - "name": "uid", + "name": "now", "type": { "type": "Number" } }, { - "id": 3, - "name": "roomState", - "type": { - "type": "Reference", - "target": "../states/RoomState/RoomState" - } - } - ] - }, - "../states/RoomState/RoomState": { - "type": "Interface", - "properties": [ - { - "id": 0, + "id": 1, "name": "players", "type": { "type": "Array", "elementType": { "type": "Reference", - "target": "../states/Player/PlayerState" + "target": "../game/state/PlayerState/PlayerState" } } + }, + { + "id": 2, + "name": "arrow", + "type": { + "type": "Array", + "elementType": { + "type": "Reference", + "target": "../game/state/ArrowState/ArrowState" + } + } + }, + { + "id": 3, + "name": "nextArrowId", + "type": { + "type": "Number" + } } ] }, - "../states/Player/PlayerState": { + "../game/state/PlayerState/PlayerState": { "type": "Interface", "properties": [ { "id": 0, - "name": "uid", + "name": "id", "type": { "type": "Number" } }, { "id": 1, - "name": "nickname", + "name": "pos", "type": { - "type": "String" + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "x", + "type": { + "type": "Number" + } + }, + { + "id": 1, + "name": "y", + "type": { + "type": "Number" + } + } + ] } }, { "id": 2, - "name": "skinId", + "name": "dizzyEndTime", + "type": { + "type": "Number" + }, + "optional": true + } + ] + }, + "../game/state/ArrowState/ArrowState": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "id", + "type": { + "type": "Number" + } + }, + { + "id": 1, + "name": "fromPlayerId", + "type": { + "type": "Number" + } + }, + { + "id": 2, + "name": "startTime", "type": { "type": "Number" } }, { "id": 3, + "name": "startPos", + "type": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "x", + "type": { + "type": "Number" + } + }, + { + "id": 1, + "name": "y", + "type": { + "type": "Number" + } + } + ] + } + }, + { + "id": 4, + "name": "targetTime", + "type": { + "type": "Number" + } + }, + { + "id": 5, + "name": "targetPos", + "type": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "x", + "type": { + "type": "Number" + } + }, + { + "id": 1, + "name": "y", + "type": { + "type": "Number" + } + } + ] + } + } + ] + }, + "server/MsgFrame/MsgFrame": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "inputs", + "type": { + "type": "Array", + "elementType": { + "type": "Reference", + "target": "../game/GameSystem/GameSystemInput" + } + } + }, + { + "id": 1, + "name": "lastSn", + "type": { + "type": "Number" + }, + "optional": true + } + ] + }, + "../game/GameSystem/GameSystemInput": { + "type": "Union", + "members": [ + { + "id": 0, + "type": { + "type": "Reference", + "target": "../game/GameSystem/PlayerMove" + } + }, + { + "id": 1, + "type": { + "type": "Reference", + "target": "../game/GameSystem/PlayerAttack" + } + }, + { + "id": 2, + "type": { + "type": "Reference", + "target": "../game/GameSystem/PlayerJoin" + } + }, + { + "id": 3, + "type": { + "type": "Reference", + "target": "../game/GameSystem/PlayerLeave" + } + }, + { + "id": 4, + "type": { + "type": "Reference", + "target": "../game/GameSystem/TimePast" + } + } + ] + }, + "../game/GameSystem/PlayerJoin": { + "type": "Interface", + "properties": [ + { + "id": 0, + "name": "type", + "type": { + "type": "Literal", + "literal": "PlayerJoin" + } + }, + { + "id": 1, + "name": "playerId", + "type": { + "type": "Number" + } + }, + { + "id": 2, "name": "pos", "type": { "type": "Interface", @@ -221,57 +475,40 @@ export const serviceProto: ServiceProto = { } ] }, - "serverMsgs/MsgFrame/MsgFrame": { + "../game/GameSystem/PlayerLeave": { "type": "Interface", "properties": [ { "id": 0, - "name": "inputs", + "name": "type", "type": { - "type": "Array", - "elementType": { - "type": "Interface", - "properties": [ - { - "id": 0, - "name": "uid", - "type": { - "type": "Number" - } - }, - { - "id": 1, - "name": "msgInput", - "type": { - "type": "Reference", - "target": "clientMsgs/MsgInput/MsgInput" - } - } - ] - } + "type": "Literal", + "literal": "PlayerLeave" + } + }, + { + "id": 1, + "name": "playerId", + "type": { + "type": "Number" } } ] }, - "serverMsgs/MsgJoin/MsgJoin": { + "../game/GameSystem/TimePast": { "type": "Interface", "properties": [ { "id": 0, - "name": "player", + "name": "type", "type": { - "type": "Reference", - "target": "../states/Player/PlayerState" + "type": "Literal", + "literal": "TimePast" } - } - ] - }, - "serverMsgs/MsgLeave/MsgLeave": { - "type": "Interface", - "properties": [ + }, { - "id": 0, - "name": "uid", + "id": 1, + "name": "dt", "type": { "type": "Number" } diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/states/Player.ts b/examples/cocos-creator-multiplayer/backend/src/shared/states/Player.ts deleted file mode 100644 index a152d3d..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/states/Player.ts +++ /dev/null @@ -1,30 +0,0 @@ -export interface PlayerState { - uid: number, - nickname: string, - skinId: number, - - // 可变状态 - pos: { - x: number, - y: number - } -} - -export interface PlayerMove { - type: 'move', - // 位移距离 - offset: { - x: number, - y: number - } -} -export type PlayerInput = PlayerMove; - -export function applyPlayerInput(state: PlayerState, input: PlayerInput): PlayerState { - if (input.type === 'move') { - state.pos.x += input.offset.x; - state.pos.y += input.offset.y; - } - - return state; -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/backend/src/shared/states/RoomState.ts b/examples/cocos-creator-multiplayer/backend/src/shared/states/RoomState.ts deleted file mode 100644 index b89f35c..0000000 --- a/examples/cocos-creator-multiplayer/backend/src/shared/states/RoomState.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PlayerState } from "./Player"; - -export interface RoomState { - players: PlayerState[] -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/map/newMap01.mtl b/examples/cocos-creator-multiplayer/frontend/assets/3d/map/newMap01.mtl index a2ea13c..f6505cb 100644 --- a/examples/cocos-creator-multiplayer/frontend/assets/3d/map/newMap01.mtl +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/map/newMap01.mtl @@ -4,52 +4,32 @@ "_objFlags": 0, "_native": "", "_effectAsset": { - "__uuid__": "1baf0fc9-befa-459c-8bdd-af1a450a0319" + "__uuid__": "a3cd009f-0ab0-420d-9278-b9fdab939bbc", + "__expectedType__": "cc.EffectAsset" }, "_techIdx": 0, "_defines": [ { - "USE_ALBEDO_MAP": true, - "ROUGHNESS_CHANNEL": "g", - "METALLIC_CHANNEL": "b", - "OCCLUSION_CHANNEL": "r" + "USE_TEXTURE": true } ], "_states": [ { + "rasterizerState": {}, + "depthStencilState": {}, "blendState": { "targets": [ {} ] - }, - "depthStencilState": {}, - "rasterizerState": {} + } } ], "_props": [ { - "albedoScale": { - "__type__": "cc.Vec4", - "x": 1, - "y": 1, - "z": 1, - "w": 1 - }, - "pbrScale": { - "__type__": "cc.Vec4", - "x": 1, - "y": 0.242535620927811, - "z": 0.400000005960464, - "w": 1 - }, - "alphaThreshold": 1, - "normalStrenth": 1, "mainTexture": { - "__uuid__": "27e1fcb7-5016-4252-8c43-ac9c1c97308e@6c48a" - }, - "occlusion": 1, - "roughness": 0.242535620927811, - "metallic": 0.400000005960464 + "__uuid__": "27e1fcb7-5016-4252-8c43-ac9c1c97308e@6c48a", + "__expectedType__": "cc.Texture2D" + } } ] -} +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01.meta b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01.meta new file mode 100644 index 0000000..6adfd90 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01.meta @@ -0,0 +1,12 @@ +{ + "ver": "1.1.0", + "importer": "directory", + "imported": true, + "uuid": "40e7bad4-3fa9-45c6-9d50-ce41c40e8174", + "files": [], + "subMetas": {}, + "userData": { + "compressionType": {}, + "isRemoteBundle": {} + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01/Material #7.mtl b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01/Material #7.mtl new file mode 100644 index 0000000..3c9ca99 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01/Material #7.mtl @@ -0,0 +1,43 @@ +{ + "__type__": "cc.Material", + "_name": "Material #7", + "_objFlags": 0, + "_native": "", + "_effectAsset": { + "__uuid__": "1baf0fc9-befa-459c-8bdd-af1a450a0319", + "__expectedType__": "cc.EffectAsset" + }, + "_techIdx": 0, + "_defines": [ + { + "USE_ALBEDO_MAP": true + } + ], + "_states": [ + { + "rasterizerState": {}, + "blendState": { + "targets": [ + {} + ] + }, + "depthStencilState": {} + } + ], + "_props": [ + { + "mainTexture": { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@291d4", + "__expectedType__": "cc.Texture2D" + }, + "albedoScale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "metallic": 0.400000005960464, + "roughness": 0.70710676908493 + } + ] +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01/Material #7.mtl.meta b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01/Material #7.mtl.meta new file mode 100644 index 0000000..b0c1efc --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/Materials_soldier01/Material #7.mtl.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.0.9", + "importer": "material", + "imported": true, + "uuid": "bc711895-84b3-4729-85f8-978c46347d19", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/mat_soldier.mtl b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/mat_soldier.mtl new file mode 100644 index 0000000..bd5c6e7 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/mat_soldier.mtl @@ -0,0 +1,36 @@ +{ + "__type__": "cc.Material", + "_name": "", + "_objFlags": 0, + "_native": "", + "_effectAsset": { + "__uuid__": "a3cd009f-0ab0-420d-9278-b9fdab939bbc", + "__expectedType__": "cc.EffectAsset" + }, + "_techIdx": 0, + "_defines": [ + { + "USE_INSTANCING": true, + "USE_TEXTURE": true + } + ], + "_states": [ + { + "rasterizerState": {}, + "depthStencilState": {}, + "blendState": { + "targets": [ + {} + ] + } + } + ], + "_props": [ + { + "mainTexture": { + "__uuid__": "e90ad74a-b668-4e2c-bf91-51a2a91b02aa@6c48a", + "__expectedType__": "cc.Texture2D" + } + } + ] +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/mat_soldier.mtl.meta b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/mat_soldier.mtl.meta new file mode 100644 index 0000000..1e1c27c --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/mat_soldier.mtl.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.0.9", + "importer": "material", + "imported": true, + "uuid": "5cf1ff47-b589-490a-bc78-a88f743b9798", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/soldier01.FBX.meta b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/soldier01.FBX.meta index 6be8c4b..97046ae 100644 --- a/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/soldier01.FBX.meta +++ b/examples/cocos-creator-multiplayer/frontend/assets/3d/soldier/soldier01.FBX.meta @@ -72,7 +72,7 @@ "userData": { "gltfIndex": 0, "wrapMode": 2, - "sample": 60, + "sample": 30, "span": { "from": 0.8, "to": 1.5 @@ -95,7 +95,7 @@ "userData": { "gltfIndex": 0, "wrapMode": 2, - "sample": 60, + "sample": 30, "span": { "from": 1.5333333333333334, "to": 2.2 @@ -264,14 +264,12 @@ "name": "run", "from": 0.8, "to": 1.5, - "fps": 60, "wrapMode": 2 }, { "name": "attack", "from": 1.5333333333333334, "to": 2.2, - "fps": 60, "wrapMode": 2 }, { diff --git a/examples/cocos-creator-multiplayer/frontend/assets/mat.meta b/examples/cocos-creator-multiplayer/frontend/assets/mat.meta new file mode 100644 index 0000000..a70ecb3 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/mat.meta @@ -0,0 +1,12 @@ +{ + "ver": "1.1.0", + "importer": "directory", + "imported": true, + "uuid": "e8e5dc6d-bdfe-4c40-8e74-4f36361cee55", + "files": [], + "subMetas": {}, + "userData": { + "compressionType": {}, + "isRemoteBundle": {} + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground.meta b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground.meta new file mode 100644 index 0000000..60321e2 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground.meta @@ -0,0 +1,12 @@ +{ + "ver": "1.1.0", + "importer": "directory", + "imported": true, + "uuid": "9aaf6024-7754-4b77-b5f5-7ca6d1ef973a", + "files": [], + "subMetas": {}, + "userData": { + "compressionType": {}, + "isRemoteBundle": {} + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/grass.png b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/grass.png new file mode 100644 index 0000000..fbaa5ac Binary files /dev/null and b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/grass.png differ diff --git a/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/grass.png.meta b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/grass.png.meta new file mode 100644 index 0000000..e82929c --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/grass.png.meta @@ -0,0 +1,40 @@ +{ + "ver": "1.0.21", + "importer": "image", + "imported": true, + "uuid": "ae68bc97-2fbf-4ff6-a6be-d9375f9a3423", + "files": [ + ".png", + ".json" + ], + "subMetas": { + "6c48a": { + "importer": "texture", + "uuid": "ae68bc97-2fbf-4ff6-a6be-d9375f9a3423@6c48a", + "displayName": "grass", + "id": "6c48a", + "name": "texture", + "userData": { + "wrapModeS": "repeat", + "wrapModeT": "repeat", + "minfilter": "linear", + "magfilter": "linear", + "mipfilter": "none", + "anisotropy": 0, + "isUuid": true, + "imageUuidOrDatabaseUri": "ae68bc97-2fbf-4ff6-a6be-d9375f9a3423" + }, + "ver": "1.0.21", + "imported": true, + "files": [ + ".json" + ], + "subMetas": {} + } + }, + "userData": { + "hasAlpha": false, + "type": "texture", + "redirect": "ae68bc97-2fbf-4ff6-a6be-d9375f9a3423@6c48a" + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/mat_ground.mtl b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/mat_ground.mtl new file mode 100644 index 0000000..f638675 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/mat_ground.mtl @@ -0,0 +1,42 @@ +{ + "__type__": "cc.Material", + "_name": "", + "_objFlags": 0, + "_native": "", + "_effectAsset": { + "__uuid__": "a3cd009f-0ab0-420d-9278-b9fdab939bbc", + "__expectedType__": "cc.EffectAsset" + }, + "_techIdx": 0, + "_defines": [ + { + "USE_TEXTURE": true + } + ], + "_states": [ + { + "rasterizerState": {}, + "depthStencilState": {}, + "blendState": { + "targets": [ + {} + ] + } + } + ], + "_props": [ + { + "mainTexture": { + "__uuid__": "ae68bc97-2fbf-4ff6-a6be-d9375f9a3423@6c48a", + "__expectedType__": "cc.Texture2D" + }, + "tilingOffset": { + "__type__": "cc.Vec4", + "x": 100, + "y": 100, + "z": 0, + "w": 0 + } + } + ] +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/mat_ground.mtl.meta b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/mat_ground.mtl.meta new file mode 100644 index 0000000..f4d1c8e --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/mat/mat_ground/mat_ground.mtl.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.0.9", + "importer": "material", + "imported": true, + "uuid": "00f711c1-6f4c-4de3-bc9b-52888e03f3ac", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Joystick/Joystick.ts b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Joystick/Joystick.ts index adda17b..27348cc 100644 --- a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Joystick/Joystick.ts +++ b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Joystick/Joystick.ts @@ -1,10 +1,8 @@ -import { _decorator, Component, Node, EventTouch, tween, Vec2, Vec3 } from 'cc'; -import { MathUtil } from '../../../scripts/models/MathUtil'; +import { Component, EventTouch, Node, Vec2, Vec3, _decorator } from 'cc'; +import { MathUtil } from '../../scripts/models/MathUtil'; const { ccclass, property } = _decorator; const v3_1 = new Vec3; -const v3_2 = new Vec3; - export interface JoystickOptions { onOperate: (output: JoystickOutput) => void, onOperateEnd: () => void, @@ -38,7 +36,6 @@ export class Joystick extends Component { this._options = v; } - onLoad() { this.node.on(Node.EventType.TOUCH_START, this.onTouch, this); this.node.on(Node.EventType.TOUCH_MOVE, this.onTouch, this); @@ -49,6 +46,10 @@ export class Joystick extends Component { private _touchStartPos?: Vec2; onTouch(e: EventTouch) { + if (!e.touch) { + return; + } + this.disk.active = true; let loc = e.touch.getUILocation(); diff --git a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Soldier.meta b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player.meta similarity index 100% rename from examples/cocos-creator-multiplayer/frontend/assets/prefabs/Soldier.meta rename to examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player.meta diff --git a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.prefab b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.prefab new file mode 100644 index 0000000..9cb5d59 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.prefab @@ -0,0 +1,900 @@ +[ + { + "__type__": "cc.Prefab", + "_name": "", + "_objFlags": 0, + "_native": "", + "data": { + "__id__": 1 + }, + "optimizationPolicy": 0, + "asyncLoadAssets": false + }, + { + "__type__": "cc.Node", + "_name": "Player", + "_objFlags": 0, + "_parent": null, + "_children": [ + { + "__id__": 2 + } + ], + "_active": true, + "_components": [ + { + "__id__": 31 + }, + { + "__id__": 33 + } + ], + "_prefab": { + "__id__": 35 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.Node", + "_name": "RootNode", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [ + { + "__id__": 3 + }, + { + "__id__": 17 + }, + { + "__id__": 19 + }, + { + "__id__": 21 + }, + { + "__id__": 26 + }, + { + "__id__": 28 + } + ], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 30 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.Node", + "_name": "Dummy01", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [ + { + "__id__": 4 + }, + { + "__id__": 8 + }, + { + "__id__": 10 + }, + { + "__id__": 12 + }, + { + "__id__": 14 + } + ], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 16 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 4.31247441140831e-32, + "z": 2.27106511374586e-9 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 8.146034247147302e-8, + "y": 0, + "z": 0, + "w": 0.9999999999999967 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 2.53999996185303, + "y": 2.53999996185303, + "z": 2.53999996185303 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0.000009334667642611398, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.Node", + "_name": "Body", + "_objFlags": 0, + "_parent": { + "__id__": 3 + }, + "_children": [ + { + "__id__": 5 + } + ], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 7 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -0.000466376630356535, + "y": 0.0555356666445732, + "z": -4.76837147544984e-9 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0.0000013147252531426701, + "y": 5.898311123805427e-7, + "z": 0.7037748466382776, + "w": 0.7104230888964633 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 0.256809949874878, + "y": 0.439815044403076, + "z": 0.0870304778218269 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0.006324434041980695, + "y": -0.006170109051330866, + "z": 89.46130112452344 + }, + "_id": "" + }, + { + "__type__": "cc.Node", + "_name": "head", + "_objFlags": 0, + "_parent": { + "__id__": 4 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 6 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0.931041061878204, + "y": -1.62124635494365e-7, + "z": 1.28416282052513e-8 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": -0.000007869318285142453, + "y": -2.023334521019378e-7, + "z": -0.001340885290760051, + "w": 0.9999991009819308 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1.24272096157074, + "y": 1.03568971157074, + "z": 1.0696634054184 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -0.0009017909722726095, + "y": -0.00002439492589956044, + "z": -0.15365418180060705 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "1etT/vqTVXbIC6bSTTJON5" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "38UefSlhhbc7fGntsIPZh6" + }, + { + "__type__": "cc.Node", + "_name": "legRight", + "_objFlags": 0, + "_parent": { + "__id__": 3 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 9 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -0.15381583571434, + "y": 0.0330642610788345, + "z": -4.76837147544984e-9 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0.6775014926325843, + "y": 0.20089959890094192, + "z": 0.6787423421146606, + "w": -0.19984972269874676 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 0.184104666113853, + "y": 0.347824722528458, + "z": 0.0710852295160294 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -147.07673505109858, + "y": -90.12052935501679, + "z": 0.05309133906220757 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "a7AVcLwkBZ46dzYAYb4QPx" + }, + { + "__type__": "cc.Node", + "_name": "legLeft", + "_objFlags": 0, + "_parent": { + "__id__": 3 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 11 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0.150058135390282, + "y": 0.0330642610788345, + "z": -1.43051144263495e-8 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0.6356643535110694, + "y": 0.3106639432517853, + "z": 0.635291228429095, + "w": -0.3095541941561399 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 0.184104397892952, + "y": 0.347825288772583, + "z": 0.0710852593183517 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -127.97583425594252, + "y": -90.01226481486562, + "z": 0.09407173384696697 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "6egLmgEjJSxb7mZpFf7FSD" + }, + { + "__type__": "cc.Node", + "_name": "handRight", + "_objFlags": 0, + "_parent": { + "__id__": 3 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 13 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -0.204364582896233, + "y": 0.240019470453262, + "z": -1.90734859017994e-8 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": -0.00043949465228992625, + "y": -0.00002823252593632647, + "z": 0.9849262411574669, + "w": -0.17297429151986207 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 0.184104412794113, + "y": 0.347825288772583, + "z": 0.07108523696661 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 179.9873448759303, + "y": 179.94664434517173, + "z": -19.921588202819525 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "50DRmSLnFemalb9mhuT9XN" + }, + { + "__type__": "cc.Node", + "_name": "handLeft", + "_objFlags": 0, + "_parent": { + "__id__": 3 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 15 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0.203091412782669, + "y": 0.240019470453262, + "z": -1.90734859017994e-8 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": -0.00001006337055508986, + "y": -0.0003337875805372209, + "z": -0.17397424484232848, + "w": 0.9847501462889564 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 0.184104338288307, + "y": 0.347825139760971, + "z": 0.0710852667689323 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -0.008291917560534557, + "y": -0.04030648567970078, + "z": -20.037940451355507 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "5eMcps3V1RoqefFsSsm8Sx" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "e14q0XOvhSf7Wwpr+JP8WX" + }, + { + "__type__": "cc.Node", + "_name": "Bip001", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 18 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -2.95868706703186, + "y": 0.568015873432159, + "z": 2.59012746810913 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": -0.5000003129242964, + "y": -0.49999968707550774, + "z": -0.49999968707550774, + "w": 0.5000003129242964 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 6.45159912109375, + "y": 6.45159912109375, + "z": 6.45160007476807 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -90, + "y": -89.99992828301158, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "72wx+9XH9fS5Jsw9lb3u/+" + }, + { + "__type__": "cc.Node", + "_name": "mixamorig:HeadTop_End", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 20 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -12.6684627532959, + "y": 2.27624535560608, + "z": -0.396418631076813 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0.07992084217915124, + "y": 0.35555240038341984, + "z": 0.03850968875854815, + "w": 0.9304365391786178 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 65.5876159667969, + "y": 65.5876617431641, + "z": 65.587646484375 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 7.027884698082062, + "y": 41.37325087834414, + "z": 7.382559841159056 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "758sU4GMNYEaDn4WLPV8VV" + }, + { + "__type__": "cc.Node", + "_name": "soldier01", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 22 + } + ], + "_prefab": { + "__id__": 25 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": -0.7071067811865476, + "y": 0, + "z": 0, + "w": 0.7071067811865476 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 2.53999996185303, + "y": 2.53999996185303, + "z": 2.53999996185303 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -90.00000000000003, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.SkinnedMeshRenderer", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 21 + }, + "_enabled": true, + "__prefab": { + "__id__": 23 + }, + "_materials": [ + { + "__uuid__": "5cf1ff47-b589-490a-bc78-a88f743b9798", + "__expectedType__": "cc.Material" + } + ], + "_visFlags": 0, + "lightmapSettings": { + "__id__": 24 + }, + "_mesh": { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@6868c", + "__expectedType__": "cc.Mesh" + }, + "_shadowCastingMode": 0, + "_shadowReceivingMode": 1, + "_enableMorph": true, + "_skeleton": { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@438fe", + "__expectedType__": "cc.Skeleton" + }, + "_skinningRoot": { + "__id__": 1 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "01bZIFKkBZQ5BDP5OTFTyW" + }, + { + "__type__": "cc.ModelLightmapSettings", + "texture": null, + "uvParam": { + "__type__": "cc.Vec4", + "x": 0, + "y": 0, + "z": 0, + "w": 0 + }, + "_bakeable": false, + "_castShadow": false, + "_receiveShadow": false, + "_recieveShadow": false, + "_lightmapSize": 64 + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "61gKhO2zhY0LoTCP8qRD7M" + }, + { + "__type__": "cc.Node", + "_name": "Bip001(__autogen 4)", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 27 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": 9.61940002441406, + "y": 0.568015873432159, + "z": 1.51320099830627 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": -0.5000003129242964, + "y": -0.49999968707550774, + "z": -0.49999968707550774, + "w": 0.5000003129242964 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 6.45159912109375, + "y": 6.45159912109375, + "z": 6.45160007476807 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": -90, + "y": -89.99992828301158, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "ceW5W7cCxbcIDrr7BHLBqe" + }, + { + "__type__": "cc.Node", + "_name": "mixamorig:HeadTop_End(__autogen 5)", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [], + "_prefab": { + "__id__": 29 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -0.0903754904866219, + "y": 2.27624559402466, + "z": -1.47334516048431 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0.07992084217915124, + "y": 0.35555240038341984, + "z": 0.03850968875854815, + "w": 0.9304365391786178 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 65.5876159667969, + "y": 65.5876617431641, + "z": 65.587646484375 + }, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 7.027884698082062, + "y": 41.37325087834414, + "z": 7.382559841159056 + }, + "_id": "" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "9evQBDrbhSio1m7RjvuLjN" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "30u7fnOj9WDp8SK/8khE/U" + }, + { + "__type__": "cc.SkeletalAnimation", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 32 + }, + "playOnLoad": false, + "_clips": [ + { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@1f586", + "__expectedType__": "cc.AnimationClip" + }, + { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@cf5ee", + "__expectedType__": "cc.AnimationClip" + }, + { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@989ed", + "__expectedType__": "cc.AnimationClip" + }, + { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@ee525", + "__expectedType__": "cc.AnimationClip" + }, + { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@5b2e9", + "__expectedType__": "cc.AnimationClip" + } + ], + "_defaultClip": { + "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@1f586", + "__expectedType__": "cc.AnimationClip" + }, + "_useBakedAnimation": false, + "_sockets": [], + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "71bamidCpRLIBqyoKSaXUX" + }, + { + "__type__": "720b7a4EnZJjYpzLWJrmvT/", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 34 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "fczHMULW9AAIJRjvl2FJiZ" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "71qfN53ihYmaSuBoR11P0t" + } +] \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.prefab.meta b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.prefab.meta new file mode 100644 index 0000000..845f068 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.prefab.meta @@ -0,0 +1,13 @@ +{ + "ver": "1.1.32", + "importer": "prefab", + "imported": true, + "uuid": "28c95a70-5b80-4b72-8f7b-93e2cefacc98", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": { + "syncNodeName": "Player" + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.ts b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.ts new file mode 100644 index 0000000..0431579 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.ts @@ -0,0 +1,22 @@ + +import { Component, _decorator } from 'cc'; +import { PlayerState } from '../../scripts/shared/game/state/PlayerState'; +const { ccclass, property } = _decorator; + +@ccclass('Player') +export class Player extends Component { + + playerId!: number; + isSelf = false; + + init(state: PlayerState) { + this.playerId = state.id; + this.setPos(state.pos); + } + + // 把 GameSystem 空间映射到游戏空间 + setPos(pos: { x: number, y: number }) { + this.node.setPosition(pos.y, 0, pos.x); + } + +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.ts.meta b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.ts.meta new file mode 100644 index 0000000..629e78f --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/prefabs/Player/Player.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.22", + "importer": "typescript", + "imported": true, + "uuid": "720b76b8-1276-498d-8a73-2d626b9af4ff", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.scene b/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.scene index 9800ca9..3af1c4f 100644 --- a/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.scene +++ b/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.scene @@ -17,99 +17,30 @@ { "__id__": 2 }, + { + "__id__": 6 + }, + { + "__id__": 9 + }, { "__id__": 5 }, { - "__id__": 7 - }, - { - "__id__": 15 + "__id__": 19 } ], "_active": true, "_components": [], - "_prefab": null, + "_prefab": { + "__id__": 43 + }, "autoReleaseAssets": false, "_globals": { - "__id__": 33 + "__id__": 46 }, "_id": "0d3889f6-dc9c-424e-b8cd-6fa78d63af15" }, - { - "__type__": "cc.Node", - "_name": "Main Light", - "_objFlags": 0, - "_parent": { - "__id__": 1 - }, - "_children": [], - "_active": true, - "_components": [ - { - "__id__": 3 - } - ], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.24999999999999997, - "y": -0.24999999999999997, - "z": -0.06698729810778066, - "w": 0.9330127018922194 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 1, - "y": 1, - "z": 1 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -30, - "y": -30, - "z": 0 - }, - "_id": "c0y6F5f+pAvI805TdmxIjx" - }, - { - "__type__": "cc.DirectionalLight", - "_name": "", - "_objFlags": 0, - "node": { - "__id__": 2 - }, - "_enabled": true, - "__prefab": null, - "_color": { - "__type__": "cc.Color", - "r": 255, - "g": 255, - "b": 255, - "a": 255 - }, - "_useColorTemperature": false, - "_colorTemperature": 6550, - "_staticSettings": { - "__id__": 4 - }, - "_illuminance": 100000, - "_id": "597uMYCbhEtJQc0ffJlcgA" - }, - { - "__type__": "cc.StaticLightSettings", - "_baked": false, - "_editorOnly": false, - "_bakeable": false, - "_castShadow": false - }, { "__type__": "cc.Node", "_name": "Main Camera", @@ -121,22 +52,25 @@ "_active": true, "_components": [ { - "__id__": 6 + "__id__": 3 + }, + { + "__id__": 4 } ], "_prefab": null, "_lpos": { "__type__": "cc.Vec3", - "x": -10, - "y": 10, - "z": 10 + "x": -35.352258452125874, + "y": 18.714107575144862, + "z": 5.2735593669694936e-15 }, "_lrot": { "__type__": "cc.Quat", - "x": -0.27781593346944056, - "y": -0.36497167621709875, - "z": -0.11507512748638377, - "w": 0.8811195706053617 + "x": -0.17043586674820901, + "y": -0.686259145895912, + "z": -0.170435866748209, + "w": 0.6862591458959121 }, "_lscale": { "__type__": "cc.Vec3", @@ -147,8 +81,8 @@ "_layer": 1073741824, "_euler": { "__type__": "cc.Vec3", - "x": -35, - "y": -45, + "x": -27.895, + "y": -90, "z": 0 }, "_id": "c9DMICJLFO5IeO07EPon7U" @@ -158,7 +92,7 @@ "_name": "", "_objFlags": 0, "node": { - "__id__": 5 + "__id__": 2 }, "_enabled": true, "__prefab": null, @@ -195,111 +129,20 @@ "_id": "7dWQTpwS5LrIHnc1zAPUtf" }, { - "__type__": "cc.Node", + "__type__": "db75bbNJnxHYIdxo63CSRnv", + "_name": "", "_objFlags": 0, - "_parent": { - "__id__": 1 + "node": { + "__id__": 2 }, - "_prefab": { - "__id__": 8 - } - }, - { - "__type__": "cc.PrefabInfo", - "root": { - "__id__": 7 + "_enabled": true, + "__prefab": null, + "focusTarget": { + "__id__": 5 }, - "asset": { - "__uuid__": "c26a63b9-5039-47ae-b027-ef2bce881f6f@fc11b", - "__expectedType__": "cc.Prefab" - }, - "fileId": "2cyg9D4KRTnaWvFuyUcwrn", - "instance": { - "__id__": 9 - } - }, - { - "__type__": "cc.PrefabInstance", - "fileId": "b9eQ3gXWlMR4eNhYoDs3g8", - "mountedChildren": [], - "mountedComponents": [], - "propertyOverrides": [ - { - "__id__": 10 - }, - { - "__id__": 12 - }, - { - "__id__": 13 - }, - { - "__id__": 14 - } - ], - "removedComponents": [] - }, - { - "__type__": "CCPropertyOverrideInfo", - "targetInfo": { - "__id__": 11 - }, - "propertyPath": [ - "_name" - ], - "value": "Map" - }, - { - "__type__": "cc.TargetInfo", - "localID": [ - "2cyg9D4KRTnaWvFuyUcwrn" - ] - }, - { - "__type__": "CCPropertyOverrideInfo", - "targetInfo": { - "__id__": 11 - }, - "propertyPath": [ - "_lpos" - ], - "value": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - } - }, - { - "__type__": "CCPropertyOverrideInfo", - "targetInfo": { - "__id__": 11 - }, - "propertyPath": [ - "_lrot" - ], - "value": { - "__type__": "cc.Quat", - "x": 0, - "y": 0, - "z": 0, - "w": 1 - } - }, - { - "__type__": "CCPropertyOverrideInfo", - "targetInfo": { - "__id__": 11 - }, - "propertyPath": [ - "_euler" - ], - "value": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - } + "speedFactor": 0.05, + "_distance": 40, + "_id": "1dWVUNxhZInJr8wtkL8WaB" }, { "__type__": "cc.Node", @@ -308,11 +151,7 @@ "_parent": { "__id__": 1 }, - "_children": [ - { - "__id__": 16 - } - ], + "_children": [], "_active": true, "_components": [], "_prefab": null, @@ -346,81 +185,19 @@ }, { "__type__": "cc.Node", - "_name": "Soldier", + "_name": "Plane", "_objFlags": 0, "_parent": { - "__id__": 15 + "__id__": 1 }, - "_children": [ - { - "__id__": 17 - } - ], - "_active": true, + "_children": [], + "_active": false, "_components": [ { - "__id__": 32 + "__id__": 7 } ], "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0.941, - "y": 0, - "z": -0.76 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 0, - "y": 0, - "z": 0, - "w": 1 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 1, - "y": 1, - "z": 1 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - }, - "_id": "ebyWCPQhZMyLIE8q8DzQ3L" - }, - { - "__type__": "cc.Node", - "_name": "RootNode", - "_objFlags": 0, - "_parent": { - "__id__": 16 - }, - "_children": [ - { - "__id__": 18 - }, - { - "__id__": 25 - }, - { - "__id__": 26 - }, - { - "__id__": 27 - }, - { - "__id__": 30 - }, - { - "__id__": 31 - } - ], - "_active": true, - "_components": [], - "_prefab": null, "_lpos": { "__type__": "cc.Vec3", "x": 0, @@ -436,9 +213,9 @@ }, "_lscale": { "__type__": "cc.Vec3", - "x": 1, - "y": 1, - "z": 1 + "x": 100, + "y": 100, + "z": 100 }, "_layer": 1073741824, "_euler": { @@ -447,456 +224,36 @@ "y": 0, "z": 0 }, - "_id": "b1SPz5a7NMd4JcacHxKGsn" + "_id": "1erbampNxCKK1cr4qjZjeX" }, { - "__type__": "cc.Node", - "_name": "Dummy01", - "_objFlags": 0, - "_parent": { - "__id__": 17 - }, - "_children": [ - { - "__id__": 19 - }, - { - "__id__": 21 - }, - { - "__id__": 22 - }, - { - "__id__": 23 - }, - { - "__id__": 24 - } - ], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0, - "y": 4.31247441140831e-32, - "z": 2.27106511374586e-9 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 8.146034247147302e-8, - "y": 0, - "z": 0, - "w": 0.9999999999999967 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 2.53999996185303, - "y": 2.53999996185303, - "z": 2.53999996185303 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": 0.000009334667642611398, - "y": 0, - "z": 0 - }, - "_id": "63UEIV8jVH6JFCmENPuLUg" - }, - { - "__type__": "cc.Node", - "_name": "Body", - "_objFlags": 0, - "_parent": { - "__id__": 18 - }, - "_children": [ - { - "__id__": 20 - } - ], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": -0.000466376630356535, - "y": 0.0555356666445732, - "z": -4.76837147544984e-9 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 0.0000013147252531426701, - "y": 5.898311123805427e-7, - "z": 0.7037748466382776, - "w": 0.7104230888964633 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 0.256809949874878, - "y": 0.439815044403076, - "z": 0.0870304778218269 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": 0.006324434041980695, - "y": -0.006170109051330866, - "z": 89.46130112452344 - }, - "_id": "c3Kc0wgrVLqLDbm0JqXiO4" - }, - { - "__type__": "cc.Node", - "_name": "head", - "_objFlags": 0, - "_parent": { - "__id__": 19 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0.931041061878204, - "y": -1.62124635494365e-7, - "z": 1.28416282052513e-8 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.000007869318285142453, - "y": -2.023334521019378e-7, - "z": -0.001340885290760051, - "w": 0.9999991009819308 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 1.24272096157074, - "y": 1.03568971157074, - "z": 1.0696634054184 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -0.0009017909722726095, - "y": -0.00002439492589956044, - "z": -0.15365418180060705 - }, - "_id": "b5X2VEA8RGd4hx8OiMzv/Z" - }, - { - "__type__": "cc.Node", - "_name": "legRight", - "_objFlags": 0, - "_parent": { - "__id__": 18 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": -0.15381583571434, - "y": 0.0330642610788345, - "z": -4.76837147544984e-9 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 0.6775014926325843, - "y": 0.20089959890094192, - "z": 0.6787423421146606, - "w": -0.19984972269874676 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 0.184104666113853, - "y": 0.347824722528458, - "z": 0.0710852295160294 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -147.07673505109858, - "y": -90.12052935501679, - "z": 0.05309133906220757 - }, - "_id": "e1fluQIndNObRTN+XQDXHF" - }, - { - "__type__": "cc.Node", - "_name": "legLeft", - "_objFlags": 0, - "_parent": { - "__id__": 18 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0.150058135390282, - "y": 0.0330642610788345, - "z": -1.43051144263495e-8 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 0.6356643535110694, - "y": 0.3106639432517853, - "z": 0.635291228429095, - "w": -0.3095541941561399 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 0.184104397892952, - "y": 0.347825288772583, - "z": 0.0710852593183517 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -127.97583425594252, - "y": -90.01226481486562, - "z": 0.09407173384696697 - }, - "_id": "68iMhCIVZK+7BrYtACLsh8" - }, - { - "__type__": "cc.Node", - "_name": "handRight", - "_objFlags": 0, - "_parent": { - "__id__": 18 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": -0.204364582896233, - "y": 0.240019470453262, - "z": -1.90734859017994e-8 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.00043949465228992625, - "y": -0.00002823252593632647, - "z": 0.9849262411574669, - "w": -0.17297429151986207 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 0.184104412794113, - "y": 0.347825288772583, - "z": 0.07108523696661 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": 179.9873448759303, - "y": 179.94664434517173, - "z": -19.921588202819525 - }, - "_id": "7bTKOHx6JFo6TQB1hhAXLX" - }, - { - "__type__": "cc.Node", - "_name": "handLeft", - "_objFlags": 0, - "_parent": { - "__id__": 18 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0.203091412782669, - "y": 0.240019470453262, - "z": -1.90734859017994e-8 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.00001006337055508986, - "y": -0.0003337875805372209, - "z": -0.17397424484232848, - "w": 0.9847501462889564 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 0.184104338288307, - "y": 0.347825139760971, - "z": 0.0710852667689323 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -0.008291917560534557, - "y": -0.04030648567970078, - "z": -20.037940451355507 - }, - "_id": "0cvPWKogRPMoUakKiazJUx" - }, - { - "__type__": "cc.Node", - "_name": "Bip001", - "_objFlags": 0, - "_parent": { - "__id__": 17 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": -2.95868706703186, - "y": 0.568015873432159, - "z": 2.59012746810913 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.5000003129242964, - "y": -0.49999968707550774, - "z": -0.49999968707550774, - "w": 0.5000003129242964 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 6.45159912109375, - "y": 6.45159912109375, - "z": 6.45160007476807 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -90, - "y": -89.99992828301158, - "z": 0 - }, - "_id": "31vrZWcK9HRp5vyFtVjdDB" - }, - { - "__type__": "cc.Node", - "_name": "mixamorig:HeadTop_End", - "_objFlags": 0, - "_parent": { - "__id__": 17 - }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": -12.6684627532959, - "y": 2.27624535560608, - "z": -0.396418631076813 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": 0.07992084217915124, - "y": 0.35555240038341984, - "z": 0.03850968875854815, - "w": 0.9304365391786178 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 65.5876159667969, - "y": 65.5876617431641, - "z": 65.587646484375 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": 7.027884698082062, - "y": 41.37325087834414, - "z": 7.382559841159056 - }, - "_id": "94wDRuucREC4GyndIAbp/E" - }, - { - "__type__": "cc.Node", - "_name": "soldier01", - "_objFlags": 0, - "_parent": { - "__id__": 17 - }, - "_children": [], - "_active": true, - "_components": [ - { - "__id__": 28 - } - ], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.7071067811865476, - "y": 0, - "z": 0, - "w": 0.7071067811865476 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 2.53999996185303, - "y": 2.53999996185303, - "z": 2.53999996185303 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -90.00000000000003, - "y": 0, - "z": 0 - }, - "_id": "af/w/4nmxBA7EI7p6SWLJ+" - }, - { - "__type__": "cc.SkinnedMeshRenderer", - "_name": "", + "__type__": "cc.MeshRenderer", + "_name": "Plane", "_objFlags": 0, + "__editorExtras__": {}, "node": { - "__id__": 27 + "__id__": 6 }, "_enabled": true, "__prefab": null, "_materials": [ { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@95953", + "__uuid__": "00f711c1-6f4c-4de3-bc9b-52888e03f3ac", "__expectedType__": "cc.Material" } ], "_visFlags": 0, "lightmapSettings": { - "__id__": 29 + "__id__": 8 }, "_mesh": { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@6868c", + "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@2e76e", "__expectedType__": "cc.Mesh" }, "_shadowCastingMode": 0, "_shadowReceivingMode": 1, "_enableMorph": true, - "_skeleton": { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@438fe", - "__expectedType__": "cc.Skeleton" - }, - "_skinningRoot": { - "__id__": 16 - }, - "_id": "30YHOawqJAk45mqt1Kv4o4" + "_id": "82T+4KKehOcqLqvINaID/a" }, { "__type__": "cc.ModelLightmapSettings", @@ -916,135 +273,608 @@ }, { "__type__": "cc.Node", - "_name": "Bip001(__autogen 4)", "_objFlags": 0, "_parent": { - "__id__": 17 + "__id__": 1 }, - "_children": [], - "_active": true, - "_components": [], - "_prefab": null, - "_lpos": { + "_prefab": { + "__id__": 10 + } + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 9 + }, + "asset": { + "__uuid__": "c26a63b9-5039-47ae-b027-ef2bce881f6f@fc11b", + "__expectedType__": "cc.Prefab" + }, + "fileId": "2cyg9D4KRTnaWvFuyUcwrn", + "instance": { + "__id__": 11 + } + }, + { + "__type__": "cc.PrefabInstance", + "fileId": "e7wpFdRzxFupYfDrzr/lg7", + "mountedChildren": [], + "mountedComponents": [], + "propertyOverrides": [ + { + "__id__": 12 + }, + { + "__id__": 14 + }, + { + "__id__": 15 + }, + { + "__id__": 16 + }, + { + "__id__": 17 + } + ], + "removedComponents": [] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 13 + }, + "propertyPath": [ + "_name" + ], + "value": "newMap01" + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "2cyg9D4KRTnaWvFuyUcwrn" + ] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 13 + }, + "propertyPath": [ + "_lpos" + ], + "value": { "__type__": "cc.Vec3", - "x": 9.61940002441406, - "y": 0.568015873432159, - "z": 1.51320099830627 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.5000003129242964, - "y": -0.49999968707550774, - "z": -0.49999968707550774, - "w": 0.5000003129242964 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 6.45159912109375, - "y": 6.45159912109375, - "z": 6.45160007476807 - }, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -90, - "y": -89.99992828301158, + "x": 0, + "y": 0, "z": 0 + } + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 13 }, - "_id": "c9relHXCxD8buEcxdgkJHW" + "propertyPath": [ + "_lrot" + ], + "value": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + } + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 13 + }, + "propertyPath": [ + "_euler" + ], + "value": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + } + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 18 + }, + "propertyPath": [ + "_materials", + "0" + ], + "value": { + "__uuid__": "b7d6d595-6cd1-43c6-8bc7-3a92644870b9", + "__expectedType__": "cc.Material" + } + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "7cPmRsw4Ne67cKUY0ub3s2" + ] }, { "__type__": "cc.Node", - "_name": "mixamorig:HeadTop_End(__autogen 5)", + "_name": "Canvas", "_objFlags": 0, "_parent": { - "__id__": 17 + "__id__": 1 }, - "_children": [], + "_children": [ + { + "__id__": 20 + }, + { + "__id__": 22 + } + ], "_active": true, - "_components": [], + "_components": [ + { + "__id__": 39 + }, + { + "__id__": 40 + }, + { + "__id__": 41 + }, + { + "__id__": 42 + } + ], "_prefab": null, "_lpos": { "__type__": "cc.Vec3", - "x": -0.0903754904866219, - "y": 2.27624559402466, - "z": -1.47334516048431 + "x": 375, + "y": 667, + "z": 0 }, "_lrot": { "__type__": "cc.Quat", - "x": 0.07992084217915124, - "y": 0.35555240038341984, - "z": 0.03850968875854815, - "w": 0.9304365391786178 + "x": 0, + "y": 0, + "z": 0, + "w": 1 }, "_lscale": { "__type__": "cc.Vec3", - "x": 65.5876159667969, - "y": 65.5876617431641, - "z": 65.587646484375 + "x": 1, + "y": 1, + "z": 1 + }, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "2bu+Wz5ktPl5ljMhLdUST8" + }, + { + "__type__": "cc.Node", + "_name": "Camera", + "_objFlags": 0, + "_parent": { + "__id__": 19 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 21 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 1000 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 }, "_layer": 1073741824, "_euler": { "__type__": "cc.Vec3", - "x": 7.027884698082062, - "y": 41.37325087834414, - "z": 7.382559841159056 + "x": 0, + "y": 0, + "z": 0 }, - "_id": "18OPyREQRP0bZHBbgBDM0L" + "_id": "ccmFJo9bNJT7Wqp2Z77wkb" }, { - "__type__": "cc.SkeletalAnimation", + "__type__": "cc.Camera", "_name": "", "_objFlags": 0, "node": { - "__id__": 16 + "__id__": 20 }, "_enabled": true, "__prefab": null, - "playOnLoad": false, - "_clips": [ + "_projection": 0, + "_priority": 1073741824, + "_fov": 45, + "_fovAxis": 0, + "_orthoHeight": 667, + "_near": 1, + "_far": 2000, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_depth": 1, + "_stencil": 0, + "_clearFlags": 6, + "_rect": { + "__type__": "cc.Rect", + "x": 0, + "y": 0, + "width": 1, + "height": 1 + }, + "_aperture": 19, + "_shutter": 7, + "_iso": 0, + "_screenScale": 1, + "_visibility": 41943040, + "_targetTexture": null, + "_id": "cbSLFrEq5ISoMAhCFPuoSv" + }, + { + "__type__": "cc.Node", + "_objFlags": 0, + "_parent": { + "__id__": 19 + }, + "_prefab": { + "__id__": 23 + } + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 22 + }, + "asset": { + "__uuid__": "0363f7f8-204e-410e-ade0-03adca6ea835", + "__expectedType__": "cc.Prefab" + }, + "fileId": "25fHuwytBN2qk6dH5oVJvO", + "instance": { + "__id__": 24 + } + }, + { + "__type__": "cc.PrefabInstance", + "fileId": "41rO7rBitC0KYZRU0Z4peA", + "mountedChildren": [], + "mountedComponents": [], + "propertyOverrides": [ { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@1f586", - "__expectedType__": "cc.AnimationClip" + "__id__": 25 }, { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@cf5ee", - "__expectedType__": "cc.AnimationClip" + "__id__": 27 }, { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@989ed", - "__expectedType__": "cc.AnimationClip" + "__id__": 28 }, { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@ee525", - "__expectedType__": "cc.AnimationClip" + "__id__": 29 }, { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@5b2e9", - "__expectedType__": "cc.AnimationClip" + "__id__": 30 + }, + { + "__id__": 32 + }, + { + "__id__": 33 + }, + { + "__id__": 35 + }, + { + "__id__": 37 } ], - "_defaultClip": { - "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@1f586", - "__expectedType__": "cc.AnimationClip" + "removedComponents": [] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 26 }, - "_useBakedAnimation": true, - "_sockets": [], - "_id": "d4kBjIp3xEdIVjRiQqSIsg" + "propertyPath": [ + "_name" + ], + "value": "Joystick" + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "25fHuwytBN2qk6dH5oVJvO" + ] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 26 + }, + "propertyPath": [ + "_lpos" + ], + "value": { + "__type__": "cc.Vec3", + "x": -375, + "y": -667, + "z": 0 + } + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 26 + }, + "propertyPath": [ + "_lrot" + ], + "value": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + } + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 26 + }, + "propertyPath": [ + "_euler" + ], + "value": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + } + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 31 + }, + "propertyPath": [ + "_contentSize" + ], + "value": { + "__type__": "cc.Size", + "width": 750, + "height": 1334 + } + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "03ZUWxyGxEKrRNfAAZAjfl" + ] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 26 + }, + "propertyPath": [ + "_layer" + ], + "value": 33554432 + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 34 + }, + "propertyPath": [ + "_layer" + ], + "value": 33554432 + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "d0wZ2A2kRHRL52JXTqW2TD" + ] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 36 + }, + "propertyPath": [ + "_layer" + ], + "value": 33554432 + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "99DpUW4QRIJ4zS/1nooi0x" + ] + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 38 + }, + "propertyPath": [ + "_layer" + ], + "value": 33554432 + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "ceQ/tc9/lBPIsW1Hwyb91a" + ] + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 19 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 750, + "height": 1334 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "26kd0+oj5JE6lQOL2JM9ql" + }, + { + "__type__": "cc.Canvas", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 19 + }, + "_enabled": true, + "__prefab": null, + "_cameraComponent": { + "__id__": 21 + }, + "_alignCanvasWithScreen": true, + "_id": "ebX9QTnS1AlKH1eI+/bdJk" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 19 + }, + "_enabled": true, + "__prefab": null, + "_alignFlags": 45, + "_target": null, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_horizontalCenter": 0, + "_verticalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 0, + "_alignMode": 2, + "_lockFlags": 0, + "_id": "c97irTOvNCH7Mmyire8Buy" + }, + { + "__type__": "d4728cOzxlKHLMu5Xg48U8U", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 19 + }, + "_enabled": true, + "__prefab": null, + "joyStick": null, + "prefabPlayer": { + "__uuid__": "28c95a70-5b80-4b72-8f7b-93e2cefacc98", + "__expectedType__": "cc.Prefab" + }, + "players": { + "__id__": 5 + }, + "camera": { + "__id__": 4 + }, + "_id": "86PJf2PFRK5LGUONuKqmzS" + }, + { + "__type__": "cc.PrefabInfo", + "fileId": "", + "targetOverrides": [ + { + "__id__": 44 + } + ] + }, + { + "__type__": "cc.TargetOverrideInfo", + "source": { + "__id__": 42 + }, + "sourceInfo": null, + "propertyPath": [ + "joyStick" + ], + "target": { + "__id__": 22 + }, + "targetInfo": { + "__id__": 45 + } + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "b6/h8KXgpAI6dQQRwusaRr" + ] }, { "__type__": "cc.SceneGlobals", "ambient": { - "__id__": 34 + "__id__": 47 }, "shadows": { - "__id__": 35 + "__id__": 48 }, "_skybox": { - "__id__": 36 + "__id__": 49 }, "fog": { - "__id__": 37 + "__id__": 50 } }, { diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.ts b/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.ts new file mode 100644 index 0000000..125b943 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.ts @@ -0,0 +1,115 @@ + +import { Component, instantiate, Node, Prefab, Vec2, _decorator } from 'cc'; +import { WsClient } from 'tsrpc-browser'; +import { Joystick } from '../../prefabs/Joystick/Joystick'; +import { Player } from '../../prefabs/Player/Player'; +import { FollowCamera } from '../../scripts/components/FollowCamera'; +import { GameManager } from '../../scripts/models/GameManager'; +import { gameConfig } from '../../scripts/shared/game/gameConfig'; +import { serviceProto, ServiceType } from '../../scripts/shared/protocols/serviceProto'; +const { ccclass, property } = _decorator; + +/** + * Predefined variables + * Name = GameScene + * DateTime = Thu Dec 02 2021 18:43:36 GMT+0800 (中国标准时间) + * Author = k8w + * FileBasename = GameScene.ts + * FileBasenameNoExtension = GameScene + * URL = db://assets/scenes/GameScene/GameScene.ts + * ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/ + * + */ + +@ccclass('GameScene') +export class GameScene extends Component { + + @property(Joystick) + joyStick!: Joystick; + + @property(Prefab) + prefabPlayer!: Prefab; + + @property(Node) + players!: Node; + + @property(FollowCamera) + camera: FollowCamera = null as any; + + client!: WsClient; + gameManager!: GameManager; + + private _playerInstances: { [playerId: number]: Player } = {}; + private _selfSpeed?: Vec2 = new Vec2(0, 0); + + onLoad() { + (window as any).game = this; + + this.joyStick.options = { + onOperate: v => { + if (!this._selfSpeed) { + this._selfSpeed = new Vec2; + } + this._selfSpeed.set(v.x, v.y); + }, + onOperateEnd: () => { + this._selfSpeed = undefined; + } + } + + this.client = new WsClient(serviceProto, { + server: 'ws://127.0.0.1:3000', + logger: console + }); + this.client.flows.postDisconnectFlow.push(v => { + location.reload() + return v; + }) + this.gameManager = new GameManager(this.client); + + this.gameManager.join(); + } + + update(dt: number) { + // Send Inputs + if (this._selfSpeed && this._selfSpeed.lengthSqr()) { + this._selfSpeed.normalize().multiplyScalar(gameConfig.moveSpeed); + this.gameManager.sendClientInput({ + type: 'PlayerMove', + speed: { + x: this._selfSpeed.x, + y: this._selfSpeed.y + }, + dt: dt + }) + } + + let gameState = this.gameManager.state; + + // console.log('update', gameState.players.length) + + // Update pos + for (let playerState of gameState.players) { + let player: Player = this._playerInstances[playerState.id]; + if (!player) { + let node = instantiate(this.prefabPlayer); + this.players.addChild(node); + player = node.getComponent(Player)!; + player.init(playerState); + + if (playerState.id === this.gameManager.selfPlayerId) { + this.camera.focusTarget = node; + } + + this._playerInstances[playerState.id] = player; + } + else { + // console.log('setPos', playerState.id, playerState.pos.x, playerState.pos.y) + player.setPos(playerState.pos); + } + } + + // Clear left players + } + +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.ts.meta b/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.ts.meta new file mode 100644 index 0000000..bbe001a --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scenes/GameScene/GameScene.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.22", + "importer": "typescript", + "imported": true, + "uuid": "d472870e-cf19-4a1c-b32e-e57838f14f14", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/Room.ts b/examples/cocos-creator-multiplayer/frontend/assets/scripts/Room.ts deleted file mode 100644 index b111b9c..0000000 --- a/examples/cocos-creator-multiplayer/frontend/assets/scripts/Room.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { WsClient } from 'tsrpc-browser'; -import { MsgInput } from './shared/protocols/clientMsgs/MsgInput'; -import { MsgFrame } from './shared/protocols/serverMsgs/MsgFrame'; -import { ServiceType } from "./shared/protocols/serviceProto"; -import { applyPlayerInput, PlayerInput, PlayerState } from "./shared/states/Player"; -import { RoomState } from './shared/states/RoomState'; - -/** - * 客户端 - 房间 - 逻辑系统 - */ -export class Room { - - state: RoomState = { - players: [] - } - - client: WsClient; - - self?: { - uid: number, - // 最后一次权威状态 - lastServerState: PlayerState - } - private _lastSendInputSN = 0; - private _sendingMsgs: MsgInput[] = []; - - constructor(client: WsClient) { - this.client = client; - this.client.listenMsg('serverMsgs/Frame', msg => { - this.applyServerFrame(msg); - }); - this.client.listenMsg('serverMsgs/Join', msg => { - this.state.players.push(msg.player); - }); - this.client.listenMsg('serverMsgs/Leave', msg => { - this.state.players.removeOne(v => v.uid === msg.uid); - }); - } - - init(roomState: RoomState) { - - } - - /** 同步服务端的权威消息 */ - applyServerFrame(msg: MsgFrame) { - msg.inputs.forEach(({ uid, msgInput }) => { - let playerIndex = this.state.players.findIndex(v => v.uid === uid); - if (playerIndex === -1) { - return; - } - let newPlayer: PlayerState = this.state.players[playerIndex]; - - // 自己:和解 - if (uid === this.self?.uid) { - this._sendingMsgs.remove(v => v.sn <= msgInput.sn); - this.state.players[playerIndex] = this.self.lastServerState; - // 预测 - this._sendingMsgs.forEach(v => { - this.state.players[playerIndex] = applyPlayerInput(this.state.players[playerIndex], v); - }) - } - // 其它人:直接同步 - else { - this.state.players[playerIndex] = applyPlayerInput(this.state.players[playerIndex], msgInput); - } - }); - } - - /** 发送客户端输入,并执行本地预测 */ - sendInput(input: PlayerInput) { - if (!this.self) { - return; - } - - let msg: MsgInput = { - ...input, - sn: ++this._lastSendInputSN - } - this._sendingMsgs.push(msg); - this.client.sendMsg('clientMsgs/Input', msg); - } - - async joinRoom() { - let ret = await this.client.callApi('JoinRoom', { - nickname: 'xxx', - skinId: 1 - }); - - if (!ret.isSucc) { - alert(ret.err.message); - return; - } - - this.self = { - uid: ret.res.uid, - lastServerState: ret.res.roomState.players.find(v => v.uid === ret.res!.uid)! - } - this.state = ret.res.roomState; - } - -} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/components.meta b/examples/cocos-creator-multiplayer/frontend/assets/scripts/components.meta new file mode 100644 index 0000000..1db4d3a --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/components.meta @@ -0,0 +1,12 @@ +{ + "ver": "1.1.0", + "importer": "directory", + "imported": true, + "uuid": "bb0fd50f-b641-4824-a798-1f06417e3e88", + "files": [], + "subMetas": {}, + "userData": { + "compressionType": {}, + "isRemoteBundle": {} + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/components/FollowCamera.ts b/examples/cocos-creator-multiplayer/frontend/assets/scripts/components/FollowCamera.ts new file mode 100644 index 0000000..3a0450c --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/components/FollowCamera.ts @@ -0,0 +1,94 @@ +import { _decorator, Component, Node, Vec3, Quat, Tween, tween } from "cc"; +import { MathUtil } from '../models/MathUtil'; +const { ccclass, property } = _decorator; + +const v3_1 = new Vec3; + +/** + * 跟随摄像机 + */ +@ccclass +export class FollowCamera extends Component { + + @property(Node) + focusTarget: Node = null as any; + + @property + speedFactor: number = 0.05; + + @property + private _distance: number = 15.0; + @property + public get distance(): number { + return this._distance; + } + public set distance(v: number) { + this._distance = v; + this._updateTargetWorldPos(); + } + + // Limit range + enableLimit: boolean = true; + minX = -Infinity; + maxX = Infinity; + minZ = -Infinity; + maxZ = Infinity; + + protected _tweenFollow?: Tween; + protected _targetWorldPos = new Vec3; + protected _lastTargetPos = new Vec3; + + start() { + this._lastTargetPos.set(this.focusTarget.worldPosition); + this._updateTargetWorldPos(); + this.node.setWorldPosition(this._targetWorldPos); + } + + protected _updateTargetWorldPos() { + this._targetWorldPos.set(this.focusTarget.worldPosition); + if (this.enableLimit) { + this._targetWorldPos.x = MathUtil.limit(this._targetWorldPos.x, this.minX, this.maxX); + this._targetWorldPos.z = MathUtil.limit(this._targetWorldPos.z, this.minZ, this.maxZ); + } + + this._targetWorldPos.add(this.node.forward.multiplyScalar(this.distance * -1)); + } + + update() { + if (!this._lastTargetPos.equals(this.focusTarget.worldPosition)) { + this._lastTargetPos.set(this.focusTarget.worldPosition); + this._updateTargetWorldPos(); + } + + // 向TargetWorldPos平滑逼近 + // Limit Range + v3_1.set(this._targetWorldPos); + let diff = v3_1.subtract(this.node.worldPosition); + if (diff.lengthSqr() > 0.01) { + this.node.worldPosition.add(diff.multiplyScalar(this.speedFactor)); + this.node.setWorldPosition(this.node.worldPosition); + } + } + + resetPos() { + this._updateTargetWorldPos(); + this.node.setWorldPosition(this._targetWorldPos); + } + + @property + get preview() { + return false; + } + set preview(v: boolean) { + this.resetPos(); + } + + @property + get autoSetDistance() { + return false; + } + set autuSetDistance(v: boolean) { + this.distance = this.node.worldPosition.clone().subtract(this.focusTarget.worldPosition).length(); + } + +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/components/FollowCamera.ts.meta b/examples/cocos-creator-multiplayer/frontend/assets/scripts/components/FollowCamera.ts.meta new file mode 100644 index 0000000..124f557 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/components/FollowCamera.ts.meta @@ -0,0 +1,13 @@ +{ + "ver": "4.0.22", + "importer": "typescript", + "imported": true, + "uuid": "db75b6cd-267c-4760-8771-a3adc24919ef", + "files": [], + "subMetas": {}, + "userData": { + "importAsPlugin": false, + "moduleId": "project:///assets/scripts/components/FollowCamera.js", + "simulateGlobals": [] + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/models.meta b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models.meta new file mode 100644 index 0000000..5ecdf64 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models.meta @@ -0,0 +1,12 @@ +{ + "ver": "1.1.0", + "importer": "directory", + "imported": true, + "uuid": "7d1b93ce-3f28-40b7-9ad5-52f9fd2cae80", + "files": [], + "subMetas": {}, + "userData": { + "compressionType": {}, + "isRemoteBundle": {} + } +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/GameManager.ts b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/GameManager.ts new file mode 100644 index 0000000..478cd39 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/GameManager.ts @@ -0,0 +1,97 @@ +import { WsClient } from "tsrpc-browser"; +import { GameSystem, GameSystemState } from "../shared/game/GameSystem"; +import { ClientInput, MsgClientInput } from "../shared/protocols/client/MsgClientInput"; +import { MsgFrame } from "../shared/protocols/server/MsgFrame"; +import { ServiceType } from "../shared/protocols/serviceProto"; + +export class GameManager { + + client: WsClient; + + gameSystem = new GameSystem(); + lastServerState: GameSystemState = this.gameSystem.state; + selfPlayerId: number = -1; + lastSN = 0; + + get state() { + return this.gameSystem.state; + } + + constructor(client: WsClient) { + this.client = client; + client.listenMsg('server/Frame', msg => { this._onServerSync(msg) }); + + (window as any).gm = this; + } + + async join(): Promise { + if (!this.client.isConnected) { + let resConnect = await this.client.connect(); + if (!resConnect.isSucc) { + if (confirm('连接到服务器失败,是否重试')) { + return this.join(); + } + else { + return; + } + } + } + + let ret = await this.client.callApi('Join', {}); + + if (!ret.isSucc) { + if (confirm(`加入房间失败\n${ret.err.message}\n是否重试 ?`)) { + return this.join(); + } + else { + return; + } + } + + this.gameSystem.reset(ret.res.gameState); + this.lastServerState = Object.merge(ret.res.gameState); + this.selfPlayerId = ret.res.playerId; + } + + private _onServerSync(frame: MsgFrame) { + // 同步权威状态 + this.gameSystem.reset(this.lastServerState); + for (let input of frame.inputs) { + this.gameSystem.applyInput(input); + } + this.lastServerState = Object.merge({}, this.gameSystem.state); + + // 和解 + let lastSn = frame.lastSn ?? -1; + this.pendingInputMsgs.remove(v => v.sn <= lastSn); + this.pendingInputMsgs.forEach(m => { + m.inputs.forEach(v => { + this.gameSystem.applyInput({ + ...v, + playerId: this.selfPlayerId + }); + }) + }) + } + + pendingInputMsgs: MsgClientInput[] = []; + sendClientInput(input: ClientInput) { + if (!this.selfPlayerId) { + return; + } + + let msg: MsgClientInput = { + sn: ++this.lastSN, + inputs: [input] + } + this.pendingInputMsgs.push(msg); + this.client.sendMsg('client/ClientInput', msg); + + // 预测 + this.gameSystem.applyInput({ + ...input, + playerId: this.selfPlayerId + }); + } + +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/GameManager.ts.meta b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/GameManager.ts.meta new file mode 100644 index 0000000..2c59981 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/GameManager.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.22", + "importer": "typescript", + "imported": true, + "uuid": "977377fa-caaf-4e5e-8dac-0b429df3bdf6", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/MathUtil.ts b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/MathUtil.ts new file mode 100644 index 0000000..4a81233 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/MathUtil.ts @@ -0,0 +1,7 @@ +export class MathUtil { + + static limit(src: number, min: number, max: number) { + return Math.min(max, Math.max(min, src)); + } + +} \ No newline at end of file diff --git a/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/MathUtil.ts.meta b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/MathUtil.ts.meta new file mode 100644 index 0000000..63762e2 --- /dev/null +++ b/examples/cocos-creator-multiplayer/frontend/assets/scripts/models/MathUtil.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.22", + "importer": "typescript", + "imported": true, + "uuid": "6fde67c5-0d09-4389-8c51-9b57bce87ee1", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/examples/cocos-creator-multiplayer/frontend/settings/v2/packages/project.json b/examples/cocos-creator-multiplayer/frontend/settings/v2/packages/project.json index 429e70c..e3be56d 100644 --- a/examples/cocos-creator-multiplayer/frontend/settings/v2/packages/project.json +++ b/examples/cocos-creator-multiplayer/frontend/settings/v2/packages/project.json @@ -5,5 +5,11 @@ "name": "canvas_19", "value": 524288 } - ] + ], + "general": { + "designResolution": { + "width": 750, + "height": 1334 + } + } } diff --git a/examples/cocos-creator-multiplayer/frontend/tsconfig.json b/examples/cocos-creator-multiplayer/frontend/tsconfig.json index d7049f6..8f1ede0 100644 --- a/examples/cocos-creator-multiplayer/frontend/tsconfig.json +++ b/examples/cocos-creator-multiplayer/frontend/tsconfig.json @@ -2,5 +2,7 @@ /* Base configuration. Do not edit this field. */ "extends": "./temp/tsconfig.cocos.json", /* Add your custom configuration here. */ - "compilerOptions": {} + "compilerOptions": { + "skipLibCheck": true + } } \ No newline at end of file