Fixed collision detection and camera tracking.

This commit is contained in:
genxium 2022-09-26 11:16:18 +08:00
parent 2dfd6083c5
commit 80dc05a92b
5 changed files with 234 additions and 67 deletions

View File

@ -440,7 +440,7 @@
"array": [
0,
0,
209.73151519075364,
216.05530045313827,
0,
0,
0,

View File

@ -22,7 +22,7 @@ cc.Class({
if (!self.mapScriptIns) return;
if (!self.mapScriptIns.selfPlayerInfo) return;
if (!self.mapScriptIns.playerRichInfoDict) return;
const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict[self.mapScriptIns.selfPlayerInfo.id];
const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict.get(self.mapScriptIns.selfPlayerInfo.id);
if (!selfPlayerRichInfo) return;
const selfPlayerNode = selfPlayerRichInfo.node;
if (!selfPlayerNode) return;

View File

@ -126,7 +126,7 @@ cc.Class({
},
maxChasingRenderFramesPerUpdate: {
type: cc.Integer,
default: 5
default: 10
},
},
@ -565,6 +565,8 @@ cc.Class({
self.onBattleStarted(rdf);
return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_READDED_AND_ACKED:
// [WARNING] The "frameId" from server could be quite fast-forwarding, don't assign it in other cases.
self.renderFrameId = frameId;
self.lastAllConfirmedRenderFrameId = frameId;
self.onBattleReadyToStart(rdf.playerMetas, true);
self.onBattleStarted(rdf);
@ -763,8 +765,8 @@ cc.Class({
newPlayerNode.getComponent("SelfPlayer").mapNode = self.node;
const currentSelfColliderCircle = newPlayerNode.getComponent(cc.CircleCollider);
const newPlayerColliderLatest = self.latestCollisionSys.createCircle(x, y, currentSelfColliderCircle);
const newPlayerColliderChaser = self.chaserCollisionSys.createCircle(x, y, currentSelfColliderCircle);
const newPlayerColliderLatest = self.latestCollisionSys.createCircle(x, y, currentSelfColliderCircle.radius);
const newPlayerColliderChaser = self.chaserCollisionSys.createCircle(x, y, currentSelfColliderCircle.radius);
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
self.latestCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderLatest);
self.chaserCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderChaser);
@ -819,11 +821,6 @@ cc.Class({
} catch (err) {
console.error("Error during Map.update", err);
} finally {
// Update camera to track selfPlayer.
if (null != self.ctrl) {
self.ctrl.justifyMapNodePosAndScale(self.ctrl.linearSpeedBase, self.ctrl.zoomingSpeedBase);
}
// Update countdown
if (null != self.countdownNanos) {
self.countdownNanos -= self.rollbackEstimatedDt*1000000000;
@ -1050,7 +1047,7 @@ cc.Class({
const player = renderFrame.players[playerId];
const encodedInput = inputList[joinIndex-1];
const decodedInput = self.ctrl.decodeDirection(encodedInput);
const baseChange = player.speed*self.rollbackEstimatedDt;
const baseChange = player.speed*self.rollbackEstimatedDt*decodedInput.speedFactor;
playerCollider.x += baseChange*decodedInput.dx;
playerCollider.y += baseChange*decodedInput.dy;
/*
@ -1063,8 +1060,9 @@ cc.Class({
collisionSys.update();
const result = collisionSys.createResult(); // Can I reuse a "self.latestCollisionSysResult" object throughout the whole battle?
self.playerRichInfoDict.forEach((playerRichInfo, playerId) => {
const joinIndex = playerRichInfo.joinIndex;
// [WARNING] Traverse in the order of joinIndices to guarantee determinism.
for (let i in self.playerRichInfoArr) {
const joinIndex = parseInt(i) + 1;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
const potentials = playerCollider.potentials();
@ -1075,7 +1073,7 @@ cc.Class({
playerCollider.x -= result.overlap * result.overlap_x;
playerCollider.y -= result.overlap * result.overlap_y;
}
});
}
}
return self._createRoomDownsyncFrameLocally(renderFrameIdEd, collisionSys, collisionSysMap);
@ -1101,6 +1099,10 @@ cc.Class({
nodeAndScriptIns[1].showArrowTipNode();
}
}
self.playerRichInfoArr = new Array(self.playerRichInfoDict.size);
self.playerRichInfoDict.forEach((playerRichInfo, playerId) => {
self.playerRichInfoArr[playerRichInfo.joinIndex-1] = playerRichInfo;
});
},
_stringifyRecentInputCache(usefullOutput) {

View File

@ -1,19 +1,24 @@
window.DIRECTION_DECODER = [
[0, 0],
[0, +1],
[0, -1],
[+2, 0],
[-2, 0],
[+2, +1],
[-2, -1],
[+2, -1],
[-2, +1],
[+2, 0],
[-2, 0],
[0, +1],
[0, -1],
[0, 0, null],
[0, +1, null],
[0, -1, null],
[+2, 0, null],
[-2, 0, null],
[+2, +1, null],
[-2, -1, null],
[+2, -1, null],
[-2, +1, null],
[+2, 0, null],
[-2, 0, null],
[0, +1, null],
[0, -1, null],
];
for (let k in window.DIRECTION_DECODER) {
const length = Math.sqrt(window.DIRECTION_DECODER[k][0]*window.DIRECTION_DECODER[k][0] + window.DIRECTION_DECODER[k][1]*window.DIRECTION_DECODER[k][1]);
window.DIRECTION_DECODER[k][2] = (0 == length ? 0 : (1.0/length));
}
cc.Class({
extends: cc.Component,
properties: {
@ -114,43 +119,6 @@ cc.Class({
this.initialized = true;
},
justifyMapNodePosAndScale(linearSpeedBase, zoomingSpeedBase) {
const self = this;
if (false == self.mapScriptIns._inputControlEnabled) return;
if (null != self._cachedMapNodePosTarget) {
while (self.maxMovingBufferLength < self._cachedMapNodePosTarget.length) {
self._cachedMapNodePosTarget.shift();
}
if (0 < self._cachedMapNodePosTarget.length && 0 == self.mapNode.getNumberOfRunningActions()) {
const nextMapNodePosTarget = self._cachedMapNodePosTarget.shift();
const linearSpeed = linearSpeedBase;
const finalDiffVec = nextMapNodePosTarget.pos.sub(self.mapNode.position);
const finalDiffVecMag = finalDiffVec.mag();
if (self.linearMovingEps > finalDiffVecMag) {
// Jittering.
// cc.log("Map node moving by finalDiffVecMag == %s is just jittering.", finalDiffVecMag);
return;
}
const durationSeconds = finalDiffVecMag / linearSpeed;
cc.log("Map node moving to %o in %s/%s == %s seconds.", nextMapNodePosTarget.pos, finalDiffVecMag, linearSpeed, durationSeconds);
const bufferedTargetPos = cc.v2(nextMapNodePosTarget.pos.x, nextMapNodePosTarget.pos.y);
self.mapNode.runAction(cc.sequence(
cc.moveTo(durationSeconds, bufferedTargetPos),
cc.callFunc(() => {
if (self._isMapOverMoved(self.mapNode.position)) {
self.mapNode.setPosition(bufferedTargetPos);
}
}, self)
));
}
}
if (null != self._cachedZoomRawTarget && false == self._cachedZoomRawTarget.processed) {
cc.log(`Processing self._cachedZoomRawTarget == ${self._cachedZoomRawTarget}`);
self._cachedZoomRawTarget.processed = true;
self.mapNode.setScale(self._cachedZoomRawTarget.scale);
}
},
_initTouchEvent() {
const self = this;
const translationListenerNode = (self.translationListenerNode ? self.translationListenerNode : self.mapNode);
@ -377,7 +345,8 @@ cc.Class({
}
return {
dx: mapped[0],
dy: mapped[1]
dy: mapped[1],
speedFactor: mapped[2],
}
},

File diff suppressed because one or more lines are too long