移动实现 不同颜色皮肤实现

This commit is contained in:
k8w 2021-12-02 23:18:31 +08:00
parent 23186001db
commit 03aeff62c5
17 changed files with 289 additions and 298 deletions

View File

@ -2,13 +2,13 @@ import 'k8w-extend-native';
import * as path from "path"; import * as path from "path";
import { WsConnection, WsServer } from "tsrpc"; import { WsConnection, WsServer } from "tsrpc";
import { Room } from './models/Room'; import { Room } from './models/Room';
import { gameConfig } from './shared/game/gameConfig';
import { serviceProto, ServiceType } from './shared/protocols/serviceProto'; import { serviceProto, ServiceType } from './shared/protocols/serviceProto';
// Create the Server // Create the Server
export const server = new WsServer(serviceProto, { export const server = new WsServer(serviceProto, {
port: 3000, port: 3000,
// Remove this to use binary mode (remove from the client too) json: true
// json: true
}); });
// 断开连接后退出房间 // 断开连接后退出房间
@ -22,14 +22,16 @@ server.flows.postDisconnectFlow.push(v => {
}) })
// 模拟网络延迟 // 模拟网络延迟
server.flows.preRecvDataFlow.push(async v => { if (gameConfig.networkLag) {
await new Promise(rs => { setTimeout(rs, 300) }) server.flows.preRecvDataFlow.push(async v => {
return v; await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
}) return v;
server.flows.preSendDataFlow.push(async v => { })
await new Promise(rs => { setTimeout(rs, 300) }) server.flows.preSendDataFlow.push(async v => {
return v; await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
}) return v;
})
}
export const roomInstance = new Room(server); export const roomInstance = new Room(server);

View File

@ -1,4 +1,5 @@
import { WsConnection, WsServer } from "tsrpc"; import { WsConnection, WsServer } from "tsrpc";
import { gameConfig } from "../shared/game/gameConfig";
import { GameSystem, GameSystemInput, PlayerJoin } from "../shared/game/GameSystem"; import { GameSystem, GameSystemInput, PlayerJoin } from "../shared/game/GameSystem";
import { ReqJoin } from "../shared/protocols/PtlJoin"; import { ReqJoin } from "../shared/protocols/PtlJoin";
import { ServiceType } from "../shared/protocols/serviceProto"; import { ServiceType } from "../shared/protocols/serviceProto";
@ -9,7 +10,7 @@ import { ServiceType } from "../shared/protocols/serviceProto";
export class Room { export class Room {
// 次数/秒 // 次数/秒
syncRate = 3; syncRate = gameConfig.syncRate;
nextPlayerId = 1; nextPlayerId = 1;
gameSystem = new GameSystem(); gameSystem = new GameSystem();
@ -32,8 +33,8 @@ export class Room {
playerId: this.nextPlayerId++, playerId: this.nextPlayerId++,
// 初始位置随机 // 初始位置随机
pos: { pos: {
x: Math.random() * 10, x: Math.random() * 10 - 5,
y: Math.random() * 10 y: Math.random() * 10 - 5
} }
} }
this.applyInput(input); this.applyInput(input);

View File

@ -1,4 +1,8 @@
export const gameConfig = { export const gameConfig = {
syncRate: 10,
// 网络延迟
networkLag: 0,
// 攻击技能的冷却时间(毫秒) // 攻击技能的冷却时间(毫秒)
attackCD: 1000, attackCD: 1000,

View File

@ -1,12 +0,0 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "40e7bad4-3fa9-45c6-9d50-ce41c40e8174",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

View File

@ -1,43 +0,0 @@
{
"__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
}
]
}

View File

@ -1,11 +0,0 @@
{
"ver": "1.0.9",
"importer": "material",
"imported": true,
"uuid": "bc711895-84b3-4729-85f8-978c46347d19",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}

View File

@ -1,48 +0,0 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "1baf0fc9-befa-459c-8bdd-af1a450a0319",
"__expectedType__": "cc.EffectAsset"
},
"_techIdx": 0,
"_defines": [
{
"USE_INSTANCING": true,
"USE_ALBEDO_MAP": true
},
{},
{},
{}
],
"_states": [
{
"rasterizerState": {},
"depthStencilState": {},
"blendState": {
"targets": [
{}
]
}
},
{},
{},
{}
],
"_props": [
{
"alphaThreshold": 0,
"roughness": 0.70710676908493,
"metallic": 0.400000005960464,
"mainTexture": {
"__uuid__": "e90ad74a-b668-4e2c-bf91-51a2a91b02aa@6c48a",
"__expectedType__": "cc.Texture2D"
}
},
{},
{},
{}
]
}

