2022-09-20 15:50:01 +00:00
window . DIRECTION _DECODER = [
2022-10-10 06:33:04 +00:00
// The 3rd value matches low-precision constants in backend.
[ 0 , 0 , 0.0 ] ,
[ 0 , + 1 , 1.0 ] ,
[ 0 , - 1 , 1.0 ] ,
[ + 2 , 0 , 0.5 ] ,
[ - 2 , 0 , 0.5 ] ,
[ + 2 , + 1 , 0.4472 ] ,
[ - 2 , - 1 , 0.4472 ] ,
[ + 2 , - 1 , 0.4472 ] ,
[ - 2 , + 1 , 0.4472 ] ,
[ + 2 , 0 , 0.5 ] ,
[ - 2 , 0 , 0.5 ] ,
[ 0 , + 1 , 1.0 ] ,
[ 0 , - 1 , 1.0 ] ,
2022-09-20 15:50:01 +00:00
] ;
cc . Class ( {
extends : cc . Component ,
properties : {
// For joystick begins.
translationListenerNode : {
default : null ,
type : cc . Node
} ,
zoomingListenerNode : {
default : null ,
type : cc . Node
} ,
stickhead : {
default : null ,
type : cc . Node
} ,
base : {
default : null ,
type : cc . Node
} ,
joyStickEps : {
default : 0.10 ,
type : cc . Float
} ,
magicLeanLowerBound : {
default : 0.414 , // Tangent of (PI/8).
type : cc . Float
} ,
magicLeanUpperBound : {
default : 2.414 , // Tangent of (3*PI/8).
type : cc . Float
} ,
// For joystick ends.
linearScaleFacBase : {
default : 1.00 ,
type : cc . Float
} ,
minScale : {
default : 1.00 ,
type : cc . Float
} ,
maxScale : {
default : 2.50 ,
type : cc . Float
} ,
maxMovingBufferLength : {
default : 1 ,
type : cc . Integer
} ,
zoomingScaleFacBase : {
default : 0.10 ,
type : cc . Float
} ,
zoomingSpeedBase : {
default : 4.0 ,
type : cc . Float
} ,
linearSpeedBase : {
default : 320.0 ,
type : cc . Float
} ,
canvasNode : {
default : null ,
type : cc . Node
} ,
mapNode : {
default : null ,
type : cc . Node
} ,
linearMovingEps : {
default : 0.10 ,
type : cc . Float
} ,
scaleByEps : {
default : 0.0375 ,
type : cc . Float
} ,
} ,
start ( ) { } ,
onLoad ( ) {
this . cachedStickHeadPosition = cc . v2 ( 0.0 , 0.0 ) ;
this . canvasNode = this . mapNode . parent ;
this . mainCameraNode = this . canvasNode . getChildByName ( "Main Camera" ) ; // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0.
this . mainCamera = this . mainCameraNode . getComponent ( cc . Camera ) ;
this . activeDirection = {
dx : 0.0 ,
dy : 0.0
} ;
this . maxHeadDistance = ( 0.5 * this . base . width ) ;
this . _initTouchEvent ( ) ;
this . _cachedMapNodePosTarget = [ ] ;
this . _cachedZoomRawTarget = null ;
this . mapScriptIns = this . mapNode . getComponent ( "Map" ) ;
this . initialized = true ;
} ,
_initTouchEvent ( ) {
const self = this ;
const translationListenerNode = ( self . translationListenerNode ? self . translationListenerNode : self . mapNode ) ;
const zoomingListenerNode = ( self . zoomingListenerNode ? self . zoomingListenerNode : self . mapNode ) ;
translationListenerNode . on ( cc . Node . EventType . TOUCH _START , function ( event ) {
self . _touchStartEvent ( event ) ;
} ) ;
translationListenerNode . on ( cc . Node . EventType . TOUCH _MOVE , function ( event ) {
self . _translationEvent ( event ) ;
} ) ;
translationListenerNode . on ( cc . Node . EventType . TOUCH _END , function ( event ) {
self . _touchEndEvent ( event ) ;
} ) ;
translationListenerNode . on ( cc . Node . EventType . TOUCH _CANCEL , function ( event ) {
self . _touchEndEvent ( event ) ;
} ) ;
translationListenerNode . inTouchPoints = new Map ( ) ;
zoomingListenerNode . on ( cc . Node . EventType . TOUCH _START , function ( event ) {
self . _touchStartEvent ( event ) ;
} ) ;
zoomingListenerNode . on ( cc . Node . EventType . TOUCH _MOVE , function ( event ) {
self . _zoomingEvent ( event ) ;
} ) ;
zoomingListenerNode . on ( cc . Node . EventType . TOUCH _END , function ( event ) {
self . _touchEndEvent ( event ) ;
} ) ;
zoomingListenerNode . on ( cc . Node . EventType . TOUCH _CANCEL , function ( event ) {
self . _touchEndEvent ( event ) ;
} ) ;
zoomingListenerNode . inTouchPoints = new Map ( ) ;
} ,
_isMapOverMoved ( mapTargetPos ) {
const virtualPlayerPos = cc . v2 ( - mapTargetPos . x , - mapTargetPos . y ) ;
return tileCollisionManager . isOutOfMapNode ( this . mapNode , virtualPlayerPos ) ;
} ,
_touchStartEvent ( event ) {
const theListenerNode = event . target ;
for ( let touch of event . _touches ) {
theListenerNode . inTouchPoints . set ( touch . _id , touch ) ;
}
} ,
_translationEvent ( event ) {
if ( ALL _MAP _STATES . VISUAL != this . mapScriptIns . state ) {
return ;
}
const theListenerNode = event . target ;
const linearScaleFacBase = this . linearScaleFacBase ; // Not used yet.
if ( 1 != theListenerNode . inTouchPoints . size ) {
return ;
}
if ( ! theListenerNode . inTouchPoints . has ( event . currentTouch . _id ) ) {
return ;
}
const diffVec = event . currentTouch . _point . sub ( event . currentTouch . _startPoint ) ;
const distance = diffVec . mag ( ) ;
const overMoved = ( distance > this . maxHeadDistance ) ;
if ( overMoved ) {
const ratio = ( this . maxHeadDistance / distance ) ;
this . cachedStickHeadPosition = diffVec . mul ( ratio ) ;
} else {
const ratio = ( distance / this . maxHeadDistance ) ;
this . cachedStickHeadPosition = diffVec . mul ( ratio ) ;
}
} ,
_zoomingEvent ( event ) {
if ( ALL _MAP _STATES . VISUAL != this . mapScriptIns . state ) {
return ;
}
const theListenerNode = event . target ;
if ( 2 != theListenerNode . inTouchPoints . size ) {
return ;
}
if ( 2 == event . _touches . length ) {
const firstTouch = event . _touches [ 0 ] ;
const secondTouch = event . _touches [ 1 ] ;
const startMagnitude = firstTouch . _startPoint . sub ( secondTouch . _startPoint ) . mag ( ) ;
const currentMagnitude = firstTouch . _point . sub ( secondTouch . _point ) . mag ( ) ;
let scaleBy = ( currentMagnitude / startMagnitude ) ;
scaleBy = 1 + ( scaleBy - 1 ) * this . zoomingScaleFacBase ;
if ( 1 < scaleBy && Math . abs ( scaleBy - 1 ) < this . scaleByEps ) {
// Jitterring.
cc . log ( ` ScaleBy == ${ scaleBy } is just jittering. ` ) ;
return ;
}
if ( 1 > scaleBy && Math . abs ( scaleBy - 1 ) < 0.5 * this . scaleByEps ) {
// Jitterring.
cc . log ( ` ScaleBy == ${ scaleBy } is just jittering. ` ) ;
return ;
}
if ( ! this . mainCamera ) return ;
const targetScale = this . mainCamera . zoomRatio * scaleBy ;
if ( this . minScale > targetScale || targetScale > this . maxScale ) {
return ;
}
this . mainCamera . zoomRatio = targetScale ;
for ( let child of this . mainCameraNode . children ) {
child . setScale ( 1 / targetScale ) ;
}
}
} ,
_touchEndEvent ( event ) {
const theListenerNode = event . target ;
do {
if ( ! theListenerNode . inTouchPoints . has ( event . currentTouch . _id ) ) {
break ;
}
const diffVec = event . currentTouch . _point . sub ( event . currentTouch . _startPoint ) ;
const diffVecMag = diffVec . mag ( ) ;
if ( this . linearMovingEps <= diffVecMag ) {
break ;
}
// Only triggers map-state-switch when `diffVecMag` is sufficiently small.
if ( ALL _MAP _STATES . VISUAL != this . mapScriptIns . state ) {
break ;
}
// TODO: Handle single-finger-click event.
} while ( false ) ;
this . cachedStickHeadPosition = cc . v2 ( 0.0 , 0.0 ) ;
for ( let touch of event . _touches ) {
if ( touch ) {
theListenerNode . inTouchPoints . delete ( touch . _id ) ;
}
}
} ,
_touchCancelEvent ( event ) { } ,
update ( dt ) {
if ( this . inMultiTouch ) return ;
if ( true != this . initialized ) return ;
this . stickhead . setPosition ( this . cachedStickHeadPosition ) ;
} ,
discretizeDirection ( continuousDx , continuousDy , eps ) {
let ret = {
dx : 0 ,
dy : 0 ,
encodedIdx : 0
} ;
if ( Math . abs ( continuousDx ) < eps && Math . abs ( continuousDy ) < eps ) {
return ret ;
}
if ( Math . abs ( continuousDx ) < eps ) {
ret . dx = 0 ;
if ( 0 < continuousDy ) {
ret . dy = + 1 ; // up
ret . encodedIdx = 1 ;
} else {
ret . dy = - 1 ; // down
ret . encodedIdx = 2 ;
}
} else if ( Math . abs ( continuousDy ) < eps ) {
ret . dy = 0 ;
if ( 0 < continuousDx ) {
ret . dx = + 2 ; // right
ret . encodedIdx = 3 ;
} else {
ret . dx = - 2 ; // left
ret . encodedIdx = 4 ;
}
} else {
const criticalRatio = continuousDy / continuousDx ;
if ( criticalRatio > this . magicLeanLowerBound && criticalRatio < this . magicLeanUpperBound ) {
if ( 0 < continuousDx ) {
ret . dx = + 2 ;
ret . dy = + 1 ;
ret . encodedIdx = 5 ;
} else {
ret . dx = - 2 ;
ret . dy = - 1 ;
ret . encodedIdx = 6 ;
}
} else if ( criticalRatio > - this . magicLeanUpperBound && criticalRatio < - this . magicLeanLowerBound ) {
if ( 0 < continuousDx ) {
ret . dx = + 2 ;
ret . dy = - 1 ;
ret . encodedIdx = 7 ;
} else {
ret . dx = - 2 ;
ret . dy = + 1 ;
ret . encodedIdx = 8 ;
}
} else {
if ( Math . abs ( criticalRatio ) < 1 ) {
ret . dy = 0 ;
if ( 0 < continuousDx ) {
ret . dx = + 2 ;
ret . encodedIdx = 9 ;
} else {
ret . dx = - 2 ;
ret . encodedIdx = 10 ;
}
} else {
ret . dx = 0 ;
if ( 0 < continuousDy ) {
ret . dy = + 1 ;
ret . encodedIdx = 11 ;
} else {
ret . dy = - 1 ;
ret . encodedIdx = 12 ;
}
}
}
}
return ret ;
} ,
decodeDirection ( encodedDirection ) {
const mapped = window . DIRECTION _DECODER [ encodedDirection ] ;
if ( null == mapped ) {
console . error ( "Unexpected encodedDirection = " , encodedDirection ) ;
}
return {
dx : mapped [ 0 ] ,
2022-09-26 03:16:18 +00:00
dy : mapped [ 1 ] ,
speedFactor : mapped [ 2 ] ,
2022-09-20 15:50:01 +00:00
}
} ,
getDiscretizedDirection ( ) {
return this . discretizeDirection ( this . cachedStickHeadPosition . x , this . cachedStickHeadPosition . y , this . joyStickEps ) ;
}
} ) ;