可通过 URL 自定义 lag
This commit is contained in:
parent
5c588ea56e
commit
171c0264a2
@ -2,7 +2,6 @@ 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
|
||||||
@ -19,19 +18,7 @@ server.flows.postDisconnectFlow.push(v => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 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);
|
export const roomInstance = new Room(server);
|
||||||
|
|
||||||
|
@ -43,12 +43,14 @@ export class GameSystem {
|
|||||||
else if (input.type === 'PlayerAttack') {
|
else if (input.type === 'PlayerAttack') {
|
||||||
let player = this._state.players.find(v => v.id === input.playerId);
|
let player = this._state.players.find(v => v.id === input.playerId);
|
||||||
if (player) {
|
if (player) {
|
||||||
this._state.arrows.push({
|
let newArrow: ArrowState = {
|
||||||
id: this._state.nextArrowId++,
|
id: this._state.nextArrowId++,
|
||||||
fromPlayerId: input.playerId,
|
fromPlayerId: input.playerId,
|
||||||
targetPos: { ...input.targetPos },
|
targetPos: { ...input.targetPos },
|
||||||
targetTime: input.targetTime
|
targetTime: input.targetTime
|
||||||
});
|
};
|
||||||
|
this._state.arrows.push(newArrow);
|
||||||
|
this.onNewArrow.forEach(v => v(newArrow));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (input.type === 'PlayerJoin') {
|
else if (input.type === 'PlayerJoin') {
|
||||||
@ -69,11 +71,6 @@ export class GameSystem {
|
|||||||
if (arrow.targetTime <= this._state.now) {
|
if (arrow.targetTime <= this._state.now) {
|
||||||
// 伤害判定
|
// 伤害判定
|
||||||
let damagedPlayers = this._state.players.filter(v => {
|
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
|
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 => {
|
damagedPlayers.forEach(p => {
|
||||||
@ -81,11 +78,8 @@ export class GameSystem {
|
|||||||
p.dizzyEndTime = this._state.now + gameConfig.arrowDizzyTime;
|
p.dizzyEndTime = this._state.now + gameConfig.arrowDizzyTime;
|
||||||
|
|
||||||
// Event
|
// Event
|
||||||
this.onDamage.forEach(h => h({
|
|
||||||
fromPlayerId: arrow.fromPlayerId,
|
|
||||||
toPlayerId: p.id
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this._state.arrows.splice(i, 1);
|
this._state.arrows.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +87,7 @@ export class GameSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Events (Game Push)
|
// Events (Game Push)
|
||||||
onDamage: ((e: { fromPlayerId: number, toPlayerId: number }) => void)[] = [];
|
onNewArrow: ((arrow: ArrowState) => void)[] = [];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
export const gameConfig = {
|
export const gameConfig = {
|
||||||
syncRate: 10,
|
syncRate: 10,
|
||||||
// 网络延迟(同时在服务端和客户端生效,所以实际是双倍延迟)
|
|
||||||
networkLag: 200,
|
|
||||||
|
|
||||||
// 攻击技能的冷却时间(毫秒)
|
// 攻击技能的冷却时间(毫秒)
|
||||||
attackCD: 1000,
|
attackCD: 1000,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import { Component, Vec3, _decorator } from 'cc';
|
import { Component, Vec3, _decorator } from 'cc';
|
||||||
import { MathUtil } from '../../scripts/models/MathUtil';
|
import { MathUtil } from '../../scripts/models/MathUtil';
|
||||||
|
import { gameConfig } from '../../scripts/shared/game/gameConfig';
|
||||||
import { ArrowState } from '../../scripts/shared/game/state/ArrowState';
|
import { ArrowState } from '../../scripts/shared/game/state/ArrowState';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ -27,7 +28,8 @@ export class Arrow extends Component {
|
|||||||
this._startPos.set(startPos);
|
this._startPos.set(startPos);
|
||||||
this._endPos.set(state.targetPos.x, 0, -state.targetPos.y);
|
this._endPos.set(state.targetPos.x, 0, -state.targetPos.y);
|
||||||
this._startTime = Date.now();
|
this._startTime = Date.now();
|
||||||
this._endTime = this._startTime + state.targetTime - now;
|
// 箭的展示与判定相分离,展示就按固定的飞行时长展示
|
||||||
|
this._endTime = this._startTime + gameConfig.arrowFlyTime;
|
||||||
|
|
||||||
this._updatePosAndForward(0);
|
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);
|
let percent = MathUtil.limit((Date.now() - this._startTime) / (this._endTime - this._startTime), 0, 1);
|
||||||
this._updatePosAndForward(percent);
|
this._updatePosAndForward(percent);
|
||||||
|
|
||||||
|
if (percent >= 1) {
|
||||||
|
this.node.removeFromParent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updatePosAndForward(percent: number) {
|
private _updatePosAndForward(percent: number) {
|
||||||
|
@ -6,6 +6,7 @@ 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 { ArrowState } from '../../scripts/shared/game/state/ArrowState';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,8 +42,8 @@ export class GameScene extends Component {
|
|||||||
|
|
||||||
gameManager!: GameManager;
|
gameManager!: GameManager;
|
||||||
|
|
||||||
private _playerInstances: { [playerId: number]: Player } = {};
|
private _playerInstances: { [playerId: number]: Player | undefined } = {};
|
||||||
private _arrowInstances: { [arrowId: number]: Arrow } = {};
|
private _arrowInstances: { [arrowId: number]: Arrow | undefined } = {};
|
||||||
private _selfSpeed?: Vec2 = new Vec2(0, 0);
|
private _selfSpeed?: Vec2 = new Vec2(0, 0);
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@ -61,10 +62,18 @@ export class GameScene extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.gameManager = new GameManager();
|
this.gameManager = new GameManager();
|
||||||
|
|
||||||
|
// 监听数据状态事件
|
||||||
|
this.gameManager.gameSystem.onNewArrow.push(v => { this._onNewArrow(v) });
|
||||||
|
|
||||||
|
// 断线一秒后重连
|
||||||
this.gameManager.client.flows.postDisconnectFlow.push(v => {
|
this.gameManager.client.flows.postDisconnectFlow.push(v => {
|
||||||
location.reload()
|
setTimeout(() => {
|
||||||
|
this.gameManager.join();
|
||||||
|
}, 2000)
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.gameManager.join();
|
this.gameManager.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,14 +94,13 @@ export class GameScene extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._updatePlayers();
|
this._updatePlayers();
|
||||||
this._updateArrows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updatePlayers() {
|
private _updatePlayers() {
|
||||||
// Update pos
|
// Update pos
|
||||||
let playerStates = this.gameManager.state.players;
|
let playerStates = this.gameManager.state.players;
|
||||||
for (let playerState of playerStates) {
|
for (let playerState of playerStates) {
|
||||||
let player: Player = this._playerInstances[playerState.id];
|
let 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);
|
||||||
@ -119,33 +127,27 @@ export class GameScene extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateArrows() {
|
private _onNewArrow(arrowState: ArrowState) {
|
||||||
// Update pos
|
let arrow = this._arrowInstances[arrowState.id];
|
||||||
let arrowStates = this.gameManager.state.arrows;
|
// 已经存在
|
||||||
for (let arrowState of arrowStates) {
|
if (arrow) {
|
||||||
let arrow: Arrow = this._arrowInstances[arrowState.id];
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear left players
|
let playerState = this.gameManager.state.players.find(v => v.id === arrowState.fromPlayerId);
|
||||||
for (let i = this.arrows.children.length - 1; i > -1; --i) {
|
if (!playerState) {
|
||||||
let arrow = this.arrows.children[i].getComponent(Arrow)!;
|
return;
|
||||||
if (!this.gameManager.state.arrows.find(v => v.id === arrow.id)) {
|
|
||||||
arrow.node.removeFromParent();
|
|
||||||
delete this._arrowInstances[arrow.id];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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() {
|
onBtnAttack() {
|
||||||
@ -154,7 +156,11 @@ export class GameScene extends Component {
|
|||||||
return;
|
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);
|
let sceneOffset = playerNode.forward.clone().normalize().multiplyScalar(gameConfig.arrowDistance);
|
||||||
// 攻击落点(逻辑层坐标)
|
// 攻击落点(逻辑层坐标)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
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";
|
||||||
@ -27,14 +26,15 @@ export class GameManager {
|
|||||||
});;
|
});;
|
||||||
client.listenMsg('server/Frame', msg => { this._onServerSync(msg) });
|
client.listenMsg('server/Frame', msg => { this._onServerSync(msg) });
|
||||||
|
|
||||||
// 模拟网络延迟
|
// 模拟网络延迟 可通过 URL 参数 ?lag=200 设置延迟
|
||||||
if (gameConfig.networkLag) {
|
let networkLag = parseInt(new URLSearchParams(location.search).get('lag') || '0') || 0;
|
||||||
|
if (networkLag) {
|
||||||
client.flows.preRecvDataFlow.push(async v => {
|
client.flows.preRecvDataFlow.push(async v => {
|
||||||
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
|
await new Promise(rs => { setTimeout(rs, networkLag) })
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
client.flows.preSendDataFlow.push(async v => {
|
client.flows.preSendDataFlow.push(async v => {
|
||||||
await new Promise(rs => { setTimeout(rs, gameConfig.networkLag) })
|
await new Promise(rs => { setTimeout(rs, networkLag) })
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user