View File

@ -1,11 +0,0 @@
{
"ver": "1.0.9",
"importer": "material",
"imported": true,
"uuid": "225b969b-eb6a-4489-a5a5-08efbcf38b0e",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}

View File

@ -10,7 +10,6 @@
"_techIdx": 0, "_techIdx": 0,
"_defines": [ "_defines": [
{ {
"USE_INSTANCING": true,
"USE_TEXTURE": true "USE_TEXTURE": true
} }
], ],

View File

@ -1,48 +0,0 @@
{
"__type__": "cc.Material",
"_name": "",
"_objFlags": 0,
"_native": "",
"_effectAsset": {
"__uuid__": "1baf0fc9-befa-459c-8bdd-af1a450a0319",
"__expectedType__": "cc.EffectAsset"
},
"_techIdx": 0,
"_defines": [
{
"USE_INSTANCING": true,
"USE_ALBEDO_MAP": true
},
{},
{},
{}
],
"_states": [
{
"rasterizerState": {},
"depthStencilState": {},
"blendState": {
"targets": [
{}
]
}
},
{},
{},
{}
],
"_props": [
{
"alphaThreshold": 0,
"roughness": 0.70710676908493,
"metallic": 0.400000005960464,
"mainTexture": {
"__uuid__": "f35bcb71-cd72-443c-94a9-5482c2d63d66@6c48a",
"__expectedType__": "cc.Texture2D"
}
},
{},
{},
{}
]
}

View File

@ -1,11 +0,0 @@
{
"ver": "1.0.9",
"importer": "material",
"imported": true,
"uuid": "411ae6be-9581-422b-9425-36c8e71651cb",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}

View File

