mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
Refactored backend for convenience of unit-testing.
This commit is contained in:
parent
901b189c5a
commit
f97ce22cef
@ -5,6 +5,7 @@ import (
|
|||||||
"battle_srv/common/utils"
|
"battle_srv/common/utils"
|
||||||
. "battle_srv/protos"
|
. "battle_srv/protos"
|
||||||
. "dnmshared"
|
. "dnmshared"
|
||||||
|
. "dnmshared/sharedprotos"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
@ -577,7 +578,7 @@ func (pR *Room) StartBattle() {
|
|||||||
pR.RenderFrameId++
|
pR.RenderFrameId++
|
||||||
elapsedInCalculation := (utils.UnixtimeNano() - stCalculation)
|
elapsedInCalculation := (utils.UnixtimeNano() - stCalculation)
|
||||||
if elapsedInCalculation > nanosPerFrame {
|
if elapsedInCalculation > nanosPerFrame {
|
||||||
Logger.Warn(fmt.Sprintf("SLOW FRAME! Elapsed time statistics: roomId=%v, room.RenderFrameId=%v, elapsedInCalculation=%v, dynamicsDuration=%v, nanosPerFrame=%v", pR.Id, pR.RenderFrameId, elapsedInCalculation, dynamicsDuration, nanosPerFrame))
|
Logger.Warn(fmt.Sprintf("SLOW FRAME! Elapsed time statistics: roomId=%v, room.RenderFrameId=%v, elapsedInCalculation=%v ns, dynamicsDuration=%v ns, expected nanosPerFrame=%v", pR.Id, pR.RenderFrameId, elapsedInCalculation, dynamicsDuration, nanosPerFrame))
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(nanosPerFrame - elapsedInCalculation))
|
time.Sleep(time.Duration(nanosPerFrame - elapsedInCalculation))
|
||||||
}
|
}
|
||||||
@ -783,7 +784,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 = 10 // 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)
|
||||||
@ -1175,7 +1176,13 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
||||||
|
|
||||||
for collisionSysRenderFrameId := fromRenderFrameId; collisionSysRenderFrameId < toRenderFrameId; collisionSysRenderFrameId++ {
|
for collisionSysRenderFrameId := fromRenderFrameId; collisionSysRenderFrameId < toRenderFrameId; collisionSysRenderFrameId++ {
|
||||||
|
currRenderFrameTmp := pR.RenderFrameBuffer.GetByFrameId(collisionSysRenderFrameId)
|
||||||
|
if nil == currRenderFrameTmp {
|
||||||
|
panic(fmt.Sprintf("collisionSysRenderFrameId=%v doesn't exist for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v)! RenderFrameBuffer=%v", collisionSysRenderFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, pR.RenderFrameBufferString()))
|
||||||
|
}
|
||||||
|
currRenderFrame := currRenderFrameTmp.(*RoomDownsyncFrame)
|
||||||
delayedInputFrameId := pR.ConvertToInputFrameId(collisionSysRenderFrameId, pR.InputDelayFrames)
|
delayedInputFrameId := pR.ConvertToInputFrameId(collisionSysRenderFrameId, pR.InputDelayFrames)
|
||||||
|
var delayedInputFrame *InputFrameDownsync = nil
|
||||||
if 0 <= delayedInputFrameId {
|
if 0 <= delayedInputFrameId {
|
||||||
if delayedInputFrameId > pR.LastAllConfirmedInputFrameId {
|
if delayedInputFrameId > pR.LastAllConfirmedInputFrameId {
|
||||||
panic(fmt.Sprintf("delayedInputFrameId=%v is not yet all-confirmed for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v) @ collisionSysRenderFrameId=%v! InputsBuffer=%v", delayedInputFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, collisionSysRenderFrameId, pR.InputsBufferString(false)))
|
panic(fmt.Sprintf("delayedInputFrameId=%v is not yet all-confirmed for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v) @ collisionSysRenderFrameId=%v! InputsBuffer=%v", delayedInputFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, collisionSysRenderFrameId, pR.InputsBufferString(false)))
|
||||||
@ -1187,75 +1194,105 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
delayedInputFrame := tmp.(*InputFrameDownsync)
|
delayedInputFrame := tmp.(*InputFrameDownsync)
|
||||||
// [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)
|
||||||
|
|
||||||
inputList := delayedInputFrame.InputList
|
|
||||||
// Ordered by joinIndex to guarantee determinism
|
|
||||||
// Move players according to inputs
|
|
||||||
for _, player := range pR.PlayersArr {
|
|
||||||
joinIndex := player.JoinIndex
|
|
||||||
encodedInput := inputList[joinIndex-1]
|
|
||||||
decodedInput := DIRECTION_DECODER[encodedInput]
|
|
||||||
player.Dir.Dx = decodedInput[0]
|
|
||||||
player.Dir.Dy = decodedInput[1]
|
|
||||||
if 0 == decodedInput[0] && 0 == decodedInput[1] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
|
||||||
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
for _, obj := range collision.Objects {
|
|
||||||
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
|
||||||
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))
|
|
||||||
dx -= pushbackX
|
|
||||||
dy -= pushbackY
|
|
||||||
} 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)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
playerCollider.X += dx
|
|
||||||
playerCollider.Y += dy
|
|
||||||
|
|
||||||
// Update again in "collision space"
|
|
||||||
playerCollider.Update()
|
|
||||||
|
|
||||||
// Update "virtual grid position"
|
|
||||||
player.VirtualGridX, player.VirtualGridY = pR.playerColliderAnchorToVirtualGridPos(playerCollider.X, playerCollider.Y, player)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pbPlayers := toPbPlayers(pR.Players)
|
nextRenderFrame := pR.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, pR.CollisionSysMap)
|
||||||
|
// Update in the latest player pointers
|
||||||
newRenderFrame := RoomDownsyncFrame{
|
for playerId, playerDownsync := range nextRenderFrame.Players {
|
||||||
Id: collisionSysRenderFrameId + 1,
|
pR.Players[playerId].VirtualGridX = playerDownsync.VirtualGridX
|
||||||
Players: pbPlayers,
|
pR.Players[playerId].VirtualGridY = playerDownsync.VirtualGridY
|
||||||
CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*pR.RollbackEstimatedDtNanos),
|
pR.Players[playerId].Dir.Dx = playerDownsync.Dir.Dx
|
||||||
|
pR.Players[playerId].Dir.Dy = playerDownsync.Dir.Dy
|
||||||
}
|
}
|
||||||
pR.RenderFrameBuffer.Put(&newRenderFrame)
|
pR.RenderFrameBuffer.Put(nextRenderFrame)
|
||||||
pR.CurDynamicsRenderFrameId++
|
pR.CurDynamicsRenderFrameId++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Write unit-test for this function to compare with its frontend counter part
|
||||||
|
func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame *InputFrameDownsync, currRenderFrame *RoomDownsyncFrame, collisionSysMap map[int32]*resolv.Object) *RoomDownsyncFrame {
|
||||||
|
nextRenderFramePlayers := make(map[int32]*PlayerDownsync, pR.Capacity)
|
||||||
|
// Make a copy first
|
||||||
|
for playerId, currPlayerDownsync := range currRenderFrame.Players {
|
||||||
|
nextRenderFramePlayers[playerId] = &PlayerDownsync{
|
||||||
|
Id: playerId,
|
||||||
|
VirtualGridX: currPlayerDownsync.VirtualGridX,
|
||||||
|
VirtualGridY: currPlayerDownsync.VirtualGridY,
|
||||||
|
Dir: &Direction{
|
||||||
|
Dx: currPlayerDownsync.Dir.Dx,
|
||||||
|
Dy: currPlayerDownsync.Dir.Dy,
|
||||||
|
},
|
||||||
|
Speed: currPlayerDownsync.Speed,
|
||||||
|
BattleState: currPlayerDownsync.BattleState,
|
||||||
|
Score: currPlayerDownsync.Score,
|
||||||
|
Removed: currPlayerDownsync.Removed,
|
||||||
|
JoinIndex: currPlayerDownsync.JoinIndex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toRet := &RoomDownsyncFrame{
|
||||||
|
Id: currRenderFrame.Id + 1,
|
||||||
|
Players: nextRenderFramePlayers,
|
||||||
|
CountdownNanos: (pR.BattleDurationNanos - int64(currRenderFrame.Id)*pR.RollbackEstimatedDtNanos),
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil != delayedInputFrame {
|
||||||
|
inputList := delayedInputFrame.InputList
|
||||||
|
// Ordered by joinIndex to guarantee determinism?
|
||||||
|
// Move players according to inputs
|
||||||
|
for joinIndex := 1; joinIndex <= pR.Capacity; joinIndex++ {
|
||||||
|
player := pR.PlayersArr[joinIndex-1]
|
||||||
|
playerId := player.Id
|
||||||
|
currPlayerDownsync := currRenderFrame.Players[playerId]
|
||||||
|
encodedInput := inputList[joinIndex-1]
|
||||||
|
decodedInput := DIRECTION_DECODER[encodedInput]
|
||||||
|
newVx := (currPlayerDownsync.VirtualGridX + (decodedInput[0] + decodedInput[0]*currPlayerDownsync.Speed))
|
||||||
|
newVy := (currPlayerDownsync.VirtualGridY + (decodedInput[1] + decodedInput[1]*currPlayerDownsync.Speed))
|
||||||
|
// Reset playerCollider position from the "virtual grid position"
|
||||||
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + currPlayerDownsync.JoinIndex
|
||||||
|
playerCollider := collisionSysMap[collisionPlayerIndex]
|
||||||
|
playerCollider.X, playerCollider.Y = pR.virtualGridToPlayerColliderPos(newVx, newVy, player)
|
||||||
|
playerCollider.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle pushbacks upon collision after all movements treated as simultaneous
|
||||||
|
for joinIndex := 1; joinIndex <= pR.Capacity; joinIndex++ {
|
||||||
|
player := pR.PlayersArr[joinIndex-1]
|
||||||
|
playerId := player.Id
|
||||||
|
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + player.JoinIndex
|
||||||
|
playerCollider := 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)
|
||||||
|
for _, obj := range collision.Objects {
|
||||||
|
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
|
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))
|
||||||
|
dx -= pushbackX
|
||||||
|
dy -= pushbackY
|
||||||
|
} 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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playerCollider.X += dx
|
||||||
|
playerCollider.Y += dy
|
||||||
|
|
||||||
|
// Update again in "collision space"
|
||||||
|
playerCollider.Update()
|
||||||
|
|
||||||
|
// Update "virtual grid position"
|
||||||
|
newVx, newVy := pR.playerColliderAnchorToVirtualGridPos(playerCollider.X, playerCollider.Y, player)
|
||||||
|
nextRenderFramePlayers[playerId].VirtualGridX = newVx
|
||||||
|
nextRenderFramePlayers[playerId].VirtualGridY = newVy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toRet
|
||||||
|
}
|
||||||
|
|
||||||
func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
|
func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
|
||||||
return 0 == (inputFrameId % 10)
|
return 0 == (inputFrameId % 10)
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
378.4531014537997,
|
372.39092362730867,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -585,7 +585,7 @@ cc.Class({
|
|||||||
if (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START < rdf.id && window.RING_BUFF_CONSECUTIVE_SET == dumpRenderCacheRet) {
|
if (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START < rdf.id && window.RING_BUFF_CONSECUTIVE_SET == dumpRenderCacheRet) {
|
||||||
/*
|
/*
|
||||||
Don't change
|
Don't change
|
||||||
- lastAllConfirmedRenderFrameId, it's updated only in "rollbackAndChase > _createRoomDownsyncFrameLocally" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
|
- lastAllConfirmedRenderFrameId, it's updated only in "rollbackAndChase > _createOrUpdateRoomDownsyncFrameLocally" (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 "onInputFrameDownsyncBatch" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
|
||||||
*/
|
*/
|
||||||
return dumpRenderCacheRet;
|
return dumpRenderCacheRet;
|
||||||
@ -945,7 +945,7 @@ cc.Class({
|
|||||||
}, 1500);
|
}, 1500);
|
||||||
},
|
},
|
||||||
|
|
||||||
_createRoomDownsyncFrameLocally(renderFrameId, collisionSys, collisionSysMap) {
|
_createOrUpdateRoomDownsyncFrameLocally(renderFrameId, collisionSys, collisionSysMap) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const prevRenderFrameId = renderFrameId - 1;
|
const prevRenderFrameId = renderFrameId - 1;
|
||||||
const inputFrameAppliedOnPrevRenderFrame = (
|
const inputFrameAppliedOnPrevRenderFrame = (
|
||||||
@ -991,23 +991,6 @@ 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"
|
||||||
@ -1114,7 +1097,7 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
latestRdf = self._createRoomDownsyncFrameLocally(i + 1, collisionSys, collisionSysMap);
|
latestRdf = self._createOrUpdateRoomDownsyncFrameLocally(i + 1, collisionSys, collisionSysMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return latestRdf;
|
return latestRdf;
|
||||||
|
@ -36,11 +36,11 @@ cc.Class({
|
|||||||
type: cc.Float
|
type: cc.Float
|
||||||
},
|
},
|
||||||
magicLeanLowerBound: {
|
magicLeanLowerBound: {
|
||||||
default: 0.9, // Tangent of (PI/4) is 1.0.
|
default: 0.1,
|
||||||
type: cc.Float
|
type: cc.Float
|
||||||
},
|
},
|
||||||
magicLeanUpperBound: {
|
magicLeanUpperBound: {
|
||||||
default: 1.1,
|
default: 0.9,
|
||||||
type: cc.Float
|
type: cc.Float
|
||||||
},
|
},
|
||||||
// For joystick ends.
|
// For joystick ends.
|
||||||
@ -265,16 +265,8 @@ cc.Class({
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(continuousDx) < eps) {
|
const criticalRatio = continuousDy / continuousDx;
|
||||||
ret.dx = 0;
|
if (Math.abs(criticalRatio) < this.magicLeanLowerBound) {
|
||||||
if (0 < continuousDy) {
|
|
||||||
ret.dy = +2; // up
|
|
||||||
ret.encodedIdx = 1;
|
|
||||||
} else {
|
|
||||||
ret.dy = -2; // down
|
|
||||||
ret.encodedIdx = 2;
|
|
||||||
}
|
|
||||||
} else if (Math.abs(continuousDy) < eps) {
|
|
||||||
ret.dy = 0;
|
ret.dy = 0;
|
||||||
if (0 < continuousDx) {
|
if (0 < continuousDx) {
|
||||||
ret.dx = +2; // right
|
ret.dx = +2; // right
|
||||||
@ -283,50 +275,40 @@ cc.Class({
|
|||||||
ret.dx = -2; // left
|
ret.dx = -2; // left
|
||||||
ret.encodedIdx = 4;
|
ret.encodedIdx = 4;
|
||||||
}
|
}
|
||||||
|
} else if (Math.abs(criticalRatio) > this.magicLeanUpperBound) {
|
||||||
|
ret.dx = 0;
|
||||||
|
if (0 < continuousDy) {
|
||||||
|
ret.dy = +2; // up
|
||||||
|
ret.encodedIdx = 1;
|
||||||
|
} else {
|
||||||
|
ret.dy = -2; // down
|
||||||
|
ret.encodedIdx = 2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const criticalRatio = continuousDy / continuousDx;
|
if (0 < continuousDx) {
|
||||||
if (criticalRatio > this.magicLeanLowerBound && criticalRatio < this.magicLeanUpperBound) {
|
if (0 < continuousDy) {
|
||||||
if (0 < continuousDx) {
|
|
||||||
ret.dx = +1;
|
ret.dx = +1;
|
||||||
ret.dy = +1;
|
ret.dy = +1;
|
||||||
ret.encodedIdx = 5;
|
ret.encodedIdx = 5;
|
||||||
|
} else {
|
||||||
|
ret.dx = +1;
|
||||||
|
ret.dy = -1;
|
||||||
|
ret.encodedIdx = 7;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 0 >= continuousDx
|
||||||
|
if (0 < continuousDy) {
|
||||||
|
ret.dx = -1;
|
||||||
|
ret.dy = +1;
|
||||||
|
ret.encodedIdx = 8;
|
||||||
} else {
|
} else {
|
||||||
ret.dx = -1;
|
ret.dx = -1;
|
||||||
ret.dy = -1;
|
ret.dy = -1;
|
||||||
ret.encodedIdx = 6;
|
ret.encodedIdx = 6;
|
||||||
}
|
}
|
||||||
} else if (criticalRatio > -this.magicLeanUpperBound && criticalRatio < -this.magicLeanLowerBound) {
|
|
||||||
if (0 < continuousDx) {
|
|
||||||
ret.dx = +1;
|
|
||||||
ret.dy = -1;
|
|
||||||
ret.encodedIdx = 7;
|
|
||||||
} else {
|
|
||||||
ret.dx = -1;
|
|
||||||
ret.dy = +1;
|
|
||||||
ret.encodedIdx = 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (Math.abs(criticalRatio) < 0.1) {
|
|
||||||
ret.dy = 0;
|
|
||||||
if (0 < continuousDx) {
|
|
||||||
ret.dx = +2; // right
|
|
||||||
ret.encodedIdx = 3;
|
|
||||||
} else {
|
|
||||||
ret.dx = -2; // left
|
|
||||||
ret.encodedIdx = 4;
|
|
||||||
}
|
|
||||||
} else if (Math.abs(criticalRatio) > 0.9) {
|
|
||||||
ret.dx = 0;
|
|
||||||
if (0 < continuousDy) {
|
|
||||||
ret.dy = +2; // up
|
|
||||||
ret.encodedIdx = 1;
|
|
||||||
} else {
|
|
||||||
ret.dy = -2; // down
|
|
||||||
ret.encodedIdx = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user