mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 11:18:55 +00:00
Minor fix on rollback frame id counting.
This commit is contained in:
parent
372bfc2b48
commit
f3428c88df
@ -535,7 +535,7 @@ func (pR *Room) ChooseStage() error {
|
||||
ErrFatal(err)
|
||||
|
||||
rand.Seed(time.Now().Unix())
|
||||
stageNameList := []string{"pacman" /*, "richsoil"*/}
|
||||
stageNameList := []string{/*"pacman" ,*/ "richsoil"}
|
||||
chosenStageIndex := rand.Int() % len(stageNameList) // Hardcoded temporarily. -- YFLu
|
||||
|
||||
pR.StageName = stageNameList[chosenStageIndex]
|
||||
|
@ -7,11 +7,11 @@
|
||||
eJztz0ENACAMALGR4F8zNspyjwronZm7xPlcD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPy7bHBg/ldQwR
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="2" name="PlayerStartingPos" locked="1">
|
||||
<object id="135" x="320" y="2884">
|
||||
<objectgroup id="2" name="PlayerStartingPos">
|
||||
<object id="135" x="1689.33" y="1872">
|
||||
<point/>
|
||||
</object>
|
||||
<object id="137" x="2876" y="320">
|
||||
<object id="137" x="1926.67" y="1626.67">
|
||||
<point/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
|
@ -440,7 +440,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
209.65900912275052,
|
||||
216.05530045313827,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -41,11 +41,6 @@ module.export = cc.Class({
|
||||
|
||||
self.computedNewDifferentPosLocalToParentWithinCurrentFrame = null;
|
||||
self.actionMangerSingleton = new cc.ActionManager();
|
||||
self.scheduledDirection = {
|
||||
dx: 0,
|
||||
dy: 0
|
||||
};
|
||||
|
||||
self.activeDirection = {
|
||||
dx: 0,
|
||||
dy: 0
|
||||
@ -65,6 +60,7 @@ module.export = cc.Class({
|
||||
'2-1': 'BottomRight'
|
||||
};
|
||||
const canvasNode = self.mapNode.parent;
|
||||
self.mapIns = self.mapNode.getComponent("Map");
|
||||
self.contactedBarriers = [];
|
||||
const joystickInputControllerScriptIns = canvasNode.getComponent("TouchEventsManager");
|
||||
self.ctrl = joystickInputControllerScriptIns;
|
||||
@ -77,8 +73,9 @@ module.export = cc.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
if (forceAnimSwitch || null == this.scheduledDirection || (newScheduledDirection.dx != this.scheduledDirection.dx || newScheduledDirection.dy != this.scheduledDirection.dy)) {
|
||||
this.scheduledDirection = newScheduledDirection;
|
||||
if (forceAnimSwitch || null == this.activeDirection || (newScheduledDirection.dx != this.activeDirection.dx || newScheduledDirection.dy != this.activeDirection.dy)) {
|
||||
this.activeDirection = newScheduledDirection;
|
||||
this.activeDirection = newScheduledDirection;
|
||||
const clipKey = newScheduledDirection.dx.toString() + newScheduledDirection.dy.toString();
|
||||
const clips = (this.attacked ? this.attackedClips : this.clips);
|
||||
let clip = clips[clipKey];
|
||||
@ -90,7 +87,7 @@ module.export = cc.Class({
|
||||
} else {
|
||||
this.animComp.play(clip);
|
||||
if (this.attacked) {
|
||||
cc.log(`Attacked, switching to play clipKey = ${clipKey}, clip == ${clip}, this.activeDirection == ${JSON.stringify(this.activeDirection)}, this.scheduledDirection == ${JSON.stringify(this.scheduledDirection)}.`);
|
||||
cc.log(`Attacked, switching to play clipKey = ${clipKey}, clip == ${clip}, this.activeDirection == ${JSON.stringify(this.activeDirection)}, this.activeDirection == ${JSON.stringify(this.activeDirection)}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,7 +354,7 @@ module.export = cc.Class({
|
||||
|
||||
update(dt) {
|
||||
const self = this;
|
||||
const vecToMoveBy = self._calculateVecToMoveBy(dt);
|
||||
const vecToMoveBy = self._calculateVecToMoveBy(self.mapIns.rollbackEstimatedDt); // To be consistent w.r.t. rollback dynamics
|
||||
// console.log("activeDirection=", self.activeDirection, "vecToMoveBy=", vecToMoveBy, ", computedNewDifferentPosLocalToParentWithinCurrentFrame=", self.computedNewDifferentPosLocalToParentWithinCurrentFrame);
|
||||
if (self._canMoveBy(vecToMoveBy)) {
|
||||
self.node.position = self.computedNewDifferentPosLocalToParentWithinCurrentFrame;
|
||||
@ -366,8 +363,8 @@ module.export = cc.Class({
|
||||
|
||||
lateUpdate(dt) {
|
||||
const self = this;
|
||||
self.activeDirection.dx = self.scheduledDirection.dx;
|
||||
self.activeDirection.dy = self.scheduledDirection.dy;
|
||||
self.activeDirection.dx = self.activeDirection.dx;
|
||||
self.activeDirection.dy = self.activeDirection.dy;
|
||||
const now = new Date().getTime();
|
||||
self.lastMovedAt = now;
|
||||
},
|
||||
@ -460,12 +457,10 @@ module.export = cc.Class({
|
||||
startFrozenDisplay() {
|
||||
const self = this;
|
||||
self.attacked = true;
|
||||
self.scheduleNewDirection(self.scheduledDirection, true);
|
||||
},
|
||||
|
||||
stopFrozenDisplay() {
|
||||
const self = this;
|
||||
self.attacked = false;
|
||||
self.scheduleNewDirection(self.scheduledDirection, true);
|
||||
},
|
||||
});
|
||||
|
@ -123,6 +123,10 @@ cc.Class({
|
||||
type: cc.TiledMap,
|
||||
default: null
|
||||
},
|
||||
rollbackEstimatedDt: {
|
||||
type: cc.Float,
|
||||
default: 1.0/60
|
||||
},
|
||||
},
|
||||
|
||||
_inputFrameIdDebuggable(inputFrameId) {
|
||||
@ -338,13 +342,12 @@ cc.Class({
|
||||
|
||||
self.recentFrameCache = {};
|
||||
self.recentFrameCacheCurrentSize = 0;
|
||||
self.recentFrameCacheMaxCount = 2048;
|
||||
self.recentFrameCacheMaxCount = 1024;
|
||||
|
||||
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
|
||||
self.recentInputCache = {}; // TODO: Use a ringbuf instead
|
||||
self.recentInputCacheCurrentSize = 0;
|
||||
self.recentInputCacheMaxCount = 1024;
|
||||
self.rollbackEstimatedDt = 1.0/60;
|
||||
self.transitToState(ALL_MAP_STATES.VISUAL);
|
||||
|
||||
self.battleState = ALL_BATTLE_STATES.WAITING;
|
||||
@ -588,8 +591,9 @@ cc.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
let firstPredictedYetIncorrectInputFrameId = -1;
|
||||
let firstPredictedYetIncorrectInputFrameJoinIndex = -1;
|
||||
// console.log("Received inputFrameDownsyncBatch=", batch, ", now correspondingLastLocalInputFrame=", self.recentInputCache[batch[batch.length-1].inputFrameId]);
|
||||
let firstPredictedYetIncorrectInputFrameId = null;
|
||||
let firstPredictedYetIncorrectInputFrameJoinIndex = null;
|
||||
for (let k in batch) {
|
||||
const inputFrameDownsync = batch[k];
|
||||
const inputFrameDownsyncId = inputFrameDownsync.inputFrameId;
|
||||
@ -597,7 +601,7 @@ cc.Class({
|
||||
if (null == localInputFrame) {
|
||||
console.warn("handleInputFrameDownsyncBatch: recentInputCache is NOT having inputFrameDownsyncId=", inputFrameDownsyncId, "; now recentInputCache=", self._stringifyRecentInputCache(false));
|
||||
} else {
|
||||
if (-1 == firstPredictedYetIncorrectInputFrameId) {
|
||||
if (null == firstPredictedYetIncorrectInputFrameId) {
|
||||
for (let i in localInputFrame.inputList) {
|
||||
if (localInputFrame.inputList[i] != inputFrameDownsync.inputList[i]) {
|
||||
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
||||
@ -611,19 +615,17 @@ cc.Class({
|
||||
// [WARNING] Currently "lastDownsyncInputFrameId" and "lastAllConfirmedInputFrameId" are identical, but they (their definitions) are prone to changes in the future
|
||||
self.lastDownsyncInputFrameId = inputFrameDownsyncId;
|
||||
self.lastAllConfirmedInputFrameId = inputFrameDownsyncId;
|
||||
if (self._inputFrameIdDebuggable(inputFrameDownsyncId)) {
|
||||
console.log("Received inputFrameDownsyncId=", inputFrameDownsyncId);
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 != firstPredictedYetIncorrectInputFrameId) {
|
||||
if (null != firstPredictedYetIncorrectInputFrameId) {
|
||||
const renderFrameId2 = self.renderFrameId;
|
||||
const inputFrameId2 = self._convertToInputFrameId(renderFrameId2, self.inputDelayFrames);
|
||||
const inputFrameId1 = firstPredictedYetIncorrectInputFrameId;
|
||||
const renderFrameId1 = self._convertToRenderFrameId(inputFrameId1, self.inputDelayFrames); // a.k.a. "firstRenderFrameIdUsingIncorrectInputFrameId"
|
||||
if (renderFrameId1 <= renderFrameId2) {
|
||||
if (renderFrameId1 < renderFrameId2) {
|
||||
// No need to rollback when "renderFrameId1 == renderFrameId2", because the "delayedInputFrame for renderFrameId2" is not yet executed by now, it just went through "++self.renderFrameId" in "update(dt)" and js-runtime is mostly single-threaded in our programmable range.
|
||||
console.warn("Mismatched input! inputFrameId1=", inputFrameId1, ", renderFrameId1=", renderFrameId1, ": at least 1 incorrect input predicted for joinIndex=", firstPredictedYetIncorrectInputFrameJoinIndex, ", inputFrameId2 = ", inputFrameId2, ", renderFrameId2=", renderFrameId2);
|
||||
self._rollback(inputFrameId1, renderFrameId1, inputFrameId2, renderFrameId2);
|
||||
self._rollbackAndReplay(inputFrameId1, renderFrameId1, inputFrameId2, renderFrameId2);
|
||||
} else {
|
||||
console.log("Mismatched input yet no rollback needed. inputFrameId1=", inputFrameId1, ", renderFrameId1=", renderFrameId1, ": at least 1 incorrect input predicted for joinIndex=", firstPredictedYetIncorrectInputFrameJoinIndex, ", inputFrameId2 = ", inputFrameId2, ", renderFrameId2=", renderFrameId2);
|
||||
}
|
||||
@ -774,7 +776,6 @@ cc.Class({
|
||||
// TODO: Is the following statement run asynchronously in an implicit manner? Should I explicitly run it asynchronously?
|
||||
self._sendInputFrameUpsyncBatch(noDelayInputFrameId);
|
||||
}
|
||||
++self.renderFrameId;
|
||||
const delayedInputFrameId = self._convertToInputFrameId(self.renderFrameId, self.inputDelayFrames); // The "inputFrameId" to use at current "renderFrameId"
|
||||
const delayedInputFrameDownsync = self.recentInputCache[delayedInputFrameId];
|
||||
if (null == delayedInputFrameDownsync) {
|
||||
@ -782,6 +783,14 @@ cc.Class({
|
||||
} else {
|
||||
self._applyInputFrameDownsyncDynamics(delayedInputFrameDownsync, false);
|
||||
}
|
||||
const rdf = self._createRoomDownsyncFrameLocally();
|
||||
self._dumpToFullFrameCache(rdf);
|
||||
/*
|
||||
if (null != delayedInputFrameDownsync && null != delayedInputFrameDownsync.inputList && 0 < delayedInputFrameDownsync.inputList[self.selfPlayerInfo.joinIndex-1]) {
|
||||
console.log("My critical status: renderFrame=", JSON.stringify(rdf), ", delayedInputFrameDownsync=", JSON.stringify(delayedInputFrameDownsync));
|
||||
}
|
||||
*/
|
||||
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
|
||||
}
|
||||
const mapNode = self.node;
|
||||
const canvasNode = mapNode.parent;
|
||||
@ -792,7 +801,7 @@ cc.Class({
|
||||
|
||||
// update countdown
|
||||
if (null != self.countdownNanos) {
|
||||
self.countdownNanos -= dt*1000000000;
|
||||
self.countdownNanos -= self.rollbackEstimatedDt*1000000000;
|
||||
if (self.countdownNanos <= 0) {
|
||||
self.onBattleStopped(self.playerRichInfoDict);
|
||||
return;
|
||||
@ -809,7 +818,6 @@ cc.Class({
|
||||
}
|
||||
if (null != self.ctrl) {
|
||||
self.ctrl.justifyMapNodePosAndScale(self.ctrl.linearSpeedBase, self.ctrl.zoomingSpeedBase);
|
||||
self._createRoomDownsyncFrameLocally();
|
||||
}
|
||||
},
|
||||
|
||||
@ -928,7 +936,7 @@ cc.Class({
|
||||
joinIndex: joinIndex
|
||||
};
|
||||
}
|
||||
self._dumpToFullFrameCache(rdf);
|
||||
return rdf;
|
||||
},
|
||||
|
||||
_applyRoomDownsyncFrameDynamics(rdf) {
|
||||
@ -960,19 +968,21 @@ cc.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_rollback(inputFrameId1, renderFrameId1, inputFrameId2, renderFrameId2) {
|
||||
_rollbackAndReplay(inputFrameId1, renderFrameId1, inputFrameId2, renderFrameId2) {
|
||||
const self = this;
|
||||
const rdf1 = self.recentFrameCache[renderFrameId1];
|
||||
if (null == rdf1) {
|
||||
const recentFrameCacheKeys = Object.keys(self.recentFrameCache);
|
||||
console.warn("renderFrameId1=", renderFrameId1, "doesn't exist in recentFrameCache ", self._stringifyRecentFrameCache(false), ": COULDN'T ROLLBACK!");
|
||||
console.error("renderFrameId1=", renderFrameId1, "doesn't exist in recentFrameCache ", self._stringifyRecentFrameCache(false), ": COULDN'T ROLLBACK!");
|
||||
return;
|
||||
}
|
||||
self._applyRoomDownsyncFrameDynamics(rdf1);
|
||||
for (let renderFrameId = renderFrameId1; renderFrameId <= renderFrameId2; ++renderFrameId) {
|
||||
// DON'T apply inputFrameDownsync dynamics for exactly "renderFrameId2", see the comment around the invocation of "_rollbackAndReplay".
|
||||
for (let renderFrameId = renderFrameId1; renderFrameId < renderFrameId2; ++renderFrameId) {
|
||||
const delayedInputFrameId = self._convertToInputFrameId(renderFrameId, self.inputDelayFrames);
|
||||
const delayedInputFrame = self.recentInputCache[delayedInputFrameId];
|
||||
self._applyInputFrameDownsyncDynamics(delayedInputFrame, true);
|
||||
const delayedInputFrameDownsync = self.recentInputCache[delayedInputFrameId];
|
||||
self._applyInputFrameDownsyncDynamics(delayedInputFrameDownsync, true);
|
||||
// console.log("_rollbackAndReplay, AFTER:", self._stringifyRollbackResult(renderFrameId, delayedInputFrameDownsync));
|
||||
}
|
||||
},
|
||||
|
||||
@ -1000,10 +1010,17 @@ cc.Class({
|
||||
|
||||
_stringifyRecentFrameCache(usefullOutput) {
|
||||
if (true == usefullOutput) {
|
||||
return JSON.stringify(this.recentFrameCache);
|
||||
|
||||
let s = [];
|
||||
for (let renderFrameId in self.recentFrameCache) {
|
||||
const roomDownsyncFrame = self.recentFrameCache[renderFrameId];
|
||||
s.push(JSON.stringify(roomDownsyncFrame));
|
||||
}
|
||||
|
||||
return s.join('\n');
|
||||
}
|
||||
const keys = Object.keys(this.recentInputCache);
|
||||
return "[stIRenderFrameId=" + keys[0] + ", edRenderFrameId=" + keys[keys.length-1] + "]";
|
||||
const keys = Object.keys(this.recentFrameCache);
|
||||
return "[stRenderFrameId=" + keys[0] + ", edRenderFrameId=" + keys[keys.length-1] + "]";
|
||||
},
|
||||
|
||||
_stringifyRecentInputCache(usefullOutput) {
|
||||
@ -1013,4 +1030,37 @@ cc.Class({
|
||||
const keys = Object.keys(this.recentInputCache);
|
||||
return "[stInputFrameId=" + keys[0] + ", edInputFrameId=" + keys[keys.length-1] + "]";
|
||||
},
|
||||
|
||||
_stringifyRollbackResult(renderFrameId, delayedInputFrameDownsync) {
|
||||
// Slightly different from "_createRoomDownsyncFrameLocally"
|
||||
const self = this;
|
||||
const s = (
|
||||
null == delayedInputFrameDownsync
|
||||
?
|
||||
{
|
||||
renderFrameId: renderFrameId,
|
||||
players: {}
|
||||
}
|
||||
:
|
||||
{
|
||||
renderFrameId: renderFrameId,
|
||||
players: {},
|
||||
delayedInputFrameDownsync: delayedInputFrameDownsync,
|
||||
}
|
||||
);
|
||||
let players = {};
|
||||
for (let playerId in self.playerRichInfoDict) {
|
||||
const playerRichInfo = self.playerRichInfoDict[playerId];
|
||||
const joinIndex = playerRichInfo.joinIndex;
|
||||
const playerNode = playerRichInfo.node;
|
||||
const playerScriptIns = playerRichInfo.scriptIns;
|
||||
s.players[playerRichInfo.id] = {
|
||||
id: playerRichInfo.id,
|
||||
x: playerNode.position.x,
|
||||
y: playerNode.position.y,
|
||||
};
|
||||
}
|
||||
|
||||
return JSON.stringify(s);
|
||||
},
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user