@ -23,14 +23,11 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 31 "__id__": 35
},
{
"__id__": 33
} }
], ],
"_prefab": { "_prefab": {
"__id__": 35 "__id__": 36
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -62,7 +59,7 @@
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "RootNode", "_name": "soldier01",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 1 "__id__": 1
@ -70,27 +67,76 @@
"_children": [ "_children": [
{ {
"__id__": 3 "__id__": 3
}
],
"_active": true,
"_components": [
{
"__id__": 32
}
],
"_prefab": {
"__id__": 34
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 1,
"z": 0,
"w": 6.123233995736766e-17
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_layer": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 180,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "RootNode",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [
{
"__id__": 4
}, },
{ {
"__id__": 17 "__id__": 18
}, },
{ {
"__id__": 19 "__id__": 20
}, },
{ {
"__id__": 21 "__id__": 22
}, },
{ {
"__id__": 26 "__id__": 27
}, },
{ {
"__id__": 28 "__id__": 29
} }
], ],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 30 "__id__": 31
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -125,29 +171,29 @@
"_name": "Dummy01", "_name": "Dummy01",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 3
}, },
"_children": [ "_children": [
{ {
"__id__": 4 "__id__": 5
}, },
{ {
"__id__": 8 "__id__": 9
}, },
{ {
"__id__": 10 "__id__": 11
}, },
{ {
"__id__": 12 "__id__": 13
}, },
{ {
"__id__": 14 "__id__": 15
} }
], ],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 16 "__id__": 17
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -182,17 +228,17 @@
"_name": "Body", "_name": "Body",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 3 "__id__": 4
}, },
"_children": [ "_children": [
{ {
"__id__": 5 "__id__": 6
} }
], ],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 7 "__id__": 8
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -227,13 +273,13 @@
"_name": "head", "_name": "head",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 4 "__id__": 5
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 6 "__id__": 7
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -288,13 +334,13 @@
"_name": "legRight", "_name": "legRight",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 3 "__id__": 4
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 9 "__id__": 10
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -339,13 +385,13 @@
"_name": "legLeft", "_name": "legLeft",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 3 "__id__": 4
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 11 "__id__": 12
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -390,13 +436,13 @@
"_name": "handRight", "_name": "handRight",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 3 "__id__": 4
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 13 "__id__": 14
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -441,13 +487,13 @@
"_name": "handLeft", "_name": "handLeft",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 3 "__id__": 4
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 15 "__id__": 16
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -502,13 +548,13 @@
"_name": "Bip001", "_name": "Bip001",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 3
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 18 "__id__": 19
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -553,13 +599,13 @@
"_name": "mixamorig:HeadTop_End", "_name": "mixamorig:HeadTop_End",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 3
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 20 "__id__": 21
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -604,17 +650,17 @@
"_name": "soldier01", "_name": "soldier01",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 3
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 22 "__id__": 23
} }
], ],
"_prefab": { "_prefab": {
"__id__": 25 "__id__": 26
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -649,11 +695,11 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 21 "__id__": 22
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 23 "__id__": 24
}, },
"_materials": [ "_materials": [
{ {
@ -663,7 +709,7 @@
], ],
"_visFlags": 0, "_visFlags": 0,
"lightmapSettings": { "lightmapSettings": {
"__id__": 24 "__id__": 25
}, },
"_mesh": { "_mesh": {
"__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@6868c", "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@6868c",
@ -677,7 +723,7 @@
"__expectedType__": "cc.Skeleton" "__expectedType__": "cc.Skeleton"
}, },
"_skinningRoot": { "_skinningRoot": {
"__id__": 1 "__id__": 2
}, },
"_id": "" "_id": ""
}, },
@ -716,13 +762,13 @@
"_name": "Bip001(__autogen 4)", "_name": "Bip001(__autogen 4)",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 3
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 27 "__id__": 28
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -767,13 +813,13 @@
"_name": "mixamorig:HeadTop_End(__autogen 5)", "_name": "mixamorig:HeadTop_End(__autogen 5)",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 3
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 29 "__id__": 30
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -828,13 +874,13 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 1 "__id__": 2
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 32 "__id__": 33
}, },
"playOnLoad": false, "playOnLoad": true,
"_clips": [ "_clips": [
{ {
"__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@1f586", "__uuid__": "57d4c4ef-3199-4596-bf79-7c065964ca9c@1f586",
@ -869,24 +915,41 @@
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
"fileId": "71bamidCpRLIBqyoKSaXUX" "fileId": "71bamidCpRLIBqyoKSaXUX"
}, },
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "71qfN53ihYmaSuBoR11P0t"
},
{ {
"__type__": "720b7a4EnZJjYpzLWJrmvT/", "__type__": "720b7a4EnZJjYpzLWJrmvT/",
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {},
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": null,
"__id__": 34 "ani": {
"__id__": 32
},
"mesh": {
"__id__": 23
},
"texSelf": {
"__uuid__": "e90ad74a-b668-4e2c-bf91-51a2a91b02aa@6c48a",
"__expectedType__": "cc.Texture2D"
},
"texOther": {
"__uuid__": "f35bcb71-cd72-443c-94a9-5482c2d63d66@6c48a",
"__expectedType__": "cc.Texture2D"
}, },
"_id": "" "_id": ""
}, },
{
"__type__": "cc.CompPrefabInfo",
"fileId": "fczHMULW9AAIJRjvl2FJiZ"
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {
@ -895,6 +958,33 @@
"asset": { "asset": {
"__id__": 0 "__id__": 0
}, },
"fileId": "71qfN53ihYmaSuBoR11P0t" "fileId": "087WztcUlE+rBZWXq8jy1C",
"targetOverrides": [
{
"__id__": 37
}
]
},
{
"__type__": "cc.TargetOverrideInfo",
"source": {
"__id__": 35
},
"sourceInfo": null,
"propertyPath": [
"ani"
],
"target": {
"__id__": 2
},
"targetInfo": {
"__id__": 38
}
},
{
"__type__": "cc.TargetInfo",
"localID": [
"71bamidCpRLIBqyoKSaXUX"
]
} }
] ]

View File

@ -2,7 +2,7 @@
"ver": "1.1.32", "ver": "1.1.32",
"importer": "prefab", "importer": "prefab",
"imported": true, "imported": true,
"uuid": "28c95a70-5b80-4b72-8f7b-93e2cefacc98", "uuid": "809957ef-4f3f-4527-87cc-cb3223f7500a",
"files": [ "files": [
".json" ".json"
], ],

View File

