mirror of
https://github.com/genxium/DelayNoMore
synced 2025-01-06 02:53:14 +00:00
330 lines
8.7 KiB
JavaScript
330 lines
8.7 KiB
JavaScript
window.DIRECTION_DECODER = [
|
|
// The 3rd value matches low-precision constants in backend.
|
|
[0, 0],
|
|
[0, +2],
|
|
[0, -2],
|
|
[+2, 0],
|
|
[-2, 0],
|
|
[+1, +1],
|
|
[-1, -1],
|
|
[+1, -1],
|
|
[-1, +1],
|
|
];
|
|
|
|
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.1,
|
|
type: cc.Float
|
|
},
|
|
magicLeanUpperBound: {
|
|
default: 0.9,
|
|
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;
|
|
}
|
|
|
|
const criticalRatio = continuousDy / continuousDx;
|
|
if (Math.abs(criticalRatio) < this.magicLeanLowerBound) {
|
|
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) > this.magicLeanUpperBound) {
|
|
ret.dx = 0;
|
|
if (0 < continuousDy) {
|
|
ret.dy = +2; // up
|
|
ret.encodedIdx = 1;
|
|
} else {
|
|
ret.dy = -2; // down
|
|
ret.encodedIdx = 2;
|
|
}
|
|
} else {
|
|
if (0 < continuousDx) {
|
|
if (0 < continuousDy) {
|
|
ret.dx = +1;
|
|
ret.dy = +1;
|
|
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 {
|
|
ret.dx = -1;
|
|
ret.dy = -1;
|
|
ret.encodedIdx = 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
|
|
decodeDirection(encodedDirection) {
|
|
const mapped = window.DIRECTION_DECODER[encodedDirection];
|
|
if (null == mapped) {
|
|
console.error("Unexpected encodedDirection = ", encodedDirection);
|
|
}
|
|
return {
|
|
dx: mapped[0],
|
|
dy: mapped[1],
|
|
};
|
|
},
|
|
|
|
getDiscretizedDirection() {
|
|
return this.discretizeDirection(this.cachedStickHeadPosition.x, this.cachedStickHeadPosition.y, this.joyStickEps);
|
|
}
|
|
});
|