可通过 URL 自定义 lag

This commit is contained in:
k8w 2021-12-03 14:19:09 +08:00
parent 5c588ea56e
commit 171c0264a2
6 changed files with 55 additions and 64 deletions

View File

@ -2,7 +2,6 @@ import 'k8w-extend-native';
import * as path from "path";
import { WsConnection, WsServer } from "tsrpc";
import { Room } from './models/Room';
import { gameConfig } from './shared/game/gameConfig';
import { serviceProto, ServiceType } from './shared/protocols/serviceProto';
// Create the Server
@ -19,19 +18,7 @@ server.flows.postDisconnectFlow.push(v => {
}
return v;
})
// 模拟网络延迟
if (gameConfig.networkLag) {
server.flows.preRecvDataFlow.push(async v => {
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
return v;
})
server.flows.preSendDataFlow.push(async v => {
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
return v;
})
}
});
export const roomInstance = new Room(server);

View File

@ -43,12 +43,14 @@ export class GameSystem {
else if (input.type === 'PlayerAttack') {
let player = this._state.players.find(v => v.id === input.playerId);
if (player) {
this._state.arrows.push({
let newArrow: ArrowState = {
id: this._state.nextArrowId++,
fromPlayerId: input.playerId,
targetPos: { ...input.targetPos },
targetTime: input.targetTime
});
};
this._state.arrows.push(newArrow);
this.onNewArrow.forEach(v => v(newArrow));
}
}
else if (input.type === 'PlayerJoin') {
@ -69,11 +71,6 @@ export class GameSystem {
if (arrow.targetTime <= this._state.now) {
// 伤害判定
let damagedPlayers = this._state.players.filter(v => {
// 不能伤害自己
// if (v.id === arrow.fromPlayerId) {
// return false;
// }
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.arrowAttackRadius * gameConfig.arrowAttackRadius
});
damagedPlayers.forEach(p => {
@ -81,11 +78,8 @@ export class GameSystem {
p.dizzyEndTime = this._state.now + gameConfig.arrowDizzyTime;
// Event
this.onDamage.forEach(h => h({
fromPlayerId: arrow.fromPlayerId,
toPlayerId: p.id
}))
})
this._state.arrows.splice(i, 1);
}
}
@ -93,7 +87,7 @@ export class GameSystem {
}
// Events (Game Push)
onDamage: ((e: { fromPlayerId: number, toPlayerId: number }) => void)[] = [];
onNewArrow: ((arrow: ArrowState) => void)[] = [];
}

View File

@ -1,7 +1,5 @@
export const gameConfig = {
syncRate: 10,
// 网络延迟(同时在服务端和客户端生效,所以实际是双倍延迟)
networkLag: 200,
// 攻击技能的冷却时间(毫秒)
attackCD: 1000,

View File

@ -1,6 +1,7 @@
import { Component, Vec3, _decorator } from 'cc';
import { MathUtil } from '../../scripts/models/MathUtil';
import { gameConfig } from '../../scripts/shared/game/gameConfig';
import { ArrowState } from '../../scripts/shared/game/state/ArrowState';
const { ccclass, property } = _decorator;
@ -27,7 +28,8 @@ export class Arrow extends Component {
this._startPos.set(startPos);
this._endPos.set(state.targetPos.x, 0, -state.targetPos.y);
this._startTime = Date.now();
this._endTime = this._startTime + state.targetTime - now;
// 箭的展示与判定相分离,展示就按固定的飞行时长展示
this._endTime = this._startTime + gameConfig.arrowFlyTime;
this._updatePosAndForward(0);
}
@ -36,6 +38,10 @@ export class Arrow extends Component {
//下一个目标位置
let percent = MathUtil.limit((Date.now() - this._startTime) / (this._endTime - this._startTime), 0, 1);
this._updatePosAndForward(percent);
if (percent >= 1) {
this.node.removeFromParent();
}
}
private _updatePosAndForward(percent: number) {

View File

@ -6,6 +6,7 @@ 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 { ArrowState } from '../../scripts/shared/game/state/ArrowState';
const { ccclass, property } = _decorator;
/**
@ -41,8 +42,8 @@ export class GameScene extends Component {
gameManager!: GameManager;
private _playerInstances: { [playerId: number]: Player } = {};
private _arrowInstances: { [arrowId: number]: Arrow } = {};
private _playerInstances: { [playerId: number]: Player | undefined } = {};
private _arrowInstances: { [arrowId: number]: Arrow | undefined } = {};
private _selfSpeed?: Vec2 = new Vec2(0, 0);
onLoad() {
@ -61,10 +62,18 @@ export class GameScene extends Component {
}
this.gameManager = new GameManager();
// 监听数据状态事件
this.gameManager.gameSystem.onNewArrow.push(v => { this._onNewArrow(v) });
// 断线一秒后重连
this.gameManager.client.flows.postDisconnectFlow.push(v => {
location.reload()
setTimeout(() => {
this.gameManager.join();
}, 2000)
return v;
});
this.gameManager.join();
}
@ -85,14 +94,13 @@ export class GameScene extends Component {
}
this._updatePlayers();
this._updateArrows();
}
private _updatePlayers() {
// Update pos
let playerStates = this.gameManager.state.players;
for (let playerState of playerStates) {
let player: Player = this._playerInstances[playerState.id];
let player = this._playerInstances[playerState.id];
if (!player) {
let node = instantiate(this.prefabPlayer);
this.players.addChild(node);
@ -119,33 +127,27 @@ export class GameScene extends Component {
}
}
private _updateArrows() {
// Update pos
let arrowStates = this.gameManager.state.arrows;
for (let arrowState of arrowStates) {
let arrow: Arrow = this._arrowInstances[arrowState.id];
if (!arrow) {
let playerState = this.gameManager.state.players.find(v => v.id === arrowState.fromPlayerId);
if (!playerState) {
continue;
}
let playerNode = this._playerInstances[playerState.id].node;
let node = instantiate(this.prefabArrow);
this.arrows.addChild(node);
arrow = this._arrowInstances[arrowState.id] = node.getComponent(Arrow)!;
arrow.init(arrowState, playerNode.position, this.gameManager.state.now);
}
private _onNewArrow(arrowState: ArrowState) {
let arrow = this._arrowInstances[arrowState.id];
// 已经存在
if (arrow) {
return;
}
// Clear left players
for (let i = this.arrows.children.length - 1; i > -1; --i) {
let arrow = this.arrows.children[i].getComponent(Arrow)!;
if (!this.gameManager.state.arrows.find(v => v.id === arrow.id)) {
arrow.node.removeFromParent();
delete this._arrowInstances[arrow.id];
}
let playerState = this.gameManager.state.players.find(v => v.id === arrowState.fromPlayerId);
if (!playerState) {
return;
}
let playerNode = this._playerInstances[playerState.id]?.node;
if (!playerNode) {
return;
}
// 创建新的箭矢显示
let node = instantiate(this.prefabArrow);
this.arrows.addChild(node);
arrow = this._arrowInstances[arrowState.id] = node.getComponent(Arrow)!;
arrow.init(arrowState, playerNode.position, this.gameManager.state.now);
}
onBtnAttack() {
@ -154,7 +156,11 @@ export class GameScene extends Component {
return;
}
let playerNode = this._playerInstances[this.gameManager.selfPlayerId].node;
let playerNode = this._playerInstances[this.gameManager.selfPlayerId]?.node;
if (!playerNode) {
return;
}
// 攻击落点偏移(表现层坐标)
let sceneOffset = playerNode.forward.clone().normalize().multiplyScalar(gameConfig.arrowDistance);
// 攻击落点(逻辑层坐标)

View File

@ -1,5 +1,4 @@
import { WsClient } from "tsrpc-browser";
import { gameConfig } from "../shared/game/gameConfig";
import { GameSystem, GameSystemState } from "../shared/game/GameSystem";
import { ClientInput, MsgClientInput } from "../shared/protocols/client/MsgClientInput";
import { MsgFrame } from "../shared/protocols/server/MsgFrame";
@ -27,14 +26,15 @@ export class GameManager {
});;
client.listenMsg('server/Frame', msg => { this._onServerSync(msg) });
// 模拟网络延迟
if (gameConfig.networkLag) {
// 模拟网络延迟 可通过 URL 参数 ?lag=200 设置延迟
let networkLag = parseInt(new URLSearchParams(location.search).get('lag') || '0') || 0;
if (networkLag) {
client.flows.preRecvDataFlow.push(async v => {
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
await new Promise(rs => { setTimeout(rs, networkLag) })
return v;
});
client.flows.preSendDataFlow.push(async v => {
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
await new Promise(rs => { setTimeout(rs, networkLag) })
return v;
});
}