@ -1,22 +1,88 @@
import { Component, _decorator } from 'cc'; import { Component, MeshRenderer, SkeletalAnimation, Texture2D, tween, Tween, Vec3, _decorator } from 'cc';
import { gameConfig } from '../../scripts/shared/game/gameConfig';
import { PlayerState } from '../../scripts/shared/game/state/PlayerState'; import { PlayerState } from '../../scripts/shared/game/state/PlayerState';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass('Player') @ccclass('Player')
export class Player extends Component { export class Player extends Component {
@property(SkeletalAnimation)
ani!: SkeletalAnimation;
@property(MeshRenderer)
mesh!: MeshRenderer;
@property(Texture2D)
texSelf!: Texture2D;
@property(Texture2D)
texOther!: Texture2D;
playerId!: number; playerId!: number;
isSelf = false; isSelf = false;
init(state: PlayerState) { private _tweens: Tween<any>[] = [];
private _targetPos = new Vec3;
init(state: PlayerState, isSelf: boolean) {
this.playerId = state.id; this.playerId = state.id;
this.setPos(state.pos); this.isSelf = isSelf;
this.mesh.material!.setProperty('mainTexture', this.isSelf ? this.texSelf : this.texOther);
} }
// 把 GameSystem 空间映射到游戏空间 // 把 GameSystem 空间映射到游戏空间
setPos(pos: { x: number, y: number }) { updateSelf(state: PlayerState) {
this.node.setPosition(pos.y, 0, pos.x); // 更新位置
this._targetPos.set(state.pos.x, 0, -state.pos.y);
if (!this.node.position.equals(this._targetPos)) {
this.setAni('run');
// 朝向
let newForward = this._targetPos.clone().subtract(this.node.position).normalize();
this.node.forward = new Vec3(newForward);
// 位置
this.node.setPosition(this._targetPos);
}
else {
this.setAni('idle');
}
}
updateOther(state: PlayerState) {
// 更新位置
let newPos = new Vec3(state.pos.x, 0, -state.pos.y);
if (!this._targetPos.equals(newPos)) {
// 清理 Tween
this._tweens?.forEach(v => v.stop());
this._tweens = [];
this.node.setPosition(this._targetPos);
// 插值朝向
let newForward = new Vec3(newPos).subtract(this.node.position).normalize();
this._tweens.push(tween({ forward: this.node.forward }).to(0.1, { forward: newForward }, {
onUpdate: (v: any) => {
this.node.forward = new Vec3(v.forward);
}
}).start())
// 新的位置
this._targetPos.set(newPos)
this.setAni('run');
this._tweens.push(tween(this.node).to(1 / gameConfig.syncRate, {
position: this._targetPos
}).call(() => {
this.setAni('idle')
}).start());
}
} }
} setAni(ani: string) {
if (this.ani.getState(ani)?.isPlaying) {
return;
}
this.ani.crossFade(ani, 0.1);
}
}
function Texture(Texture: any) {
throw new Error('Function not implemented.');
}

View File

