Trying to improve latency placing bombs while running
This commit is contained in:
parent
21f9807482
commit
e9306a2502
98
src/game.js
98
src/game.js
@ -127,6 +127,7 @@ const network = {
|
|||||||
inputStateAtClient: {
|
inputStateAtClient: {
|
||||||
dir: null,
|
dir: null,
|
||||||
bomb: false,
|
bomb: false,
|
||||||
|
bombCell: null,
|
||||||
},
|
},
|
||||||
lastInputSentAt: 0,
|
lastInputSentAt: 0,
|
||||||
activeRoster: [],
|
activeRoster: [],
|
||||||
@ -712,7 +713,7 @@ function handleSocketMessage(raw) {
|
|||||||
if (!network.isHost || state.mode !== "multiplayer" || state.screen !== "game") {
|
if (!network.isHost || state.mode !== "multiplayer" || state.screen !== "game") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
network.remoteInputs.set(msg.playerId, msg.input || { dir: null, bomb: false });
|
network.remoteInputs.set(msg.playerId, msg.input || { dir: null, bomb: false, bombCell: null });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,7 +780,7 @@ function leaveLobbyInternals() {
|
|||||||
network.activeRoster = [];
|
network.activeRoster = [];
|
||||||
state.notification.text = "";
|
state.notification.text = "";
|
||||||
state.notification.expiresAt = 0;
|
state.notification.expiresAt = 0;
|
||||||
network.inputStateAtClient = { dir: null, bomb: false };
|
network.inputStateAtClient = { dir: null, bomb: false, bombCell: null };
|
||||||
network.lastInputSentAt = 0;
|
network.lastInputSentAt = 0;
|
||||||
network.hasReceivedSnapshot = false;
|
network.hasReceivedSnapshot = false;
|
||||||
}
|
}
|
||||||
@ -975,22 +976,94 @@ function updateLobbyNetwork(dt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sameBombCell(a, b) {
|
||||||
|
if (!a && !b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!a || !b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return a.x === b.x && a.y === b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveBombDropCell(player, preferredCell = null) {
|
||||||
|
const candidates = [];
|
||||||
|
if (player.moveProgress < 1) {
|
||||||
|
candidates.push({ x: player.moveFromX, y: player.moveFromY });
|
||||||
|
if (player.moveToX !== player.moveFromX || player.moveToY !== player.moveFromY) {
|
||||||
|
candidates.push({ x: player.moveToX, y: player.moveToY });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
candidates.push({ x: player.x, y: player.y });
|
||||||
|
}
|
||||||
|
|
||||||
|
const canPlaceAt = (x, y) => {
|
||||||
|
if (!inBounds(x, y)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const tile = state.map[y]?.[x];
|
||||||
|
if (!tile || tile.type !== "floor") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !getBombAt(x, y);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isCandidateCell = (cell) =>
|
||||||
|
candidates.some((candidate) => candidate.x === cell.x && candidate.y === cell.y);
|
||||||
|
|
||||||
|
if (preferredCell && Number.isInteger(preferredCell.x) && Number.isInteger(preferredCell.y)) {
|
||||||
|
if (isCandidateCell(preferredCell) && canPlaceAt(preferredCell.x, preferredCell.y)) {
|
||||||
|
return { x: preferredCell.x, y: preferredCell.y };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const primary =
|
||||||
|
player.moveProgress < 1 && player.moveProgress >= 0.5
|
||||||
|
? { x: player.moveToX, y: player.moveToY }
|
||||||
|
: candidates[0];
|
||||||
|
|
||||||
|
if (primary && canPlaceAt(primary.x, primary.y)) {
|
||||||
|
return { x: primary.x, y: primary.y };
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const candidate of candidates) {
|
||||||
|
if (canPlaceAt(candidate.x, candidate.y)) {
|
||||||
|
return { x: candidate.x, y: candidate.y };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function sendLocalMultiplayerInput(force = false) {
|
function sendLocalMultiplayerInput(force = false) {
|
||||||
if (state.mode !== "multiplayer" || state.screen !== "game" || network.isHost) {
|
if (state.mode !== "multiplayer" || state.screen !== "game" || network.isHost) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const t = now();
|
const t = now();
|
||||||
|
const localPlayer = state.players.find((player) => player.ownerId === network.clientId) || null;
|
||||||
const nextInput = {
|
const nextInput = {
|
||||||
dir: currentHumanDirection(),
|
dir: currentHumanDirection(),
|
||||||
bomb: inputState.bombHeld,
|
bomb: inputState.bombHeld,
|
||||||
|
bombCell: null,
|
||||||
};
|
};
|
||||||
|
if (nextInput.bomb && localPlayer) {
|
||||||
|
nextInput.bombCell = resolveBombDropCell(localPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
const changed =
|
const changed =
|
||||||
nextInput.dir !== network.inputStateAtClient.dir || nextInput.bomb !== network.inputStateAtClient.bomb;
|
nextInput.dir !== network.inputStateAtClient.dir ||
|
||||||
|
nextInput.bomb !== network.inputStateAtClient.bomb ||
|
||||||
|
!sameBombCell(nextInput.bombCell, network.inputStateAtClient.bombCell);
|
||||||
const dueHeartbeat = t - network.lastInputSentAt > 0.12;
|
const dueHeartbeat = t - network.lastInputSentAt > 0.12;
|
||||||
if (!changed && !force && !dueHeartbeat) {
|
if (!changed && !force && !dueHeartbeat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
network.inputStateAtClient = nextInput;
|
|
||||||
|
network.inputStateAtClient = {
|
||||||
|
dir: nextInput.dir,
|
||||||
|
bomb: nextInput.bomb,
|
||||||
|
bombCell: nextInput.bombCell ? { ...nextInput.bombCell } : null,
|
||||||
|
};
|
||||||
network.lastInputSentAt = t;
|
network.lastInputSentAt = t;
|
||||||
sendSocketMessage("player_input", { input: nextInput, ts: t });
|
sendSocketMessage("player_input", { input: nextInput, ts: t });
|
||||||
}
|
}
|
||||||
@ -1032,18 +1105,20 @@ function queueDetonation(bombId) {
|
|||||||
state.pendingDetonations.push(bombId);
|
state.pendingDetonations.push(bombId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dropBomb(player) {
|
function dropBomb(player, preferredCell = null) {
|
||||||
if (!player.alive || player.bombsPlaced >= player.bombCapacity) {
|
if (!player.alive || player.bombsPlaced >= player.bombCapacity) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (getBombAt(player.x, player.y)) {
|
|
||||||
|
const dropCell = resolveBombDropCell(player, preferredCell);
|
||||||
|
if (!dropCell) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bomb = {
|
const bomb = {
|
||||||
id: state.nextBombId,
|
id: state.nextBombId,
|
||||||
x: player.x,
|
x: dropCell.x,
|
||||||
y: player.y,
|
y: dropCell.y,
|
||||||
timer: CONFIG.bombFuse,
|
timer: CONFIG.bombFuse,
|
||||||
range: player.flameRange,
|
range: player.flameRange,
|
||||||
ownerId: player.id,
|
ownerId: player.id,
|
||||||
@ -1329,7 +1404,7 @@ function occupiedTiles(player) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getNetworkInput(ownerId) {
|
function getNetworkInput(ownerId) {
|
||||||
return network.remoteInputs.get(ownerId) || { dir: null, bomb: false };
|
return network.remoteInputs.get(ownerId) || { dir: null, bomb: false, bombCell: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDesiredDirection(player) {
|
function getDesiredDirection(player) {
|
||||||
@ -1371,8 +1446,9 @@ function updatePlayerMovement(player, dt) {
|
|||||||
player.renderY = player.y;
|
player.renderY = player.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const occupied = new Set(occupiedTiles(player));
|
||||||
for (const bomb of state.bombs) {
|
for (const bomb of state.bombs) {
|
||||||
if (bomb.passThrough.has(player.id) && (player.x !== bomb.x || player.y !== bomb.y)) {
|
if (bomb.passThrough.has(player.id) && !occupied.has(tileKey(bomb.x, bomb.y))) {
|
||||||
bomb.passThrough.delete(player.id);
|
bomb.passThrough.delete(player.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1585,7 +1661,7 @@ function updateGame(dt) {
|
|||||||
const remote = getNetworkInput(player.ownerId);
|
const remote = getNetworkInput(player.ownerId);
|
||||||
const prevBomb = network.remoteBombPrev.get(player.ownerId) || false;
|
const prevBomb = network.remoteBombPrev.get(player.ownerId) || false;
|
||||||
if (remote.bomb && !prevBomb) {
|
if (remote.bomb && !prevBomb) {
|
||||||
dropBomb(player);
|
dropBomb(player, remote.bombCell || null);
|
||||||
}
|
}
|
||||||
network.remoteBombPrev.set(player.ownerId, remote.bomb);
|
network.remoteBombPrev.set(player.ownerId, remote.bomb);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user