mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
Improvements on using integer positioning.
This commit is contained in:
parent
e5ed8124e8
commit
901b189c5a
@ -60,36 +60,17 @@ const (
|
|||||||
MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED = -2
|
MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED = -2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These directions are chosen such that when speed is changed to "(speedX+delta, speedY+delta)" for any of them, the direction is unchanged.
|
||||||
var DIRECTION_DECODER = [][]int32{
|
var DIRECTION_DECODER = [][]int32{
|
||||||
{0, 0},
|
{0, 0},
|
||||||
{0, +1},
|
{0, +2},
|
||||||
{0, -1},
|
{0, -2},
|
||||||
{+2, 0},
|
{+2, 0},
|
||||||
{-2, 0},
|
{-2, 0},
|
||||||
{+2, +1},
|
{+1, +1},
|
||||||
{-2, -1},
|
{-1, -1},
|
||||||
{+2, -1},
|
{+1, -1},
|
||||||
{-2, +1},
|
{-1, +1},
|
||||||
{+2, 0},
|
|
||||||
{-2, 0},
|
|
||||||
{0, +1},
|
|
||||||
{0, -1},
|
|
||||||
}
|
|
||||||
|
|
||||||
var DIRECTION_DECODER_INVERSE_LENGTH = []float64{
|
|
||||||
0.0,
|
|
||||||
1.0,
|
|
||||||
1.0,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0.44, // Actually it should be "0.4472", but truncated for better precision sync as well as a reduction of speed in diagonal direction
|
|
||||||
0.44,
|
|
||||||
0.44,
|
|
||||||
0.44,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
1.0,
|
|
||||||
1.0,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoomBattleState struct {
|
type RoomBattleState struct {
|
||||||
@ -802,7 +783,7 @@ func (pR *Room) OnDismissed() {
|
|||||||
// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference.
|
// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference.
|
||||||
pR.WorldToVirtualGridRatio = float64(10)
|
pR.WorldToVirtualGridRatio = float64(10)
|
||||||
pR.VirtualGridToWorldRatio = float64(1.0) / pR.WorldToVirtualGridRatio // this is a one-off computation, should avoid division in iterations
|
pR.VirtualGridToWorldRatio = float64(1.0) / pR.WorldToVirtualGridRatio // this is a one-off computation, should avoid division in iterations
|
||||||
pR.PlayerDefaultSpeed = int32(3 * pR.WorldToVirtualGridRatio) // Hardcoded in virtual grids per frame
|
pR.PlayerDefaultSpeed = 10 // Hardcoded in virtual grids per frame
|
||||||
pR.Players = make(map[int32]*Player)
|
pR.Players = make(map[int32]*Player)
|
||||||
pR.PlayersArr = make([]*Player, pR.Capacity)
|
pR.PlayersArr = make([]*Player, pR.Capacity)
|
||||||
pR.CollisionSysMap = make(map[int32]*resolv.Object)
|
pR.CollisionSysMap = make(map[int32]*resolv.Object)
|
||||||
@ -1209,24 +1190,37 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
|
|
||||||
inputList := delayedInputFrame.InputList
|
inputList := delayedInputFrame.InputList
|
||||||
// Ordered by joinIndex to guarantee determinism
|
// Ordered by joinIndex to guarantee determinism
|
||||||
|
// Move players according to inputs
|
||||||
for _, player := range pR.PlayersArr {
|
for _, player := range pR.PlayersArr {
|
||||||
joinIndex := player.JoinIndex
|
joinIndex := player.JoinIndex
|
||||||
encodedInput := inputList[joinIndex-1]
|
encodedInput := inputList[joinIndex-1]
|
||||||
decodedInput := DIRECTION_DECODER[encodedInput]
|
decodedInput := DIRECTION_DECODER[encodedInput]
|
||||||
decodedInputSpeedFactor := DIRECTION_DECODER_INVERSE_LENGTH[encodedInput]
|
player.Dir.Dx = decodedInput[0]
|
||||||
if 0.0 == decodedInputSpeedFactor {
|
player.Dir.Dy = decodedInput[1]
|
||||||
|
if 0 == decodedInput[0] && 0 == decodedInput[1] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
baseChange := float64(player.Speed) * pR.VirtualGridToWorldRatio * decodedInputSpeedFactor
|
|
||||||
oldDx, oldDy := baseChange*float64(decodedInput[0]), baseChange*float64(decodedInput[1])
|
|
||||||
dx, dy := oldDx, oldDy
|
|
||||||
|
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
||||||
// Reset playerCollider position from the "virtual grid position"
|
|
||||||
playerCollider.X, playerCollider.Y = pR.virtualGridToPlayerColliderPos(player.VirtualGridX, player.VirtualGridY, player)
|
|
||||||
|
|
||||||
if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
|
// Reset playerCollider position from the "virtual grid position"
|
||||||
|
newVx := (player.VirtualGridX + (decodedInput[0] + decodedInput[0]*player.Speed))
|
||||||
|
newVy := (player.VirtualGridY + (decodedInput[1] + decodedInput[1]*player.Speed))
|
||||||
|
playerCollider.X, playerCollider.Y = pR.virtualGridToPlayerColliderPos(newVx, newVy, player)
|
||||||
|
|
||||||
|
// Update in "collision space"
|
||||||
|
playerCollider.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle pushbacks upon collision
|
||||||
|
for _, player := range pR.PlayersArr {
|
||||||
|
joinIndex := player.JoinIndex
|
||||||
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||||
|
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
||||||
|
oldDx, oldDy := float64(0), float64(0)
|
||||||
|
dx, dy := oldDx, oldDy
|
||||||
|
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)
|
||||||
@ -1242,16 +1236,15 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
playerCollider.X += dx
|
playerCollider.X += dx
|
||||||
playerCollider.Y += dy
|
playerCollider.Y += dy
|
||||||
|
|
||||||
// Update in "collision space"
|
// Update again in "collision space"
|
||||||
playerCollider.Update()
|
playerCollider.Update()
|
||||||
|
|
||||||
player.Dir.Dx = decodedInput[0]
|
// Update "virtual grid position"
|
||||||
player.Dir.Dy = decodedInput[1]
|
|
||||||
player.VirtualGridX, player.VirtualGridY = pR.playerColliderAnchorToVirtualGridPos(playerCollider.X, playerCollider.Y, player)
|
player.VirtualGridX, player.VirtualGridY = pR.playerColliderAnchorToVirtualGridPos(playerCollider.X, playerCollider.Y, player)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pbPlayers := toPbPlayers(pR.Players)
|
pbPlayers := toPbPlayers(pR.Players)
|
||||||
|
|
||||||
newRenderFrame := RoomDownsyncFrame{
|
newRenderFrame := RoomDownsyncFrame{
|
||||||
Id: collisionSysRenderFrameId + 1,
|
Id: collisionSysRenderFrameId + 1,
|
||||||
@ -1295,13 +1288,15 @@ func (pR *Room) printBarrier(barrierCollider *resolv.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) worldToVirtualGridPos(wx, wy float64) (int32, int32) {
|
func (pR *Room) worldToVirtualGridPos(wx, wy float64) (int32, int32) {
|
||||||
|
// [WARNING] Introduces loss of precision!
|
||||||
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
|
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
|
||||||
var virtualGridX int32 = int32(wx * pR.WorldToVirtualGridRatio)
|
var virtualGridX int32 = int32(math.Round(wx * pR.WorldToVirtualGridRatio))
|
||||||
var virtualGridY int32 = int32(wy * pR.WorldToVirtualGridRatio)
|
var virtualGridY int32 = int32(math.Round(wy * pR.WorldToVirtualGridRatio))
|
||||||
return virtualGridX, virtualGridY
|
return virtualGridX, virtualGridY
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) virtualGridToWorldPos(vx, vy int32) (float64, float64) {
|
func (pR *Room) virtualGridToWorldPos(vx, vy int32) (float64, float64) {
|
||||||
|
// No loss of precision
|
||||||
var wx float64 = float64(vx) * pR.VirtualGridToWorldRatio
|
var wx float64 = float64(vx) * pR.VirtualGridToWorldRatio
|
||||||
var wy float64 = float64(vy) * pR.VirtualGridToWorldRatio
|
var wy float64 = float64(vy) * pR.VirtualGridToWorldRatio
|
||||||
return wx, wy
|
return wx, wy
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
216.67592045656244,
|
378.4531014537997,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -44,14 +44,14 @@ module.export = cc.Class({
|
|||||||
onLoad() {
|
onLoad() {
|
||||||
const self = this;
|
const self = this;
|
||||||
self.clips = {
|
self.clips = {
|
||||||
'01': 'Top',
|
'02': 'Top',
|
||||||
'0-1': 'Bottom',
|
'0-2': 'Bottom',
|
||||||
'-20': 'Left',
|
'-20': 'Left',
|
||||||
'20': 'Right',
|
'20': 'Right',
|
||||||
'-21': 'TopLeft',
|
'-11': 'TopLeft',
|
||||||
'21': 'TopRight',
|
'11': 'TopRight',
|
||||||
'-2-1': 'BottomLeft',
|
'-1-1': 'BottomLeft',
|
||||||
'2-1': 'BottomRight'
|
'1-1': 'BottomRight'
|
||||||
};
|
};
|
||||||
const canvasNode = self.mapNode.parent;
|
const canvasNode = self.mapNode.parent;
|
||||||
self.mapIns = self.mapNode.getComponent("Map");
|
self.mapIns = self.mapNode.getComponent("Map");
|
||||||
|
@ -111,7 +111,7 @@ cc.Class({
|
|||||||
type: cc.Integer,
|
type: cc.Integer,
|
||||||
default: 4 // implies (renderFrameIdLagTolerance >> inputScaleFrames) count of inputFrameIds
|
default: 4 // implies (renderFrameIdLagTolerance >> inputScaleFrames) count of inputFrameIds
|
||||||
},
|
},
|
||||||
teleportEps1D: {
|
jigglingEps1D: {
|
||||||
type: cc.Float,
|
type: cc.Float,
|
||||||
default: 1e-3
|
default: 1e-3
|
||||||
},
|
},
|
||||||
@ -749,7 +749,8 @@ cc.Class({
|
|||||||
newPlayerNode.setPosition(cc.v2(wpos[0], wpos[1]));
|
newPlayerNode.setPosition(cc.v2(wpos[0], wpos[1]));
|
||||||
newPlayerNode.getComponent("SelfPlayer").mapNode = self.node;
|
newPlayerNode.getComponent("SelfPlayer").mapNode = self.node;
|
||||||
const cpos = self.virtualGridToPlayerColliderPos(vx, vy, playerRichInfo);
|
const cpos = self.virtualGridToPlayerColliderPos(vx, vy, playerRichInfo);
|
||||||
const d = playerRichInfo.colliderRadius*2, x0 = cpos[0],
|
const d = playerRichInfo.colliderRadius * 2,
|
||||||
|
x0 = cpos[0],
|
||||||
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]];
|
||||||
|
|
||||||
@ -990,6 +991,23 @@ cc.Class({
|
|||||||
rdf.id > self.lastAllConfirmedRenderFrameId
|
rdf.id > self.lastAllConfirmedRenderFrameId
|
||||||
) {
|
) {
|
||||||
// We got a more up-to-date "all-confirmed-render-frame".
|
// We got a more up-to-date "all-confirmed-render-frame".
|
||||||
|
let predictedRdf = self.recentRenderCache.getByFrameId(rdf.id);
|
||||||
|
if (null != predictedRdf) {
|
||||||
|
let renderFrameCorrectlyPredicted = true;
|
||||||
|
for (let playerId in predictedRdf.players) {
|
||||||
|
const predictedPlayer = predictedRdf.players[playerId];
|
||||||
|
const confirmedPlayer = rdf.players[playerId];
|
||||||
|
if (predictedPlayer.virtualGridX != confirmedPlayer.virtualGridX || predictedPlayer.virtualGridY != confirmedPlayer.virtualGridY) {
|
||||||
|
renderFrameCorrectlyPredicted = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!renderFrameCorrectlyPredicted) {
|
||||||
|
// TODO: Can I also check whether the applied inputFrame on predictedRdf was "correctly predicted"? If it wasn't then a mismatch of positions is expected.
|
||||||
|
console.warn("render frame was incorrectly predicted\npredictedRdf=" + predictedRdf.toString() + "\nrdf=" + rdf.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
self.lastAllConfirmedRenderFrameId = rdf.id;
|
self.lastAllConfirmedRenderFrameId = rdf.id;
|
||||||
if (rdf.id > self.chaserRenderFrameId) {
|
if (rdf.id > self.chaserRenderFrameId) {
|
||||||
// it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId"
|
// it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId"
|
||||||
@ -1008,13 +1026,14 @@ cc.Class({
|
|||||||
const wpos = self.virtualGridToWorldPos(immediatePlayerInfo.virtualGridX, immediatePlayerInfo.virtualGridY);
|
const wpos = self.virtualGridToWorldPos(immediatePlayerInfo.virtualGridX, immediatePlayerInfo.virtualGridY);
|
||||||
const dx = (wpos[0] - playerRichInfo.node.x);
|
const dx = (wpos[0] - playerRichInfo.node.x);
|
||||||
const dy = (wpos[1] - playerRichInfo.node.y);
|
const dy = (wpos[1] - playerRichInfo.node.y);
|
||||||
const justJiggling = (self.teleportEps1D >= Math.abs(dx) && self.teleportEps1D >= Math.abs(dy));
|
const justJiggling = (self.jigglingEps1D >= Math.abs(dx) && self.jigglingEps1D >= Math.abs(dy));
|
||||||
if (!justJiggling) {
|
if (!justJiggling) {
|
||||||
console.log("@renderFrameId=" + self.renderFrameId + ", teleporting playerId=" + playerId + ": '(" + playerRichInfo.node.x + ", " + playerRichInfo.node.y, ")' to '(" + wpos[0] + ", " + wpos[1] + ")'");
|
|
||||||
playerRichInfo.node.setPosition(wpos[0], wpos[1]);
|
playerRichInfo.node.setPosition(wpos[0], wpos[1]);
|
||||||
|
playerRichInfo.virtualGridX = immediatePlayerInfo.virtualGridX;
|
||||||
|
playerRichInfo.virtualGridY = immediatePlayerInfo.virtualGridY;
|
||||||
|
playerRichInfo.scriptIns.scheduleNewDirection(immediatePlayerInfo.dir, false);
|
||||||
|
playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed);
|
||||||
}
|
}
|
||||||
playerRichInfo.scriptIns.scheduleNewDirection(immediatePlayerInfo.dir, false);
|
|
||||||
playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1062,18 +1081,20 @@ cc.Class({
|
|||||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
const player = renderFrame.players[playerId];
|
const player = renderFrame.players[playerId];
|
||||||
|
|
||||||
|
const encodedInput = inputList[joinIndex - 1];
|
||||||
|
const decodedInput = self.ctrl.decodeDirection(encodedInput);
|
||||||
|
if (0 == decodedInput.dx && 0 == decodedInput.dy) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
const cpos = self.virtualGridToPlayerColliderPos(player.virtualGridX, player.virtualGridY, self.playerRichInfoArr[j]);
|
const newVx = player.virtualGridX + (decodedInput.dx + player.speed * decodedInput.dx);
|
||||||
playerCollider.x = cpos[0];
|
const newVy = player.virtualGridY + (decodedInput.dy + player.speed * decodedInput.dy);
|
||||||
playerCollider.y = cpos[1];
|
const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[j]);
|
||||||
|
playerCollider.x = newCpos[0];
|
||||||
const encodedInput = inputList[joinIndex - 1];
|
playerCollider.y = newCpos[1];
|
||||||
const decodedInput = self.ctrl.decodeDirection(encodedInput);
|
|
||||||
const baseChange = player.speed * self.virtualGridToWorldRatio * decodedInput.speedFactor;
|
|
||||||
playerCollider.x += baseChange * decodedInput.dx;
|
|
||||||
playerCollider.y += baseChange * decodedInput.dy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
collisionSys.update();
|
collisionSys.update();
|
||||||
@ -1154,14 +1175,16 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
worldToVirtualGridPos(x, y) {
|
worldToVirtualGridPos(x, y) {
|
||||||
|
// [WARNING] Introduces loss of precision!
|
||||||
const self = this;
|
const self = this;
|
||||||
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
|
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
|
||||||
let virtualGridX = parseInt(x * self.worldToVirtualGridRatio);
|
let virtualGridX = Math.round(x * self.worldToVirtualGridRatio);
|
||||||
let virtualGridY = parseInt(y * self.worldToVirtualGridRatio);
|
let virtualGridY = Math.round(y * self.worldToVirtualGridRatio);
|
||||||
return [virtualGridX, virtualGridY];
|
return [virtualGridX, virtualGridY];
|
||||||
},
|
},
|
||||||
|
|
||||||
virtualGridToWorldPos(vx, vy) {
|
virtualGridToWorldPos(vx, vy) {
|
||||||
|
// No loss of precision
|
||||||
const self = this;
|
const self = this;
|
||||||
let wx = parseFloat(vx) * self.virtualGridToWorldRatio;
|
let wx = parseFloat(vx) * self.virtualGridToWorldRatio;
|
||||||
let wy = parseFloat(vy) * self.virtualGridToWorldRatio;
|
let wy = parseFloat(vy) * self.virtualGridToWorldRatio;
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
window.DIRECTION_DECODER = [
|
window.DIRECTION_DECODER = [
|
||||||
// The 3rd value matches low-precision constants in backend.
|
// The 3rd value matches low-precision constants in backend.
|
||||||
[0, 0, 0.0],
|
[0, 0],
|
||||||
[0, +1, 1.0],
|
[0, +2],
|
||||||
[0, -1, 1.0],
|
[0, -2],
|
||||||
[+2, 0, 0.5],
|
[+2, 0],
|
||||||
[-2, 0, 0.5],
|
[-2, 0],
|
||||||
[+2, +1, 0.44],
|
[+1, +1],
|
||||||
[-2, -1, 0.44],
|
[-1, -1],
|
||||||
[+2, -1, 0.44],
|
[+1, -1],
|
||||||
[-2, +1, 0.44],
|
[-1, +1],
|
||||||
[+2, 0, 0.5],
|
|
||||||
[-2, 0, 0.5],
|
|
||||||
[0, +1, 1.0],
|
|
||||||
[0, -1, 1.0],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
cc.Class({
|
cc.Class({
|
||||||
@ -40,11 +36,11 @@ cc.Class({
|
|||||||
type: cc.Float
|
type: cc.Float
|
||||||
},
|
},
|
||||||
magicLeanLowerBound: {
|
magicLeanLowerBound: {
|
||||||
default: 0.414, // Tangent of (PI/8).
|
default: 0.9, // Tangent of (PI/4) is 1.0.
|
||||||
type: cc.Float
|
type: cc.Float
|
||||||
},
|
},
|
||||||
magicLeanUpperBound: {
|
magicLeanUpperBound: {
|
||||||
default: 2.414, // Tangent of (3*PI/8).
|
default: 1.1,
|
||||||
type: cc.Float
|
type: cc.Float
|
||||||
},
|
},
|
||||||
// For joystick ends.
|
// For joystick ends.
|
||||||
@ -117,8 +113,8 @@ cc.Class({
|
|||||||
|
|
||||||
_initTouchEvent() {
|
_initTouchEvent() {
|
||||||
const self = this;
|
const self = this;
|
||||||
const translationListenerNode = (self.translationListenerNode ? self.translationListenerNode : self.mapNode);
|
const translationListenerNode = (self.translationListenerNode ? self.translationListenerNode : self.mapNode);
|
||||||
const zoomingListenerNode = (self.zoomingListenerNode ? self.zoomingListenerNode : self.mapNode);
|
const zoomingListenerNode = (self.zoomingListenerNode ? self.zoomingListenerNode : self.mapNode);
|
||||||
|
|
||||||
translationListenerNode.on(cc.Node.EventType.TOUCH_START, function(event) {
|
translationListenerNode.on(cc.Node.EventType.TOUCH_START, function(event) {
|
||||||
self._touchStartEvent(event);
|
self._touchStartEvent(event);
|
||||||
@ -132,7 +128,7 @@ cc.Class({
|
|||||||
translationListenerNode.on(cc.Node.EventType.TOUCH_CANCEL, function(event) {
|
translationListenerNode.on(cc.Node.EventType.TOUCH_CANCEL, function(event) {
|
||||||
self._touchEndEvent(event);
|
self._touchEndEvent(event);
|
||||||
});
|
});
|
||||||
translationListenerNode.inTouchPoints = new Map();
|
translationListenerNode.inTouchPoints = new Map();
|
||||||
|
|
||||||
zoomingListenerNode.on(cc.Node.EventType.TOUCH_START, function(event) {
|
zoomingListenerNode.on(cc.Node.EventType.TOUCH_START, function(event) {
|
||||||
self._touchStartEvent(event);
|
self._touchStartEvent(event);
|
||||||
@ -146,7 +142,7 @@ cc.Class({
|
|||||||
zoomingListenerNode.on(cc.Node.EventType.TOUCH_CANCEL, function(event) {
|
zoomingListenerNode.on(cc.Node.EventType.TOUCH_CANCEL, function(event) {
|
||||||
self._touchEndEvent(event);
|
self._touchEndEvent(event);
|
||||||
});
|
});
|
||||||
zoomingListenerNode.inTouchPoints = new Map();
|
zoomingListenerNode.inTouchPoints = new Map();
|
||||||
},
|
},
|
||||||
|
|
||||||
_isMapOverMoved(mapTargetPos) {
|
_isMapOverMoved(mapTargetPos) {
|
||||||
@ -155,7 +151,7 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_touchStartEvent(event) {
|
_touchStartEvent(event) {
|
||||||
const theListenerNode = event.target;
|
const theListenerNode = event.target;
|
||||||
for (let touch of event._touches) {
|
for (let touch of event._touches) {
|
||||||
theListenerNode.inTouchPoints.set(touch._id, touch);
|
theListenerNode.inTouchPoints.set(touch._id, touch);
|
||||||
}
|
}
|
||||||
@ -165,12 +161,12 @@ cc.Class({
|
|||||||
if (ALL_MAP_STATES.VISUAL != this.mapScriptIns.state) {
|
if (ALL_MAP_STATES.VISUAL != this.mapScriptIns.state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const theListenerNode = event.target;
|
const theListenerNode = event.target;
|
||||||
const linearScaleFacBase = this.linearScaleFacBase; // Not used yet.
|
const linearScaleFacBase = this.linearScaleFacBase; // Not used yet.
|
||||||
if (1 != theListenerNode.inTouchPoints.size) {
|
if (1 != theListenerNode.inTouchPoints.size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!theListenerNode.inTouchPoints.has(event.currentTouch._id)) {
|
if (!theListenerNode.inTouchPoints.has(event.currentTouch._id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const diffVec = event.currentTouch._point.sub(event.currentTouch._startPoint);
|
const diffVec = event.currentTouch._point.sub(event.currentTouch._startPoint);
|
||||||
@ -189,9 +185,9 @@ cc.Class({
|
|||||||
if (ALL_MAP_STATES.VISUAL != this.mapScriptIns.state) {
|
if (ALL_MAP_STATES.VISUAL != this.mapScriptIns.state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const theListenerNode = event.target;
|
const theListenerNode = event.target;
|
||||||
if (2 != theListenerNode.inTouchPoints.size) {
|
if (2 != theListenerNode.inTouchPoints.size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (2 == event._touches.length) {
|
if (2 == event._touches.length) {
|
||||||
const firstTouch = event._touches[0];
|
const firstTouch = event._touches[0];
|
||||||
@ -219,13 +215,13 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
this.mainCamera.zoomRatio = targetScale;
|
this.mainCamera.zoomRatio = targetScale;
|
||||||
for (let child of this.mainCameraNode.children) {
|
for (let child of this.mainCameraNode.children) {
|
||||||
child.setScale(1/targetScale);
|
child.setScale(1 / targetScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_touchEndEvent(event) {
|
_touchEndEvent(event) {
|
||||||
const theListenerNode = event.target;
|
const theListenerNode = event.target;
|
||||||
do {
|
do {
|
||||||
if (!theListenerNode.inTouchPoints.has(event.currentTouch._id)) {
|
if (!theListenerNode.inTouchPoints.has(event.currentTouch._id)) {
|
||||||
break;
|
break;
|
||||||
@ -241,7 +237,7 @@ cc.Class({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle single-finger-click event.
|
// TODO: Handle single-finger-click event.
|
||||||
} while (false);
|
} while (false);
|
||||||
this.cachedStickHeadPosition = cc.v2(0.0, 0.0);
|
this.cachedStickHeadPosition = cc.v2(0.0, 0.0);
|
||||||
for (let touch of event._touches) {
|
for (let touch of event._touches) {
|
||||||
@ -266,16 +262,16 @@ cc.Class({
|
|||||||
encodedIdx: 0
|
encodedIdx: 0
|
||||||
};
|
};
|
||||||
if (Math.abs(continuousDx) < eps && Math.abs(continuousDy) < eps) {
|
if (Math.abs(continuousDx) < eps && Math.abs(continuousDy) < eps) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(continuousDx) < eps) {
|
if (Math.abs(continuousDx) < eps) {
|
||||||
ret.dx = 0;
|
ret.dx = 0;
|
||||||
if (0 < continuousDy) {
|
if (0 < continuousDy) {
|
||||||
ret.dy = +1; // up
|
ret.dy = +2; // up
|
||||||
ret.encodedIdx = 1;
|
ret.encodedIdx = 1;
|
||||||
} else {
|
} else {
|
||||||
ret.dy = -1; // down
|
ret.dy = -2; // down
|
||||||
ret.encodedIdx = 2;
|
ret.encodedIdx = 2;
|
||||||
}
|
}
|
||||||
} else if (Math.abs(continuousDy) < eps) {
|
} else if (Math.abs(continuousDy) < eps) {
|
||||||
@ -291,42 +287,42 @@ cc.Class({
|
|||||||
const criticalRatio = continuousDy / continuousDx;
|
const criticalRatio = continuousDy / continuousDx;
|
||||||
if (criticalRatio > this.magicLeanLowerBound && criticalRatio < this.magicLeanUpperBound) {
|
if (criticalRatio > this.magicLeanLowerBound && criticalRatio < this.magicLeanUpperBound) {
|
||||||
if (0 < continuousDx) {
|
if (0 < continuousDx) {
|
||||||
ret.dx = +2;
|
ret.dx = +1;
|
||||||
ret.dy = +1;
|
ret.dy = +1;
|
||||||
ret.encodedIdx = 5;
|
ret.encodedIdx = 5;
|
||||||
} else {
|
} else {
|
||||||
ret.dx = -2;
|
ret.dx = -1;
|
||||||
ret.dy = -1;
|
ret.dy = -1;
|
||||||
ret.encodedIdx = 6;
|
ret.encodedIdx = 6;
|
||||||
}
|
}
|
||||||
} else if (criticalRatio > -this.magicLeanUpperBound && criticalRatio < -this.magicLeanLowerBound) {
|
} else if (criticalRatio > -this.magicLeanUpperBound && criticalRatio < -this.magicLeanLowerBound) {
|
||||||
if (0 < continuousDx) {
|
if (0 < continuousDx) {
|
||||||
ret.dx = +2;
|
ret.dx = +1;
|
||||||
ret.dy = -1;
|
ret.dy = -1;
|
||||||
ret.encodedIdx = 7;
|
ret.encodedIdx = 7;
|
||||||
} else {
|
} else {
|
||||||
ret.dx = -2;
|
ret.dx = -1;
|
||||||
ret.dy = +1;
|
ret.dy = +1;
|
||||||
ret.encodedIdx = 8;
|
ret.encodedIdx = 8;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Math.abs(criticalRatio) < 1) {
|
if (Math.abs(criticalRatio) < 0.1) {
|
||||||
ret.dy = 0;
|
ret.dy = 0;
|
||||||
if (0 < continuousDx) {
|
if (0 < continuousDx) {
|
||||||
ret.dx = +2;
|
ret.dx = +2; // right
|
||||||
ret.encodedIdx = 9;
|
ret.encodedIdx = 3;
|
||||||
} else {
|
} else {
|
||||||
ret.dx = -2;
|
ret.dx = -2; // left
|
||||||
ret.encodedIdx = 10;
|
ret.encodedIdx = 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (Math.abs(criticalRatio) > 0.9) {
|
||||||
ret.dx = 0;
|
ret.dx = 0;
|
||||||
if (0 < continuousDy) {
|
if (0 < continuousDy) {
|
||||||
ret.dy = +1;
|
ret.dy = +2; // up
|
||||||
ret.encodedIdx = 11;
|
ret.encodedIdx = 1;
|
||||||
} else {
|
} else {
|
||||||
ret.dy = -1;
|
ret.dy = -2; // down
|
||||||
ret.encodedIdx = 12;
|
ret.encodedIdx = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,16 +333,15 @@ cc.Class({
|
|||||||
decodeDirection(encodedDirection) {
|
decodeDirection(encodedDirection) {
|
||||||
const mapped = window.DIRECTION_DECODER[encodedDirection];
|
const mapped = window.DIRECTION_DECODER[encodedDirection];
|
||||||
if (null == mapped) {
|
if (null == mapped) {
|
||||||
console.error("Unexpected encodedDirection = ", encodedDirection);
|
console.error("Unexpected encodedDirection = ", encodedDirection);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
dx: mapped[0],
|
dx: mapped[0],
|
||||||
dy: mapped[1],
|
dy: mapped[1],
|
||||||
speedFactor: mapped[2],
|
};
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDiscretizedDirection() {
|
getDiscretizedDirection() {
|
||||||
return this.discretizeDirection(this.cachedStickHeadPosition.x, this.cachedStickHeadPosition.y, this.joyStickEps);
|
return this.discretizeDirection(this.cachedStickHeadPosition.x, this.cachedStickHeadPosition.y, this.joyStickEps);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user