@ -61,16 +61,16 @@
"_prefab": null, "_prefab": null,
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -35.352258452125874, "x": 0,
"y": 18.714107575144862, "y": 18.714107575144862,
"z": 5.2735593669694936e-15 "z": 35.352258452125874
}, },
"_lrot": { "_lrot": {
"__type__": "cc.Quat", "__type__": "cc.Quat",
"x": -0.17043586674820901, "x": -0.2410327142701308,
"y": -0.686259145895912, "y": 0,
"z": -0.170435866748209, "z": 0,
"w": 0.6862591458959121 "w": 0.9705169914285754
}, },
"_lscale": { "_lscale": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@ -82,7 +82,7 @@
"_euler": { "_euler": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -27.895, "x": -27.895,
"y": -90, "y": 0,
"z": 0 "z": 0
}, },
"_id": "c9DMICJLFO5IeO07EPon7U" "_id": "c9DMICJLFO5IeO07EPon7U"
@ -820,7 +820,7 @@
"__prefab": null, "__prefab": null,
"joyStick": null, "joyStick": null,
"prefabPlayer": { "prefabPlayer": {
"__uuid__": "28c95a70-5b80-4b72-8f7b-93e2cefacc98", "__uuid__": "809957ef-4f3f-4527-87cc-cb3223f7500a",
"__expectedType__": "cc.Prefab" "__expectedType__": "cc.Prefab"
}, },
"players": { "players": {

View File

@ -1,12 +1,10 @@
import { Component, instantiate, Node, Prefab, Vec2, _decorator } from 'cc'; import { Component, instantiate, Node, Prefab, Vec2, _decorator } from 'cc';
import { WsClient } from 'tsrpc-browser';
import { Joystick } from '../../prefabs/Joystick/Joystick'; import { Joystick } from '../../prefabs/Joystick/Joystick';
import { Player } from '../../prefabs/Player/Player'; import { Player } from '../../prefabs/Player/Player';
import { FollowCamera } from '../../scripts/components/FollowCamera'; import { FollowCamera } from '../../scripts/components/FollowCamera';
import { GameManager } from '../../scripts/models/GameManager'; import { GameManager } from '../../scripts/models/GameManager';
import { gameConfig } from '../../scripts/shared/game/gameConfig'; import { gameConfig } from '../../scripts/shared/game/gameConfig';
import { serviceProto, ServiceType } from '../../scripts/shared/protocols/serviceProto';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
/** /**
@ -36,8 +34,7 @@ export class GameScene extends Component {
@property(FollowCamera) @property(FollowCamera)
camera: FollowCamera = null as any; camera: FollowCamera = null as any;
client!: WsClient<ServiceType>; gameManager = new GameManager();
gameManager!: GameManager;
private _playerInstances: { [playerId: number]: Player } = {}; private _playerInstances: { [playerId: number]: Player } = {};
private _selfSpeed?: Vec2 = new Vec2(0, 0); private _selfSpeed?: Vec2 = new Vec2(0, 0);
@ -57,20 +54,16 @@ export class GameScene extends Component {
} }
} }
this.client = new WsClient(serviceProto, { this.gameManager.client.flows.postDisconnectFlow.push(v => {
server: 'ws://127.0.0.1:3000',
logger: console
});
this.client.flows.postDisconnectFlow.push(v => {
location.reload() location.reload()
return v; return v;
}) })
this.gameManager = new GameManager(this.client);
this.gameManager.join(); this.gameManager.join();
} }
update(dt: number) { update(dt: number) {
// Send Inputs // Send Inputs
if (this._selfSpeed && this._selfSpeed.lengthSqr()) { if (this._selfSpeed && this._selfSpeed.lengthSqr()) {
this._selfSpeed.normalize().multiplyScalar(gameConfig.moveSpeed); this._selfSpeed.normalize().multiplyScalar(gameConfig.moveSpeed);
@ -84,32 +77,34 @@ export class GameScene extends Component {
}) })
} }
let gameState = this.gameManager.state;
// console.log('update', gameState.players.length)
// Update pos // Update pos
for (let playerState of gameState.players) { let playerStates = this.gameManager.state.players;
for (let playerState of playerStates) {
let player: Player = this._playerInstances[playerState.id]; let player: Player = this._playerInstances[playerState.id];
if (!player) { if (!player) {
let node = instantiate(this.prefabPlayer); let node = instantiate(this.prefabPlayer);
this.players.addChild(node); this.players.addChild(node);
player = node.getComponent(Player)!; player = this._playerInstances[playerState.id] = node.getComponent(Player)!;
player.init(playerState); player.init(playerState, playerState.id === this.gameManager.selfPlayerId)
// 摄像机拍摄自己
if (playerState.id === this.gameManager.selfPlayerId) { if (playerState.id === this.gameManager.selfPlayerId) {
this.camera.focusTarget = node; this.camera.focusTarget = node;
} }
}
this._playerInstances[playerState.id] = player; // 自己不插值(本地预测),插值其它人
} player.isSelf ? player.updateSelf(playerState) : player.updateOther(playerState);
else {
// console.log('setPos', playerState.id, playerState.pos.x, playerState.pos.y)
player.setPos(playerState.pos);
}
} }
// Clear left players // Clear left players
for (let i = this.players.children.length - 1; i > -1; --i) {
let player = this.players.children[i].getComponent(Player)!;
if (!this.gameManager.state.players.find(v => v.id === player.playerId)) {
player.node.removeFromParent();
delete this._playerInstances[player.playerId];
}
}
} }
} }

View File

@ -1,8 +1,9 @@
import { WsClient } from "tsrpc-browser"; import { WsClient } from "tsrpc-browser";
import { gameConfig } from "../shared/game/gameConfig";
import { GameSystem, GameSystemState } from "../shared/game/GameSystem"; import { GameSystem, GameSystemState } from "../shared/game/GameSystem";
import { ClientInput, MsgClientInput } from "../shared/protocols/client/MsgClientInput"; import { ClientInput, MsgClientInput } from "../shared/protocols/client/MsgClientInput";
import { MsgFrame } from "../shared/protocols/server/MsgFrame"; import { MsgFrame } from "../shared/protocols/server/MsgFrame";
import { ServiceType } from "../shared/protocols/serviceProto"; import { serviceProto, ServiceType } from "../shared/protocols/serviceProto";
export class GameManager { export class GameManager {
@ -17,10 +18,27 @@ export class GameManager {
return this.gameSystem.state; return this.gameSystem.state;
} }
constructor(client: WsClient<ServiceType>) { constructor() {
this.client = client; let client = this.client = new WsClient(serviceProto, {
server: `ws://${location.hostname}:3000`,
json: true,
// logger: console
});;
client.listenMsg('server/Frame', msg => { this._onServerSync(msg) }); client.listenMsg('server/Frame', msg => { this._onServerSync(msg) });
// 模拟网络延迟
if (gameConfig.networkLag) {
client.flows.preRecvDataFlow.push(async v => {
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
return v;
});
client.flows.preSendDataFlow.push(async v => {
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
return v;
});
}
(window as any).gm = this; (window as any).gm = this;
} }