mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
Fixes for resync.
This commit is contained in:
parent
15a062af10
commit
320e98361e
@ -448,12 +448,11 @@ func (pR *Room) StartBattle() {
|
|||||||
pR.prefabInputFrameDownsync(noDelayInputFrameId)
|
pR.prefabInputFrameDownsync(noDelayInputFrameId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pR.markConfirmationIfApplicable()
|
||||||
unconfirmedMask := uint64(0)
|
unconfirmedMask := uint64(0)
|
||||||
if pR.BackendDynamicsEnabled {
|
if pR.BackendDynamicsEnabled {
|
||||||
// Force setting all-confirmed of buffered inputFrames periodically
|
// Force setting all-confirmed of buffered inputFrames periodically
|
||||||
unconfirmedMask = pR.forceConfirmationIfApplicable()
|
unconfirmedMask = pR.forceConfirmationIfApplicable()
|
||||||
} else {
|
|
||||||
pR.markConfirmationIfApplicable()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
upperToSendInputFrameId := atomic.LoadInt32(&(pR.LastAllConfirmedInputFrameId))
|
upperToSendInputFrameId := atomic.LoadInt32(&(pR.LastAllConfirmedInputFrameId))
|
||||||
@ -486,6 +485,7 @@ func (pR *Room) StartBattle() {
|
|||||||
refRenderFrameId = pR.CurDynamicsRenderFrameId
|
refRenderFrameId = pR.CurDynamicsRenderFrameId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for playerId, player := range pR.Players {
|
for playerId, player := range pR.Players {
|
||||||
if swapped := atomic.CompareAndSwapInt32(&player.BattleState, PlayerBattleStateIns.ACTIVE, PlayerBattleStateIns.ACTIVE); !swapped {
|
if swapped := atomic.CompareAndSwapInt32(&player.BattleState, PlayerBattleStateIns.ACTIVE, PlayerBattleStateIns.ACTIVE); !swapped {
|
||||||
// [WARNING] DON'T send anything if the player is disconnected, because it could jam the channel and cause significant delay upon "battle recovery for reconnected player".
|
// [WARNING] DON'T send anything if the player is disconnected, because it could jam the channel and cause significant delay upon "battle recovery for reconnected player".
|
||||||
@ -500,7 +500,7 @@ func (pR *Room) StartBattle() {
|
|||||||
candidateToSendInputFrameId := pR.Players[playerId].LastSentInputFrameId + 1
|
candidateToSendInputFrameId := pR.Players[playerId].LastSentInputFrameId + 1
|
||||||
if candidateToSendInputFrameId < pR.InputsBuffer.StFrameId {
|
if candidateToSendInputFrameId < pR.InputsBuffer.StFrameId {
|
||||||
// [WARNING] As "player.LastSentInputFrameId <= lastAllConfirmedInputFrameIdWithChange" for each iteration, and "lastAllConfirmedInputFrameIdWithChange <= lastAllConfirmedInputFrameId" where the latter is used to "applyInputFrameDownsyncDynamics" and then evict "pR.InputsBuffer", thus there's a very high possibility that "player.LastSentInputFrameId" is already evicted.
|
// [WARNING] As "player.LastSentInputFrameId <= lastAllConfirmedInputFrameIdWithChange" for each iteration, and "lastAllConfirmedInputFrameIdWithChange <= lastAllConfirmedInputFrameId" where the latter is used to "applyInputFrameDownsyncDynamics" and then evict "pR.InputsBuffer", thus there's a very high possibility that "player.LastSentInputFrameId" is already evicted.
|
||||||
// Logger.Debug(fmt.Sprintf("LastSentInputFrameId already popped: roomId=%v, playerId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, candidateToSendInputFrameId-1, player.AckingInputFrameId, pR.InputsBufferString(false)))
|
Logger.Warn(fmt.Sprintf("LastSentInputFrameId already popped: roomId=%v, playerId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, candidateToSendInputFrameId-1, player.AckingInputFrameId, pR.InputsBufferString(false)))
|
||||||
candidateToSendInputFrameId = pR.InputsBuffer.StFrameId
|
candidateToSendInputFrameId = pR.InputsBuffer.StFrameId
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,7 +526,6 @@ func (pR *Room) StartBattle() {
|
|||||||
|
|
||||||
if 0 >= len(toSendInputFrames) {
|
if 0 >= len(toSendInputFrames) {
|
||||||
// [WARNING] When sending DOWNSYNC_MSG_ACT_FORCED_RESYNC, there MUST BE accompanying "toSendInputFrames" for calculating "refRenderFrameId"!
|
// [WARNING] When sending DOWNSYNC_MSG_ACT_FORCED_RESYNC, there MUST BE accompanying "toSendInputFrames" for calculating "refRenderFrameId"!
|
||||||
|
|
||||||
if MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId {
|
if MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId {
|
||||||
Logger.Warn(fmt.Sprintf("Not sending due to empty toSendInputFrames: roomId=%v, playerId=%v, refRenderFrameId=%v, upperToSendInputFrameId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v", pR.Id, playerId, refRenderFrameId, upperToSendInputFrameId, player.LastSentInputFrameId, player.AckingInputFrameId))
|
Logger.Warn(fmt.Sprintf("Not sending due to empty toSendInputFrames: roomId=%v, playerId=%v, refRenderFrameId=%v, upperToSendInputFrameId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v", pR.Id, playerId, refRenderFrameId, upperToSendInputFrameId, player.LastSentInputFrameId, player.AckingInputFrameId))
|
||||||
}
|
}
|
||||||
@ -535,8 +534,9 @@ func (pR *Room) StartBattle() {
|
|||||||
|
|
||||||
indiceInJoinIndexBooleanArr := uint32(player.JoinIndex - 1)
|
indiceInJoinIndexBooleanArr := uint32(player.JoinIndex - 1)
|
||||||
var joinMask uint64 = (1 << indiceInJoinIndexBooleanArr)
|
var joinMask uint64 = (1 << indiceInJoinIndexBooleanArr)
|
||||||
if pR.BackendDynamicsEnabled && (MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId || 0 < (unconfirmedMask&joinMask)) {
|
shouldResyncForSlowerClocker := (0 < (unconfirmedMask & joinMask)) // This condition is critical, if we don't send resync upon this condition, the player with a slower frontend clock might never get its input synced
|
||||||
// [WARNING] Even upon "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED", it could be true that "0 == (unconfirmedMask & joinMask)"!
|
if pR.BackendDynamicsEnabled && (MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId || shouldResyncForSlowerClocker) {
|
||||||
|
// [WARNING] Even upon "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED", it could be true that "0 == ()"!
|
||||||
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
|
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
|
||||||
if nil == tmp {
|
if nil == tmp {
|
||||||
panic(fmt.Sprintf("Required refRenderFrameId=%v for roomId=%v, playerId=%v, candidateToSendInputFrameId=%v doesn't exist! InputsBuffer=%v, RenderFrameBuffer=%v", refRenderFrameId, pR.Id, playerId, candidateToSendInputFrameId, pR.InputsBufferString(false), pR.RenderFrameBufferString()))
|
panic(fmt.Sprintf("Required refRenderFrameId=%v for roomId=%v, playerId=%v, candidateToSendInputFrameId=%v doesn't exist! InputsBuffer=%v, RenderFrameBuffer=%v", refRenderFrameId, pR.Id, playerId, candidateToSendInputFrameId, pR.InputsBufferString(false), pR.RenderFrameBufferString()))
|
||||||
@ -550,28 +550,35 @@ func (pR *Room) StartBattle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evict no longer required "RenderFrameBuffer"
|
if pR.BackendDynamicsEnabled {
|
||||||
for pR.RenderFrameBuffer.N < pR.RenderFrameBuffer.Cnt || (0 < pR.RenderFrameBuffer.Cnt && pR.RenderFrameBuffer.StFrameId < refRenderFrameId) {
|
// Evict no longer required "RenderFrameBuffer"
|
||||||
_ = pR.RenderFrameBuffer.Pop()
|
for pR.RenderFrameBuffer.N < pR.RenderFrameBuffer.Cnt || (0 < pR.RenderFrameBuffer.Cnt && pR.RenderFrameBuffer.StFrameId < refRenderFrameId) {
|
||||||
|
_ = pR.RenderFrameBuffer.Pop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toApplyInputFrameId := pR.ConvertToInputFrameId(refRenderFrameId, pR.InputDelayFrames)
|
toApplyInputFrameId := pR.ConvertToInputFrameId(refRenderFrameId, pR.InputDelayFrames)
|
||||||
if false == pR.BackendDynamicsEnabled {
|
/*
|
||||||
// When "false == pR.BackendDynamicsEnabled", the variable "refRenderFrameId" is not well defined
|
[WARNING]
|
||||||
minLastSentInputFrameId := int32(math.MaxInt32)
|
The following updates to "toApplyInputFrameId" is necessary because
|
||||||
for _, player := range pR.Players {
|
1. When "false == pR.BackendDynamicsEnabled", the variable "refRenderFrameId" is not well defined;
|
||||||
if player.LastSentInputFrameId >= minLastSentInputFrameId {
|
2. When "true == pR.BackendDynamicsEnabled", the initial value of "toApplyInputFrameId" might be too big and thus making frontends unable to receive consecutive all-confirmed inputFrameDownsync sequence - which is what we want during a battle if no one disconnects.
|
||||||
continue
|
*/
|
||||||
}
|
minLastSentInputFrameId := int32(math.MaxInt32)
|
||||||
minLastSentInputFrameId = player.LastSentInputFrameId
|
for _, player := range pR.Players {
|
||||||
|
if player.LastSentInputFrameId >= minLastSentInputFrameId {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
minLastSentInputFrameId = player.LastSentInputFrameId
|
||||||
|
}
|
||||||
|
if minLastSentInputFrameId < toApplyInputFrameId {
|
||||||
toApplyInputFrameId = minLastSentInputFrameId
|
toApplyInputFrameId = minLastSentInputFrameId
|
||||||
}
|
}
|
||||||
for pR.InputsBuffer.N < pR.InputsBuffer.Cnt || (0 < pR.InputsBuffer.Cnt && pR.InputsBuffer.StFrameId < toApplyInputFrameId) {
|
for pR.InputsBuffer.N < pR.InputsBuffer.Cnt || (0 < pR.InputsBuffer.Cnt && pR.InputsBuffer.StFrameId < toApplyInputFrameId) {
|
||||||
f := pR.InputsBuffer.Pop().(*InputFrameDownsync)
|
f := pR.InputsBuffer.Pop().(*InputFrameDownsync)
|
||||||
if pR.inputFrameIdDebuggable(f.InputFrameId) {
|
if pR.inputFrameIdDebuggable(f.InputFrameId) {
|
||||||
// Popping of an "inputFrame" would be AFTER its being all being confirmed, because it requires the "inputFrame" to be all acked
|
// Popping of an "inputFrame" would be AFTER its being all being confirmed, because it requires the "inputFrame" to be all acked
|
||||||
Logger.Debug("inputFrame lifecycle#4[popped]:", zap.Any("roomId", pR.Id), zap.Any("inputFrameId", f.InputFrameId), zap.Any("InputsBuffer", pR.InputsBufferString(false)))
|
Logger.Debug("inputFrame lifecycle#4[popped]:", zap.Any("roomId", pR.Id), zap.Any("inputFrameId", f.InputFrameId), zap.Any("minLastSentInputFrameId", minLastSentInputFrameId), zap.Any("toApplyInputFrameId", toApplyInputFrameId), zap.Any("InputsBuffer", pR.InputsBufferString(false)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1109,7 +1116,6 @@ func (pR *Room) markConfirmationIfApplicable() {
|
|||||||
inputFrameDownsync.ConfirmedList |= (1 << indiceInJoinIndexBooleanArr)
|
inputFrameDownsync.ConfirmedList |= (1 << indiceInJoinIndexBooleanArr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force confirmation of "inputFrame2"
|
|
||||||
if allConfirmedMask == inputFrameDownsync.ConfirmedList {
|
if allConfirmedMask == inputFrameDownsync.ConfirmedList {
|
||||||
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, -1)
|
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, -1)
|
||||||
} else {
|
} else {
|
||||||
@ -1140,24 +1146,12 @@ func (pR *Room) forceConfirmationIfApplicable() uint64 {
|
|||||||
if nil == tmp {
|
if nil == tmp {
|
||||||
panic(fmt.Sprintf("inputFrameId2=%v doesn't exist for roomId=%v, this is abnormal because the server should prefab inputFrameDownsync in a most advanced pace, check the prefab logic! InputsBuffer=%v", inputFrameId2, pR.Id, pR.InputsBufferString(false)))
|
panic(fmt.Sprintf("inputFrameId2=%v doesn't exist for roomId=%v, this is abnormal because the server should prefab inputFrameDownsync in a most advanced pace, check the prefab logic! InputsBuffer=%v", inputFrameId2, pR.Id, pR.InputsBufferString(false)))
|
||||||
}
|
}
|
||||||
inputFrame2 := tmp.(*InputFrameDownsync)
|
|
||||||
for _, player := range pR.Players {
|
|
||||||
// Enrich by already arrived player upsync commands
|
|
||||||
bufIndex := pR.toDiscreteInputsBufferIndex(inputFrame2.InputFrameId, player.JoinIndex)
|
|
||||||
tmp, loaded := pR.DiscreteInputsBuffer.LoadAndDelete(bufIndex)
|
|
||||||
if !loaded {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inputFrameUpsync := tmp.(*InputFrameUpsync)
|
|
||||||
indiceInJoinIndexBooleanArr := uint32(player.JoinIndex - 1)
|
|
||||||
inputFrame2.InputList[indiceInJoinIndexBooleanArr] = pR.EncodeUpsyncCmd(inputFrameUpsync)
|
|
||||||
inputFrame2.ConfirmedList |= (1 << indiceInJoinIndexBooleanArr)
|
|
||||||
}
|
|
||||||
|
|
||||||
totPlayerCnt := uint32(pR.Capacity)
|
totPlayerCnt := uint32(pR.Capacity)
|
||||||
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
||||||
|
|
||||||
// Force confirmation of "inputFrame2"
|
// Force confirmation of "inputFrame2"
|
||||||
|
inputFrame2 := tmp.(*InputFrameDownsync)
|
||||||
oldConfirmedList := inputFrame2.ConfirmedList
|
oldConfirmedList := inputFrame2.ConfirmedList
|
||||||
unconfirmedMask := (oldConfirmedList ^ allConfirmedMask)
|
unconfirmedMask := (oldConfirmedList ^ allConfirmedMask)
|
||||||
inputFrame2.ConfirmedList = allConfirmedMask
|
inputFrame2.ConfirmedList = allConfirmedMask
|
||||||
@ -1244,9 +1238,6 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
|
|||||||
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
|
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
|
||||||
currPlayerDownsync := currRenderFrame.Players[playerId]
|
currPlayerDownsync := currRenderFrame.Players[playerId]
|
||||||
encodedInput := inputList[joinIndex-1]
|
encodedInput := inputList[joinIndex-1]
|
||||||
if 0 == encodedInput {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
decodedInput := DIRECTION_DECODER[encodedInput]
|
decodedInput := DIRECTION_DECODER[encodedInput]
|
||||||
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))
|
||||||
|
@ -174,9 +174,16 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const joinIndex = self.selfPlayerInfo.joinIndex;
|
const joinIndex = self.selfPlayerInfo.joinIndex;
|
||||||
const discreteDir = self.ctrl.getDiscretizedDirection();
|
|
||||||
const previousInputFrameDownsyncWithPrediction = self.getCachedInputFrameDownsyncWithPrediction(inputFrameId);
|
const previousInputFrameDownsyncWithPrediction = self.getCachedInputFrameDownsyncWithPrediction(inputFrameId);
|
||||||
|
const previousSelfInput = (null == previousInputFrameDownsyncWithPrediction ? null : previousInputFrameDownsyncWithPrediction.inputList[joinIndex - 1]);
|
||||||
|
|
||||||
|
// If "forceConfirmation" is active on backend, we shouldn't override the already downsynced "inputFrameDownsync"s.
|
||||||
|
const existingInputFrame = self.recentInputCache.getByFrameId(inputFrameId);
|
||||||
|
if (null != existingInputFrame && self._allConfirmed(existingInputFrame.confirmedList)) {
|
||||||
|
return [previousSelfInput, existingInputFrame.inputList[joinIndex - 1]];
|
||||||
|
}
|
||||||
const prefabbedInputList = (null == previousInputFrameDownsyncWithPrediction ? new Array(self.playerRichInfoDict.size).fill(0) : previousInputFrameDownsyncWithPrediction.inputList.slice());
|
const prefabbedInputList = (null == previousInputFrameDownsyncWithPrediction ? new Array(self.playerRichInfoDict.size).fill(0) : previousInputFrameDownsyncWithPrediction.inputList.slice());
|
||||||
|
const discreteDir = self.ctrl.getDiscretizedDirection();
|
||||||
prefabbedInputList[(joinIndex - 1)] = discreteDir.encodedIdx;
|
prefabbedInputList[(joinIndex - 1)] = discreteDir.encodedIdx;
|
||||||
const prefabbedInputFrameDownsync = {
|
const prefabbedInputFrameDownsync = {
|
||||||
inputFrameId: inputFrameId,
|
inputFrameId: inputFrameId,
|
||||||
@ -186,7 +193,6 @@ cc.Class({
|
|||||||
|
|
||||||
self.dumpToInputCache(prefabbedInputFrameDownsync); // A prefabbed inputFrame, would certainly be adding a new inputFrame to the cache, because server only downsyncs "all-confirmed inputFrames"
|
self.dumpToInputCache(prefabbedInputFrameDownsync); // A prefabbed inputFrame, would certainly be adding a new inputFrame to the cache, because server only downsyncs "all-confirmed inputFrames"
|
||||||
|
|
||||||
const previousSelfInput = (null == previousInputFrameDownsyncWithPrediction ? null : previousInputFrameDownsyncWithPrediction.inputList[joinIndex - 1]);
|
|
||||||
return [previousSelfInput, discreteDir.encodedIdx];
|
return [previousSelfInput, discreteDir.encodedIdx];
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -664,6 +670,8 @@ cc.Class({
|
|||||||
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
||||||
}
|
}
|
||||||
self.lastAllConfirmedInputFrameId = inputFrameDownsyncId;
|
self.lastAllConfirmedInputFrameId = inputFrameDownsyncId;
|
||||||
|
// [WARNING] Take all "inputFrameDownsync" from backend as all-confirmed, it'll be later checked by "rollbackAndChase".
|
||||||
|
inputFrameDownsync.confirmedList = (1 << self.playerRichInfoDict.size) - 1;
|
||||||
self.dumpToInputCache(inputFrameDownsync);
|
self.dumpToInputCache(inputFrameDownsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,9 +1008,10 @@ cc.Class({
|
|||||||
|
|
||||||
if (null != delayedInputFrame) {
|
if (null != delayedInputFrame) {
|
||||||
const inputList = delayedInputFrame.inputList;
|
const inputList = delayedInputFrame.inputList;
|
||||||
const effPushbacks = new Array(inputList.length).fill([0.0, 0.0]); // Guaranteed determinism regardless of traversal order
|
const effPushbacks = new Array(self.playerRichInfoArr.length); // 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;
|
||||||
|
effPushbacks[joinIndex - 1] = [0.0, 0.0];
|
||||||
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);
|
||||||
@ -1010,9 +1019,6 @@ cc.Class({
|
|||||||
|
|
||||||
const encodedInput = inputList[joinIndex - 1];
|
const encodedInput = inputList[joinIndex - 1];
|
||||||
const decodedInput = self.ctrl.decodeDirection(encodedInput);
|
const decodedInput = self.ctrl.decodeDirection(encodedInput);
|
||||||
if (0 == decodedInput.dx && 0 == decodedInput.dy) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(`Got non-zero inputs for playerId=${playerId}, decodedInput=${JSON.stringify(decodedInput)} @currRenderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.id}`);
|
// console.log(`Got non-zero inputs for playerId=${playerId}, decodedInput=${JSON.stringify(decodedInput)} @currRenderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.id}`);
|
||||||
/*
|
/*
|
||||||
@ -1020,7 +1026,7 @@ cc.Class({
|
|||||||
*/
|
*/
|
||||||
const newVx = player.virtualGridX + (decodedInput.dx + player.speed * decodedInput.dx);
|
const newVx = player.virtualGridX + (decodedInput.dx + player.speed * decodedInput.dx);
|
||||||
const newVy = player.virtualGridY + (decodedInput.dy + player.speed * decodedInput.dy);
|
const newVy = player.virtualGridY + (decodedInput.dy + player.speed * decodedInput.dy);
|
||||||
const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[j]);
|
const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1]);
|
||||||
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
|
// Update directions and thus would eventually update moving animation accordingly
|
||||||
@ -1041,11 +1047,9 @@ 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
|
||||||
effPushbacks[j][0] += result.overlap * result.overlap_x;
|
effPushbacks[joinIndex - 1][0] += result.overlap * result.overlap_x;
|
||||||
effPushbacks[j][1] += result.overlap * result.overlap_y;
|
effPushbacks[joinIndex - 1][1] += result.overlap * result.overlap_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x, playerCollider.y, self.playerRichInfoArr[j]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let j in self.playerRichInfoArr) {
|
for (let j in self.playerRichInfoArr) {
|
||||||
@ -1053,7 +1057,7 @@ cc.Class({
|
|||||||
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 newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[j][0], playerCollider.y - effPushbacks[j][1], self.playerRichInfoArr[j]);
|
const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j]);
|
||||||
nextRenderFramePlayers[playerId].virtualGridX = newVpos[0];
|
nextRenderFramePlayers[playerId].virtualGridX = newVpos[0];
|
||||||
nextRenderFramePlayers[playerId].virtualGridY = newVpos[1];
|
nextRenderFramePlayers[playerId].virtualGridY = newVpos[1];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user