mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
Completed frontend refactoring for more convenient unit testing.
This commit is contained in:
parent
3f4e49656a
commit
15a062af10
@ -1195,7 +1195,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
// [WARNING] It's possible that by now "allConfirmedMask != delayedInputFrame.ConfirmedList && delayedInputFrameId <= pR.LastAllConfirmedInputFrameId", we trust "pR.LastAllConfirmedInputFrameId" as the TOP AUTHORITY.
|
// [WARNING] It's possible that by now "allConfirmedMask != delayedInputFrame.ConfirmedList && delayedInputFrameId <= pR.LastAllConfirmedInputFrameId", we trust "pR.LastAllConfirmedInputFrameId" as the TOP AUTHORITY.
|
||||||
atomic.StoreUint64(&(delayedInputFrame.ConfirmedList), allConfirmedMask)
|
atomic.StoreUint64(&(delayedInputFrame.ConfirmedList), allConfirmedMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
nextRenderFrame := pR.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, pR.CollisionSysMap)
|
nextRenderFrame := pR.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, pR.CollisionSysMap)
|
||||||
// Update in the latest player pointers
|
// Update in the latest player pointers
|
||||||
for playerId, playerDownsync := range nextRenderFrame.Players {
|
for playerId, playerDownsync := range nextRenderFrame.Players {
|
||||||
@ -1238,11 +1238,10 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
|
|
||||||
if nil != delayedInputFrame {
|
if nil != delayedInputFrame {
|
||||||
inputList := delayedInputFrame.InputList
|
inputList := delayedInputFrame.InputList
|
||||||
// Ordered by joinIndex to guarantee determinism?
|
effPushbacks := make([]Vec2D, pR.Capacity) // Guaranteed determinism regardless of traversal order
|
||||||
// Move players according to inputs
|
for playerId, player := range pR.Players {
|
||||||
for joinIndex := 1; joinIndex <= pR.Capacity; joinIndex++ {
|
joinIndex := player.JoinIndex
|
||||||
player := pR.PlayersArr[joinIndex-1]
|
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
|
||||||
playerId := player.Id
|
|
||||||
currPlayerDownsync := currRenderFrame.Players[playerId]
|
currPlayerDownsync := currRenderFrame.Players[playerId]
|
||||||
encodedInput := inputList[joinIndex-1]
|
encodedInput := inputList[joinIndex-1]
|
||||||
if 0 == encodedInput {
|
if 0 == encodedInput {
|
||||||
@ -1252,42 +1251,42 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
newVx := (currPlayerDownsync.VirtualGridX + (decodedInput[0] + decodedInput[0]*currPlayerDownsync.Speed))
|
newVx := (currPlayerDownsync.VirtualGridX + (decodedInput[0] + decodedInput[0]*currPlayerDownsync.Speed))
|
||||||
newVy := (currPlayerDownsync.VirtualGridY + (decodedInput[1] + decodedInput[1]*currPlayerDownsync.Speed))
|
newVy := (currPlayerDownsync.VirtualGridY + (decodedInput[1] + decodedInput[1]*currPlayerDownsync.Speed))
|
||||||
// Reset playerCollider position from the "virtual grid position"
|
// Reset playerCollider position from the "virtual grid position"
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + currPlayerDownsync.JoinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
playerCollider.X, playerCollider.Y = pR.virtualGridToPlayerColliderPos(newVx, newVy, player)
|
playerCollider.X, playerCollider.Y = pR.virtualGridToPlayerColliderPos(newVx, newVy, player)
|
||||||
|
|
||||||
|
// Update in the collision system
|
||||||
playerCollider.Update()
|
playerCollider.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle pushbacks upon collision after all movements treated as simultaneous
|
// handle pushbacks upon collision after all movements treated as simultaneous
|
||||||
for joinIndex := 1; joinIndex <= pR.Capacity; joinIndex++ {
|
for _, player := range pR.Players {
|
||||||
player := pR.PlayersArr[joinIndex-1]
|
joinIndex := player.JoinIndex
|
||||||
playerId := player.Id
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + player.JoinIndex
|
|
||||||
playerCollider := collisionSysMap[collisionPlayerIndex]
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
oldDx, oldDy := float64(0), float64(0)
|
oldDx, oldDy := float64(0), float64(0)
|
||||||
dx, dy := oldDx, oldDy
|
|
||||||
if collision := playerCollider.Check(oldDx, oldDy); collision != nil {
|
if collision := playerCollider.Check(oldDx, oldDy); collision != nil {
|
||||||
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
for _, obj := range collision.Objects {
|
for _, obj := range collision.Objects {
|
||||||
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
if overlapped, pushbackX, pushbackY := CalcPushbacks(oldDx, oldDy, playerShape, barrierShape); overlapped {
|
if overlapped, pushbackX, pushbackY := CalcPushbacks(oldDx, oldDy, playerShape, barrierShape); overlapped {
|
||||||
Logger.Debug(fmt.Sprintf("Collided & overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY))
|
Logger.Debug(fmt.Sprintf("Collided & overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY))
|
||||||
dx -= pushbackX
|
effPushbacks[joinIndex-1].X += pushbackX
|
||||||
dy -= pushbackY
|
effPushbacks[joinIndex-1].Y += pushbackY
|
||||||
} else {
|
} else {
|
||||||
Logger.Debug(fmt.Sprintf("Collided BUT not overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape)))
|
Logger.Debug(fmt.Sprintf("Collided BUT not overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
playerCollider.X += dx
|
for playerId, player := range pR.Players {
|
||||||
playerCollider.Y += dy
|
joinIndex := player.JoinIndex
|
||||||
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
// Update again in "collision space"
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
playerCollider.Update()
|
|
||||||
|
|
||||||
// Update "virtual grid position"
|
// Update "virtual grid position"
|
||||||
newVx, newVy := pR.playerColliderAnchorToVirtualGridPos(playerCollider.X, playerCollider.Y, player)
|
newVx, newVy := pR.playerColliderAnchorToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, player)
|
||||||
nextRenderFramePlayers[playerId].VirtualGridX = newVx
|
nextRenderFramePlayers[playerId].VirtualGridX = newVx
|
||||||
nextRenderFramePlayers[playerId].VirtualGridY = newVy
|
nextRenderFramePlayers[playerId].VirtualGridY = newVy
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
344.6705889248102,
|
377.5870760500153,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -324,12 +324,10 @@ cc.Class({
|
|||||||
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
|
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
|
||||||
self.recentInputCache = new RingBuffer(1024);
|
self.recentInputCache = new RingBuffer(1024);
|
||||||
|
|
||||||
self.latestCollisionSys = new collisions.Collisions();
|
self.collisionSys = new collisions.Collisions();
|
||||||
self.chaserCollisionSys = new collisions.Collisions();
|
|
||||||
|
|
||||||
self.collisionBarrierIndexPrefix = (1 << 16); // For tracking the movements of barriers, though not yet actually used
|
self.collisionBarrierIndexPrefix = (1 << 16); // For tracking the movements of barriers, though not yet actually used
|
||||||
self.latestCollisionSysMap = new Map();
|
self.collisionSysMap = new Map();
|
||||||
self.chaserCollisionSysMap = new Map();
|
|
||||||
|
|
||||||
self.transitToState(ALL_MAP_STATES.VISUAL);
|
self.transitToState(ALL_MAP_STATES.VISUAL);
|
||||||
|
|
||||||
@ -382,8 +380,7 @@ cc.Class({
|
|||||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||||
window.initPersistentSessionClient(self.initAfterWSConnected, null /* Deliberately NOT passing in any `expectedRoomId`. -- YFLu */ );
|
window.initPersistentSessionClient(self.initAfterWSConnected, null /* Deliberately NOT passing in any `expectedRoomId`. -- YFLu */ );
|
||||||
};
|
};
|
||||||
resultPanelScriptIns.onCloseDelegate = () => {
|
resultPanelScriptIns.onCloseDelegate = () => {};
|
||||||
};
|
|
||||||
|
|
||||||
self.gameRuleNode = cc.instantiate(self.gameRulePrefab);
|
self.gameRuleNode = cc.instantiate(self.gameRulePrefab);
|
||||||
self.gameRuleNode.width = self.canvasNode.width;
|
self.gameRuleNode.width = self.canvasNode.width;
|
||||||
@ -474,13 +471,11 @@ cc.Class({
|
|||||||
for (let i = 0; i < boundaryObj.length; ++i) {
|
for (let i = 0; i < boundaryObj.length; ++i) {
|
||||||
pts.push([boundaryObj[i].x - x0, boundaryObj[i].y - y0]);
|
pts.push([boundaryObj[i].x - x0, boundaryObj[i].y - y0]);
|
||||||
}
|
}
|
||||||
const newBarrierLatest = self.latestCollisionSys.createPolygon(x0, y0, pts);
|
const newBarrier = self.collisionSys.createPolygon(x0, y0, pts);
|
||||||
// console.log("Created barrier: ", newBarrierLatest);
|
// console.log("Created barrier: ", newBarrier);
|
||||||
const newBarrierChaser = self.chaserCollisionSys.createPolygon(x0, y0, pts);
|
|
||||||
++barrierIdCounter;
|
++barrierIdCounter;
|
||||||
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);
|
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);
|
||||||
self.latestCollisionSysMap.set(collisionBarrierIndex, newBarrierLatest);
|
self.collisionSysMap.set(collisionBarrierIndex, newBarrier);
|
||||||
self.chaserCollisionSysMap.set(collisionBarrierIndex, newBarrierChaser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
self.selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
||||||
@ -587,7 +582,7 @@ cc.Class({
|
|||||||
/*
|
/*
|
||||||
Don't change
|
Don't change
|
||||||
- lastAllConfirmedRenderFrameId, it's updated only in "rollbackAndChase" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
|
- lastAllConfirmedRenderFrameId, it's updated only in "rollbackAndChase" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
|
||||||
- chaserRenderFrameId, it's updated only in "onInputFrameDownsyncBatch" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
|
- chaserRenderFrameId, it's updated only in "rollbackAndChase & onInputFrameDownsyncBatch" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
|
||||||
*/
|
*/
|
||||||
return dumpRenderCacheRet;
|
return dumpRenderCacheRet;
|
||||||
}
|
}
|
||||||
@ -755,11 +750,9 @@ cc.Class({
|
|||||||
y0 = cpos[1];
|
y0 = cpos[1];
|
||||||
let pts = [[0, 0], [d, 0], [d, d], [0, d]];
|
let pts = [[0, 0], [d, 0], [d, d], [0, d]];
|
||||||
|
|
||||||
const newPlayerColliderLatest = self.latestCollisionSys.createPolygon(x0, y0, pts);
|
const newPlayerCollider = self.collisionSys.createPolygon(x0, y0, pts);
|
||||||
const newPlayerColliderChaser = self.chaserCollisionSys.createPolygon(x0, y0, pts);
|
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
self.latestCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderLatest);
|
self.collisionSysMap.set(collisionPlayerIndex, newPlayerCollider);
|
||||||
self.chaserCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderChaser);
|
|
||||||
|
|
||||||
safelyAddChild(self.node, newPlayerNode);
|
safelyAddChild(self.node, newPlayerNode);
|
||||||
setLocalZOrder(newPlayerNode, 5);
|
setLocalZOrder(newPlayerNode, 5);
|
||||||
@ -806,12 +799,11 @@ cc.Class({
|
|||||||
if (nextChaserRenderFrameId > self.renderFrameId) {
|
if (nextChaserRenderFrameId > self.renderFrameId) {
|
||||||
nextChaserRenderFrameId = self.renderFrameId;
|
nextChaserRenderFrameId = self.renderFrameId;
|
||||||
}
|
}
|
||||||
self.rollbackAndChase(prevChaserRenderFrameId, nextChaserRenderFrameId, self.chaserCollisionSys, self.chaserCollisionSysMap);
|
self.rollbackAndChase(prevChaserRenderFrameId, nextChaserRenderFrameId, self.collisionSys, self.collisionSysMap, true);
|
||||||
self.chaserRenderFrameId = nextChaserRenderFrameId; // Move the cursor "self.chaserRenderFrameId", keep in mind that "self.chaserRenderFrameId" is not monotonic!
|
|
||||||
let t2 = performance.now();
|
let t2 = performance.now();
|
||||||
|
|
||||||
// Inside the following "self.rollbackAndChase" (which actually ROLLS FORWARD), the "self.latestCollisionSys" is ALWAYS "ROLLED BACK" to "self.recentRenderCache.get(self.renderFrameId)" before being applied dynamics from corresponding delayedInputFrame, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
// Inside the following "self.rollbackAndChase" actually ROLLS FORWARD w.r.t. the corresponding delayedInputFrame, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
||||||
const rdf = self.rollbackAndChase(self.renderFrameId, self.renderFrameId + 1, self.latestCollisionSys, self.latestCollisionSysMap);
|
const rdf = self.rollbackAndChase(self.renderFrameId, self.renderFrameId + 1, self.collisionSys, self.collisionSysMap, false);
|
||||||
/*
|
/*
|
||||||
const nonTrivialChaseEnded = (prevChaserRenderFrameId < nextChaserRenderFrameId && nextChaserRenderFrameId == self.renderFrameId);
|
const nonTrivialChaseEnded = (prevChaserRenderFrameId < nextChaserRenderFrameId && nextChaserRenderFrameId == self.renderFrameId);
|
||||||
if (nonTrivialChaseEnded) {
|
if (nonTrivialChaseEnded) {
|
||||||
@ -981,6 +973,7 @@ cc.Class({
|
|||||||
|
|
||||||
// TODO: Write unit-test for this function to compare with its backend counter part
|
// TODO: Write unit-test for this function to compare with its backend counter part
|
||||||
applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap) {
|
applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap) {
|
||||||
|
const self = this;
|
||||||
const nextRenderFramePlayers = {}
|
const nextRenderFramePlayers = {}
|
||||||
for (let playerId in currRenderFrame.players) {
|
for (let playerId in currRenderFrame.players) {
|
||||||
const currPlayerDownsync = currRenderFrame.players[playerId];
|
const currPlayerDownsync = currRenderFrame.players[playerId];
|
||||||
@ -1001,19 +994,19 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toRet = {
|
const toRet = {
|
||||||
id: currRenderFrame.id,
|
id: currRenderFrame.id + 1,
|
||||||
players: nextRenderFramePlayers,
|
players: nextRenderFramePlayers,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (null != delayedInputFrame) {
|
if (null != delayedInputFrame) {
|
||||||
const inputList = delayedInputFrame.inputList;
|
const inputList = delayedInputFrame.inputList;
|
||||||
// [WARNING] Traverse in the order of joinIndices to guarantee determinism.
|
const effPushbacks = new Array(inputList.length).fill([0.0, 0.0]); // Guaranteed determinism regardless of traversal order
|
||||||
for (let j in self.playerRichInfoArr) {
|
for (let j in self.playerRichInfoArr) {
|
||||||
const joinIndex = parseInt(j) + 1;
|
const joinIndex = parseInt(j) + 1;
|
||||||
const playerId = self.playerRichInfoArr[j].id;
|
const playerId = self.playerRichInfoArr[j].id;
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
const player = renderFrame.players[playerId];
|
const player = currRenderFrame.players[playerId];
|
||||||
|
|
||||||
const encodedInput = inputList[joinIndex - 1];
|
const encodedInput = inputList[joinIndex - 1];
|
||||||
const decodedInput = self.ctrl.decodeDirection(encodedInput);
|
const decodedInput = self.ctrl.decodeDirection(encodedInput);
|
||||||
@ -1021,6 +1014,7 @@ cc.Class({
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log(`Got non-zero inputs for playerId=${playerId}, decodedInput=${JSON.stringify(decodedInput)} @currRenderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.id}`);
|
||||||
/*
|
/*
|
||||||
Reset "position" of players in "collisionSys" according to "virtual grid position". The easy part is that we don't have path-dependent-integrals to worry about like that of thermal dynamics.
|
Reset "position" of players in "collisionSys" according to "virtual grid position". The easy part is that we don't have path-dependent-integrals to worry about like that of thermal dynamics.
|
||||||
*/
|
*/
|
||||||
@ -1029,10 +1023,13 @@ cc.Class({
|
|||||||
const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[j]);
|
const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[j]);
|
||||||
playerCollider.x = newCpos[0];
|
playerCollider.x = newCpos[0];
|
||||||
playerCollider.y = newCpos[1];
|
playerCollider.y = newCpos[1];
|
||||||
|
// Update directions and thus would eventually update moving animation accordingly
|
||||||
|
nextRenderFramePlayers[playerId].dir.dx = decodedInput.dx;
|
||||||
|
nextRenderFramePlayers[playerId].dir.dy = decodedInput.dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
collisionSys.update();
|
collisionSys.update();
|
||||||
const result = collisionSys.createResult(); // Can I reuse a "self.latestCollisionSysResult" object throughout the whole battle?
|
const result = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
|
||||||
|
|
||||||
for (let j in self.playerRichInfoArr) {
|
for (let j in self.playerRichInfoArr) {
|
||||||
const joinIndex = parseInt(j) + 1;
|
const joinIndex = parseInt(j) + 1;
|
||||||
@ -1044,11 +1041,19 @@ cc.Class({
|
|||||||
// Test if the player collides with the wall
|
// Test if the player collides with the wall
|
||||||
if (!playerCollider.collides(potential, result)) continue;
|
if (!playerCollider.collides(potential, result)) continue;
|
||||||
// Push the player out of the wall
|
// Push the player out of the wall
|
||||||
playerCollider.x -= result.overlap * result.overlap_x;
|
effPushbacks[j][0] += result.overlap * result.overlap_x;
|
||||||
playerCollider.y -= result.overlap * result.overlap_y;
|
effPushbacks[j][1] += result.overlap * result.overlap_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x, playerCollider.y, self.playerRichInfoArr[j]);
|
const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x, playerCollider.y, self.playerRichInfoArr[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j in self.playerRichInfoArr) {
|
||||||
|
const joinIndex = parseInt(j) + 1;
|
||||||
|
const playerId = self.playerRichInfoArr[j].id;
|
||||||
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
|
const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[j][0], playerCollider.y - effPushbacks[j][1], self.playerRichInfoArr[j]);
|
||||||
nextRenderFramePlayers[playerId].virtualGridX = newVpos[0];
|
nextRenderFramePlayers[playerId].virtualGridX = newVpos[0];
|
||||||
nextRenderFramePlayers[playerId].virtualGridY = newVpos[1];
|
nextRenderFramePlayers[playerId].virtualGridY = newVpos[1];
|
||||||
}
|
}
|
||||||
@ -1057,14 +1062,15 @@ cc.Class({
|
|||||||
return toRet;
|
return toRet;
|
||||||
},
|
},
|
||||||
|
|
||||||
rollbackAndChase(renderFrameIdSt, renderFrameIdEd, collisionSys, collisionSysMap) {
|
rollbackAndChase(renderFrameIdSt, renderFrameIdEd, collisionSys, collisionSysMap, isChasing) {
|
||||||
/*
|
/*
|
||||||
This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd".
|
This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd" if not interruptted.
|
||||||
*/
|
*/
|
||||||
const self = this;
|
const self = this;
|
||||||
let latestRdf = self.recentRenderCache.getByFrameId(renderFrameIdSt); // typed "RoomDownsyncFrame"
|
let latestRdf = self.recentRenderCache.getByFrameId(renderFrameIdSt); // typed "RoomDownsyncFrame"
|
||||||
if (null == latestRdf) {
|
if (null == latestRdf) {
|
||||||
console.error("Couldn't find renderFrameId=", renderFrameIdSt, " to rollback, lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId, ", recentRenderCache=", self._stringifyRecentRenderCache(false), ", recentInputCache=", self._stringifyRecentInputCache(false));
|
console.error("Couldn't find renderFrameId=", renderFrameIdSt, " to rollback, lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId, ", recentRenderCache=", self._stringifyRecentRenderCache(false), ", recentInputCache=", self._stringifyRecentInputCache(false));
|
||||||
|
return latestRdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderFrameIdSt >= renderFrameIdEd) {
|
if (renderFrameIdSt >= renderFrameIdEd) {
|
||||||
@ -1072,14 +1078,16 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let i = renderFrameIdSt; i < renderFrameIdEd; ++i) {
|
for (let i = renderFrameIdSt; i < renderFrameIdEd; ++i) {
|
||||||
const currRenderFrame = self.recentRenderCache.getByFrameId(i); // typed "RoomDownsyncFrame"; FIXME: onRoomDownsyncFrame(rdf) might get called asynchronously and thus made this line return "null"!
|
const currRenderFrame = self.recentRenderCache.getByFrameId(i); // typed "RoomDownsyncFrame"; [WARNING] When "true == isChasing", this function can be interruptted by "onRoomDownsyncFrame(rdf)" asynchronously anytime, making this line return "null"!
|
||||||
if (null == currRenderFrame) {
|
if (null == currRenderFrame) {
|
||||||
console.error("Couldn't find renderFrameId=", i, " to rollback, lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId, ", recentRenderCache=", self._stringifyRecentRenderCache(false), ", recentInputCache=", self._stringifyRecentInputCache(false));
|
console.warn("Couldn't find renderFrame for i=", i, " to rollback, self.renderFrameId=", self.renderFrameId, ", lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId, ", might've been interruptted by `onRoomDownsyncFrame`");
|
||||||
|
return latestRdf;
|
||||||
}
|
}
|
||||||
const j = self._convertToInputFrameId(i, self.inputDelayFrames);
|
const j = self._convertToInputFrameId(i, self.inputDelayFrames);
|
||||||
const delayedInputFrame = self.getCachedInputFrameDownsyncWithPrediction(j);
|
const delayedInputFrame = self.getCachedInputFrameDownsyncWithPrediction(j);
|
||||||
if (null == delayedInputFrame) {
|
if (null == delayedInputFrame) {
|
||||||
console.error("Failed to get cached delayedInputFrame for renderFrameId=", i, ", inputFrameId=", j, "lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId, ", recentRenderCache=", self._stringifyRecentRenderCache(false), ", recentInputCache=", self._stringifyRecentInputCache(false));
|
console.warn("Failed to get cached delayedInputFrame for i=", i, ", j=", j, ", self.renderFrameId=", self.renderFrameId, ", lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId);
|
||||||
|
return latestRdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
latestRdf = self.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap);
|
latestRdf = self.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap);
|
||||||
@ -1091,10 +1099,15 @@ cc.Class({
|
|||||||
// We got a more up-to-date "all-confirmed-render-frame".
|
// We got a more up-to-date "all-confirmed-render-frame".
|
||||||
self.lastAllConfirmedRenderFrameId = latestRdf.id;
|
self.lastAllConfirmedRenderFrameId = latestRdf.id;
|
||||||
if (latestRdf.id > self.chaserRenderFrameId) {
|
if (latestRdf.id > self.chaserRenderFrameId) {
|
||||||
// it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId"
|
// it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId", regardeless of the "isChasing" param
|
||||||
self.chaserRenderFrameId = latestRdf.id;
|
self.chaserRenderFrameId = latestRdf.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (true == isChasing) {
|
||||||
|
// Move the cursor "self.chaserRenderFrameId", keep in mind that "self.chaserRenderFrameId" is not monotonic!
|
||||||
|
self.chaserRenderFrameId = latestRdf.id;
|
||||||
|
}
|
||||||
self.dumpToRenderCache(latestRdf);
|
self.dumpToRenderCache(latestRdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user