Initial commit.

This commit is contained in:
genxium
2022-09-20 23:50:01 +08:00
commit e90a335c56
432 changed files with 101884 additions and 0 deletions

View File

@@ -0,0 +1,471 @@
module.export = cc.Class({
extends: cc.Component,
properties: {
animComp: {
type: cc.Animation,
default: null,
},
baseSpeed: {
type: cc.Float,
default: 300,
},
speed: {
type: cc.Float,
default: 300
},
lastMovedAt: {
type: cc.Float,
default: 0 // In "GMT milliseconds"
},
eps: {
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
},
},
// LIFE-CYCLE CALLBACKS:
start() {
const self = this;
self.contactedControlledPlayers = [];
self.contactedNPCPlayers = [];
self.coveringShelterZReducers = [];
self.computedNewDifferentPosLocalToParentWithinCurrentFrame = null;
self.actionMangerSingleton = new cc.ActionManager();
self.scheduledDirection = {
dx: 0,
dy: 0
};
self.activeDirection = {
dx: 0,
dy: 0
};
},
onLoad() {
const self = this;
self.clips = {
'01': 'Top',
'0-1': 'Bottom',
'-20': 'Left',
'20': 'Right',
'-21': 'TopLeft',
'21': 'TopRight',
'-2-1': 'BottomLeft',
'2-1': 'BottomRight'
};
const canvasNode = self.mapNode.parent;
self.contactedBarriers = [];
const joystickInputControllerScriptIns = canvasNode.getComponent("TouchEventsManager");
self.ctrl = joystickInputControllerScriptIns;
self.animComp = self.node.getComponent(cc.Animation);
self.animComp.play();
},
scheduleNewDirection(newScheduledDirection, forceAnimSwitch) {
if (!newScheduledDirection) {
return;
}
if (forceAnimSwitch || null == this.scheduledDirection || (newScheduledDirection.dx != this.scheduledDirection.dx || newScheduledDirection.dy != this.scheduledDirection.dy)) {
this.scheduledDirection = newScheduledDirection;
const clipKey = newScheduledDirection.dx.toString() + newScheduledDirection.dy.toString();
const clips = (this.attacked ? this.attackedClips : this.clips);
let clip = clips[clipKey];
if (!clip) {
// Keep playing the current anim.
if (0 !== newScheduledDirection.dx || 0 !== newScheduledDirection.dy) {
cc.warn('Clip for clipKey === ' + clipKey + ' is invalid: ' + clip + '.');
}
} else {
this.animComp.play(clip);
if (this.attacked) {
cc.log(`Attacked, switching to play clipKey = ${clipKey}, clip == ${clip}, this.activeDirection == ${JSON.stringify(this.activeDirection)}, this.scheduledDirection == ${JSON.stringify(this.scheduledDirection)}.`);
}
}
}
},
_addCoveringShelterZReducer(comp) {
const self = this;
for (let coveringShelterZReducer of self.coveringShelterZReducers) {
if (coveringShelterZReducer._id == comp._id) {
return false;
}
}
self.coveringShelterZReducers.push(comp);
return true;
},
_removeCoveringShelterZReducer(comp) {
const self = this;
self.coveringShelterZReducers = self.coveringShelterZReducers.filter((coveringShelterZReducer) => {
return coveringShelterZReducer._id != comp._id;
});
return true;
},
_addContactedBarrier(collider) {
const self = this;
if (!self.contactedBarriers) {
cc.log("self.contactedBarriers is null or undefined" + self.contactedBarriers)
}
for (let contactedBarrier of self.contactedBarriers) {
if (contactedBarrier._id == collider._id) {
return false;
}
}
self.contactedBarriers.push(collider);
return true;
},
_removeContactedBarrier(collider) {
const self = this;
self.contactedBarriers = self.contactedBarriers.filter((contactedBarrier) => {
return contactedBarrier._id != collider._id;
});
return true;
},
_addContactedControlledPlayers(comp) {
const self = this;
for (let aComp of self.contactedControlledPlayers) {
if (aComp.uuid == comp.uuid) {
return false;
}
}
self.contactedControlledPlayers.push(comp);
return true;
},
_removeContactedControlledPlayer(comp) {
const self = this;
self.contactedControlledPlayers = self.contactedControlledPlayers.filter((aComp) => {
return aComp.uuid != comp.uuid;
});
return true;
},
_addContactedNPCPlayers(comp) {
const self = this;
for (let aComp of self.contactedNPCPlayers) {
if (aComp.uuid == comp.uuid) {
return false;
}
}
self.contactedNPCPlayers.push(comp);
return true;
},
_removeContactedNPCPlayer(comp) {
const self = this;
self.contactedNPCPlayers = self.contactedNPCPlayers.filter((aComp) => {
return aComp.uuid != comp.uuid;
});
return true;
},
_canMoveBy(vecToMoveBy) {
const self = this;
const computedNewDifferentPosLocalToParentWithinCurrentFrame = self.node.position.add(vecToMoveBy);
self.computedNewDifferentPosLocalToParentWithinCurrentFrame = computedNewDifferentPosLocalToParentWithinCurrentFrame;
if (tileCollisionManager.isOutOfMapNode(self.mapNode, computedNewDifferentPosLocalToParentWithinCurrentFrame)) {
return false;
}
const currentSelfColliderCircle = self.node.getComponent(cc.CircleCollider);
let nextSelfColliderCircle = null;
if (0 < self.contactedBarriers.length) {
/* To avoid unexpected buckling. */
const mutatedVecToMoveBy = vecToMoveBy.mul(5); // To help it escape the engaged `contactedBarriers`.
nextSelfColliderCircle = {
position: self.node.position.add(mutatedVecToMoveBy).add(currentSelfColliderCircle.offset),
radius: currentSelfColliderCircle.radius,
};
} else {
nextSelfColliderCircle = {
position: computedNewDifferentPosLocalToParentWithinCurrentFrame.add(currentSelfColliderCircle.offset),
radius: currentSelfColliderCircle.radius,
};
}
for (let contactedBarrier of self.contactedBarriers) {
let contactedBarrierPolygonLocalToParentWithinCurrentFrame = [];
for (let p of contactedBarrier.points) {
contactedBarrierPolygonLocalToParentWithinCurrentFrame.push(contactedBarrier.node.position.add(p));
}
if (cc.Intersection.pointInPolygon(nextSelfColliderCircle.position, contactedBarrierPolygonLocalToParentWithinCurrentFrame)) {
// Make sure that the player is "leaving" the PolygonCollider.
return false;
}
if (cc.Intersection.polygonCircle(contactedBarrierPolygonLocalToParentWithinCurrentFrame, nextSelfColliderCircle)) {
if (null == self.firstContactedEdge) {
return false;
}
if (null != self.firstContactedEdge && self.firstContactedEdge.associatedBarrier != contactedBarrier) {
const res = self._calculateTangentialMovementAttrs(nextSelfColliderCircle, contactedBarrier);
if (null == res.contactedEdge) {
// Otherwise, the current movement is going to transit smoothly onto the next PolygonCollider.
return false;
}
}
}
}
return true;
/*
* In a subclass, use
*
* _canMoveBy(vecToMoveBy) {
* BasePlayer.prototype._canMoveBy.call(this, vecToMoveBy);
* // Customized codes.
* }
*
* Reference http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/class.html#override
*/
},
_calculateTangentialMovementAttrs(currentSelfColliderCircle, contactedBarrier) {
/*
* Theoretically when the `contactedBarrier` is a convex polygon and the `PlayerCollider` is a circle, there can be only 1 `contactedEdge` for each `contactedBarrier`. Except only for around the corner.
*
* We should avoid the possibility of players hitting the "corners of convex polygons" by map design wherever & whenever possible.
*
*/
const self = this;
const sDir = self.activeDirection;
const currentSelfColliderCircleCentrePos = (currentSelfColliderCircle.position ? currentSelfColliderCircle.position : self.node.position.add(currentSelfColliderCircle.offset));
const currentSelfColliderCircleRadius = currentSelfColliderCircle.radius;
let contactedEdgeCandidateList = [];
let skinDepthThreshold = 0.45*currentSelfColliderCircleRadius;
for (let i = 0; i < contactedBarrier.points.length; ++i) {
const stPoint = contactedBarrier.points[i].add(contactedBarrier.offset).add(contactedBarrier.node.position);
const edPoint = (i == contactedBarrier.points.length - 1 ? contactedBarrier.points[0].add(contactedBarrier.offset).add(contactedBarrier.node.position) : contactedBarrier.points[1 + i].add(contactedBarrier.offset).add(contactedBarrier.node.position));
const tmpVSt = stPoint.sub(currentSelfColliderCircleCentrePos);
const tmpVEd = edPoint.sub(currentSelfColliderCircleCentrePos);
const crossProdScalar = tmpVSt.cross(tmpVEd);
if (0 < crossProdScalar) {
// If moving parallel along `st <-> ed`, the trajectory of `currentSelfColliderCircleCentrePos` will cut inside the polygon.
continue;
}
const dis = cc.Intersection.pointLineDistance(currentSelfColliderCircleCentrePos, stPoint, edPoint, true);
if (dis > currentSelfColliderCircleRadius) continue;
if (dis < skinDepthThreshold) continue;
contactedEdgeCandidateList.push({
st: stPoint,
ed: edPoint,
associatedBarrier: contactedBarrier,
});
}
let contactedEdge = null;
let contactedEdgeDir = null;
let largestInnerProdAbs = Number.MIN_VALUE;
if (0 < contactedEdgeCandidateList.length) {
const sDirMag = Math.sqrt(sDir.dx * sDir.dx + sDir.dy * sDir.dy);
for (let contactedEdgeCandidate of contactedEdgeCandidateList) {
const tmp = contactedEdgeCandidate.ed.sub(contactedEdgeCandidate.st);
const contactedEdgeDirCandidate = {
dx: tmp.x,
dy: tmp.y,
};
const contactedEdgeDirCandidateMag = Math.sqrt(contactedEdgeDirCandidate.dx * contactedEdgeDirCandidate.dx + contactedEdgeDirCandidate.dy * contactedEdgeDirCandidate.dy);
const innerDotProd = (sDir.dx * contactedEdgeDirCandidate.dx + sDir.dy * contactedEdgeDirCandidate.dy)/(sDirMag * contactedEdgeDirCandidateMag);
const innerDotProdThresholdMag = 0.7;
if ((0 > innerDotProd && innerDotProd > -innerDotProdThresholdMag) || (0 < innerDotProd && innerDotProd < innerDotProdThresholdMag)) {
// Intentionally left blank, in this case the player is trying to escape from the `contactedEdge`.
continue;
} else if (innerDotProd > 0) {
const abs = Math.abs(innerDotProd);
if (abs > largestInnerProdAbs) {
contactedEdgeDir = contactedEdgeDirCandidate;
contactedEdge = contactedEdgeCandidate;
}
} else {
const abs = Math.abs(innerDotProd);
if (abs > largestInnerProdAbs) {
contactedEdgeDir = {
dx: -contactedEdgeDirCandidate.dx,
dy: -contactedEdgeDirCandidate.dy,
};
contactedEdge = contactedEdgeCandidate;
}
}
}
}
return {
contactedEdgeDir: contactedEdgeDir,
contactedEdge: contactedEdge,
};
},
_calculateVecToMoveByWithChosenDir(elapsedTime, sDir) {
if (0 == sDir.dx && 0 == sDir.dy) {
return cc.v2();
}
const self = this;
const distanceToMove = (self.speed * elapsedTime);
const denominator = Math.sqrt(sDir.dx * sDir.dx + sDir.dy * sDir.dy);
const unitProjDx = (sDir.dx / denominator);
const unitProjDy = (sDir.dy / denominator);
return cc.v2(
distanceToMove * unitProjDx,
distanceToMove * unitProjDy,
);
},
_calculateVecToMoveBy(elapsedTime) {
const self = this;
// Note that `sDir` used in this method MUST BE a copy in RAM.
let sDir = {
dx: self.activeDirection.dx,
dy: self.activeDirection.dy,
};
if (0 == sDir.dx && 0 == sDir.dy) {
return cc.v2();
}
self.firstContactedEdge = null; // Reset everytime (temporary algorithm design, might change later).
if (0 < self.contactedBarriers.length) {
/*
* Hardcoded to take care of only the 1st `contactedEdge` of the 1st `contactedBarrier` for now. Each `contactedBarrier` must be "counterclockwisely convex polygonal", otherwise sliding doesn't work!
*
*/
const contactedBarrier = self.contactedBarriers[0];
const currentSelfColliderCircle = self.node.getComponent(cc.CircleCollider);
const res = self._calculateTangentialMovementAttrs(currentSelfColliderCircle, contactedBarrier);
if (res.contactedEdge) {
self.firstContactedEdge = res.contactedEdge;
sDir = res.contactedEdgeDir;
}
}
return self._calculateVecToMoveByWithChosenDir(elapsedTime, sDir);
},
update(dt) {
const self = this;
const vecToMoveBy = self._calculateVecToMoveBy(dt);
// console.log("activeDirection=", self.activeDirection, "vecToMoveBy=", vecToMoveBy, ", computedNewDifferentPosLocalToParentWithinCurrentFrame=", self.computedNewDifferentPosLocalToParentWithinCurrentFrame);
if (self._canMoveBy(vecToMoveBy)) {
self.node.position = self.computedNewDifferentPosLocalToParentWithinCurrentFrame;
}
},
lateUpdate(dt) {
const self = this;
self.activeDirection.dx = self.scheduledDirection.dx;
self.activeDirection.dy = self.scheduledDirection.dy;
const now = new Date().getTime();
self.lastMovedAt = now;
},
onCollisionEnter(other, self) {
const playerScriptIns = self.node.getComponent("SelfPlayer");
switch (other.node.name) {
case "NPCPlayer":
if ("NPCPlayer" != self.node.name) {
other.node.getComponent('NPCPlayer').showProfileTrigger();
}
playerScriptIns._addContactedNPCPlayers(other);
break;
case "PolygonBoundaryBarrier":
playerScriptIns._addContactedBarrier(other);
break;
case "PolygonBoundaryShelter":
break;
case "PolygonBoundaryShelterZReducer":
playerScriptIns._addCoveringShelterZReducer(other);
if (1 == playerScriptIns.coveringShelterZReducers.length) {
setLocalZOrder(self.node, 2);
}
break;
default:
break;
}
},
onCollisionStay(other, self) {
// TBD.
},
onCollisionExit(other, self) {
const playerScriptIns = self.getComponent("SelfPlayer");
switch (other.node.name) {
case "NPCPlayer":
other.node.getComponent('NPCPlayer').hideProfileTrigger();
playerScriptIns._removeContactedNPCPlayer(other);
break;
case "PolygonBoundaryBarrier":
playerScriptIns._removeContactedBarrier(other);
break;
case "PolygonBoundaryShelter":
break;
case "PolygonBoundaryShelterZReducer":
playerScriptIns._removeCoveringShelterZReducer(other);
if (0 == playerScriptIns.coveringShelterZReducers.length) {
setLocalZOrder(self.node, 5);
}
break;
default:
break;
}
},
_generateRandomDirection() {
return ALL_DISCRETE_DIRECTIONS_CLOCKWISE[Math.floor(Math.random() * ALL_DISCRETE_DIRECTIONS_CLOCKWISE.length)];
},
_generateRandomDirectionExcluding(toExcludeDx, toExcludeDy) {
let randomDirectionList = [];
let exactIdx = null;
for (let ii = 0; ii < ALL_DISCRETE_DIRECTIONS_CLOCKWISE.length; ++ii) {
if (toExcludeDx != ALL_DISCRETE_DIRECTIONS_CLOCKWISE[ii].dx || toExcludeDy != ALL_DISCRETE_DIRECTIONS_CLOCKWISE[ii].dy) continue;
exactIdx = ii;
break;
}
if (null == exactIdx) {
return this._generateRandomDirection();
}
for (let ii = 0; ii < ALL_DISCRETE_DIRECTIONS_CLOCKWISE.length; ++ii) {
if (ii == exactIdx || ((ii - 1) % ALL_DISCRETE_DIRECTIONS_CLOCKWISE.length) == exactIdx || ((ii + 1) % ALL_DISCRETE_DIRECTIONS_CLOCKWISE.length) == exactIdx) continue;
randomDirectionList.push(ALL_DISCRETE_DIRECTIONS_CLOCKWISE[ii]);
}
return randomDirectionList[Math.floor(Math.random() * randomDirectionList.length)]
},
updateSpeed(proposedSpeed) {
if (0 == proposedSpeed && 0 < this.speed) {
this.startFrozenDisplay();
}
if (0 < proposedSpeed && 0 == this.speed) {
this.stopFrozenDisplay();
}
this.speed = proposedSpeed;
},
startFrozenDisplay() {
const self = this;
self.attacked = true;
self.scheduleNewDirection(self.scheduledDirection, true);
},
stopFrozenDisplay() {
const self = this;
self.attacked = false;
self.scheduleNewDirection(self.scheduledDirection, true);
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "2fa4ffbb-5654-4c7a-b7f3-a27d1303b019",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,201 @@
module.export = cc.Class({
extends: cc.Component,
properties: {
localIdInBattle: {
default: null,
},
linearSpeed: {
default: 0.0,
},
},
ctor() {
this.ctrl = null;
this.activeDirection = null;
},
onLoad() {
},
_calculateVecToMoveByWithChosenDir(elapsedTime, sDir) {
if (0 == sDir.dx && 0 == sDir.dy) {
return cc.v2();
}
const self = this;
const distanceToMove = (self.linearSpeed * elapsedTime);
const denominator = Math.sqrt(sDir.dx * sDir.dx + sDir.dy * sDir.dy);
const unitProjDx = (sDir.dx / denominator);
const unitProjDy = (sDir.dy / denominator);
return cc.v2(
distanceToMove * unitProjDx,
distanceToMove * unitProjDy,
);
},
_calculateVecToMoveBy(elapsedTime) {
const self = this;
if (null == self.activeDirection) {
return null;
}
// Note that `sDir` used in this method MUST BE a copy in RAM.
let sDir = {
dx: self.activeDirection.dx,
dy: self.activeDirection.dy,
};
if (0 == sDir.dx && 0 == sDir.dy) {
return cc.v2();
}
return self._calculateVecToMoveByWithChosenDir(elapsedTime, sDir);
},
_canMoveBy(vecToMoveBy) {
return true;
},
update(dt) {
// Used only for EXTRAPOLATING the position of this bullet. The position might be corrected within `setData` as well.
const self = this;
if (null != self.bulletMaxDist) {
const dxMoved = self.node.position.x - self.startAtPoint.x;
const dyMoved = self.node.position.y - self.startAtPoint.y;
const distanceMoved = Math.sqrt(dxMoved * dxMoved + dyMoved * dyMoved)
self.node.opacity = 255*(1 - distanceMoved/self.bulletMaxDist);
}
const vecToMoveBy = self._calculateVecToMoveBy(dt);
if (null == vecToMoveBy) {
return;
}
if (self._canMoveBy(vecToMoveBy)) {
self.node.position = self.node.position.add(vecToMoveBy);
}
},
_calculateAngle(dx, dy) {
if (dx == 0) {
if (dy > 0) {
return 90;
}
if (dy < 0) {
return -90;
}
}
if (dx > 0) {
if (dy == 0) {
return 0;
}
if (dy > 0) {
return 45;
}
if (dy < 0) {
return -45;
}
}
if (dx < 0) {
if (dy == 0) {
return 180;
}
if (dy > 0) {
return 135;
}
if (dy < 0) {
return -135;
}
}
return null;
},
setData(bulletLocalIdInBattle, bulletInfo, dtFromMapUpdate) {
const targetNode = this.node;
if (true == bulletInfo.removed) {
return false;
}
if (null == bulletInfo.startAtPoint || null == bulletInfo.endAtPoint) {
console.error(`Init bullet direction error, startAtPoint:${bulletInfo.startAtPoint}, endAtPoint:${bulletInfo.endAtPoint}`);
return false;
}
this.localIdInBattle = bulletLocalIdInBattle;
this.linearSpeed = bulletInfo.linearSpeed * 1000000000; // The `bullet.LinearSpeed` on server-side is denoted in pts/nanoseconds.
const dx = bulletInfo.endAtPoint.x - bulletInfo.startAtPoint.x;
const dy = bulletInfo.endAtPoint.y - bulletInfo.startAtPoint.y;
const discretizedDir = this.ctrl.discretizeDirection(dx, dy, this.ctrl.joyStickEps);
const baseAngle = 0;
const angleToRotate = baseAngle - this._calculateAngle(discretizedDir.dx, discretizedDir.dy);
if (null == angleToRotate) {
return false;
}
set2dRotation(targetNode, angleToRotate);
const newPos = cc.v2(
bulletInfo.x,
bulletInfo.y
);
if (null == this.activeDirection) {
// Initialization.
this.startAtPoint = bulletInfo.startAtPoint;
this.endAtPoint = bulletInfo.endAtPoint;
this.bulletMaxDist = 600.0; // Hardcoded temporarily, matching that in "<backend>/models/room.go". -- YFLu, 2019-09-05.
targetNode.setPosition(newPos);
this.activeDirection = {
dx: 0,
dy: 0,
};
return true;
}
const oldPos = cc.v2(
targetNode.x,
targetNode.y,
);
const toMoveByVec = newPos.sub(oldPos);
const toMoveByVecMag = toMoveByVec.mag();
const toTeleportDisThreshold = (this.linearSpeed * dtFromMapUpdate * 100);
const notToMoveDisThreshold = (this.linearSpeed * dtFromMapUpdate * 0.5);
if (toMoveByVecMag < notToMoveDisThreshold) {
// To stop extrapolated moving.
this.activeDirection = {
dx: 0,
dy: 0,
};
} else {
if (toMoveByVecMag > toTeleportDisThreshold) {
console.log("Bullet ", bulletLocalIdInBattle, " is teleporting! Having toMoveByVecMag == ", toMoveByVecMag, ", toTeleportDisThreshold == ", toTeleportDisThreshold);
// To stop extrapolated moving.
this.activeDirection = {
dx: 0,
dy: 0
};
// Deliberately NOT using `cc.Action`. -- YFLu, 2019-09-04
targetNode.setPosition(newPos);
} else {
// The common case which is suitable for interpolation.
const normalizedDir = {
dx: toMoveByVec.x / toMoveByVecMag,
dy: toMoveByVec.y / toMoveByVecMag,
};
if (isNaN(normalizedDir.dx) || isNaN(normalizedDir.dy)) {
this.activeDirection = {
dx: 0,
dy: 0,
};
} else {
this.activeDirection = normalizedDir;
}
}
}
return true;
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "ea965d25-ec82-478c-bdb2-9ac07981ab0e",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,31 @@
cc.Class({
extends: cc.Component,
properties: {
mapNode: {
type: cc.Node,
default: null
},
},
onLoad () {
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera);
this.mapScriptIns = this.mapNode.getComponent("Map");
},
start() {},
update(dt) {
const self = this;
if (!self.mainCamera) return;
if (!self.mapScriptIns) return;
if (!self.mapScriptIns.selfPlayerInfo) return;
if (!self.mapScriptIns.playerRichInfoDict) return;
const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict[self.mapScriptIns.selfPlayerInfo.id];
if (!selfPlayerRichInfo) return;
const selfPlayerNode = selfPlayerRichInfo.node;
if (!selfPlayerNode) return;
self.mainCamera.node.setPosition(selfPlayerNode.position);
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "78830fc7-4e25-49a1-a7fc-9f9d3883f278",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,16 @@
cc.Class({
extends: cc.Component,
properties: {
map: {
type: cc.Node,
default: null
}
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "8ac0809b-f98d-4cff-a66c-3bd9e218ecd6",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,29 @@
cc.Class({
extends: cc.Component,
properties: {
mapNode: {
type: cc.Node,
default: null,
}
},
onButtonClick(event, customData) {
const mapScriptIns = this.mapNode.getComponent('Map');
switch (customData) {
case 'confirm':
mapScriptIns.logout.bind(mapScriptIns)(true, false);
break;
case 'cancel':
mapScriptIns.onLogoutConfirmationDismissed.bind(mapScriptIns)();
break;
default:
break;
}
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "e16000cb-4e57-44be-a791-e26298b480bb",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,32 @@
cc.Class({
extends: cc.Component,
properties: {
countdownSeconds : {
type: cc.Label,
default: null
},
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
},
setData() {
this.startedMillis = Date.now();
this.durationMillis = 3000;
},
update() {
const currentGMTMillis = Date.now();
const elapsedMillis = currentGMTMillis - this.startedMillis;
let remainingMillis = this.durationMillis - elapsedMillis;
if (remainingMillis <= 0) {
remainingMillis = 0;
}
let remaingHint = "" + Math.round(remainingMillis / 1000 );
if (remaingHint != this.countdownSeconds.string) {
this.countdownSeconds.string = remaingHint;
}
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "6a3d663a-2a2d-418a-a015-48a211770465",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,146 @@
cc.Class({
extends: cc.Component,
properties: {
firstPlayerInfoNode: {
type: cc.Node,
default: null
},
secondPlayerInfoNode: {
type: cc.Node,
default: null
},
findingAnimNode: {
type: cc.Node,
default: null
},
myAvatarNode: {
type: cc.Node,
default: null
},
exitBtnNode: {
type: cc.Node,
default: null
}
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
// WARNING: 不能保证在ws连接成功并且拿到boundRoomId后才运行到此处。
if (cc.sys.platform == cc.sys.WECHAT_GAME) {
const boundRoomId = window.getBoundRoomIdFromPersistentStorage();
const wxToShareMessage = {
title: '夺宝大作战',
imageUrl: 'https://mmocgame.qpic.cn/wechatgame/ibxA6JVNslX02zq6aAWCZiaWTXLYGorrVgUszo3WH1oL1CFDcFU7VKPRXPFiadxagMR/0',
imageUrlId: 'FiLZpa5FT5GgEeEagzGBsA',
query: 'expectedRoomId=' + boundRoomId,
};
console.warn("The boundRoomId for sharing: ", boundRoomId, " wxToShareMessage ", wxToShareMessage);
wx.showShareMenu();
wx.onShareAppMessage(() => (wxToShareMessage));
}
},
init() {
if (null != this.firstPlayerInfoNode) {
this.firstPlayerInfoNode.active = false;
}
if (null != this.secondPlayerInfoNode) {
this.secondPlayerInfoNode.active = false;
}
this.playersInfoNode = {};
Object.assign(this.playersInfoNode, {
1: this.firstPlayerInfoNode
});
Object.assign(this.playersInfoNode, {
2: this.secondPlayerInfoNode
});
if (null != this.findingAnimNode) {
this.findingAnimNode.active = true;
}
window.firstPlayerInfoNode = this.firstPlayerInfoNode;
},
hideExitButton() {
if (null == this.exitBtnNode != null) {
return;
}
this.exitBtnNode.active = false;
},
exitBtnOnClick(evt) {
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
window.closeWSConnection();
if (cc.sys.platform == cc.sys.WECHAT_GAME) {
cc.director.loadScene('wechatGameLogin');
} else {
cc.director.loadScene('login');
}
},
updatePlayersInfo(playerMetas) {
if (null == playerMetas) return;
for (let i in playerMetas) {
const playerMeta = playerMetas[i];
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
if (null == playerInfoNode) {
cc.error("There's no playerInfoNode for joinIndex == ", joinIndex, ", as `this.playerInfoNode` is currently ", this.playersInfoNode);
}
playerInfoNode.active = true;
if (2 == playerMeta.joinIndex) {
if (null != this.findingAnimNode) {
this.findingAnimNode.active = false;
}
}
}
//显示自己的头像名称以及他人的头像名称
for (let i in playerMetas) {
const playerMeta = playerMetas[i];
console.log("Showing playerMeta:", playerMeta);
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
(() => { //远程加载头像
let remoteUrl = playerMeta.avatar;
if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for :`);
cc.log(playerMeta);
remoteUrl = 'http://wx.qlogo.cn/mmopen/PiajxSqBRaEJUWib5D85KXWHumaxhU4E9XOn9bUpCNKF3F4ibfOj8JYHCiaoosvoXCkTmOQE1r2AKKs8ObMaz76EdA/0'
}
cc.loader.load({
url: remoteUrl,
type: 'jpg'
}, function(err, texture) {
if (null != err ) {
console.error(err);
} else {
if (null == texture) {
return;
}
const sf = new cc.SpriteFrame();
sf.setTexture(texture);
playerInfoNode.getChildByName('avatarMask').getChildByName('avatar').getComponent(cc.Sprite).spriteFrame = sf;
}
});
})();
function isEmptyString(str) {
return str == null || str == ''
}
const nameNode = playerInfoNode.getChildByName("name");
const nameToDisplay = (() => {
if (!isEmptyString(playerMeta.displayName)) {
return playerMeta.displayName
} else if (!isEmptyString(playerMeta.name)) {
return playerMeta.name
} else {
return ""
}
})();
nameNode.getComponent(cc.Label).string = nameToDisplay;
}
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "ecdd3aad-b601-4f8d-85a1-69d9d270a806",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,24 @@
cc.Class({
extends: cc.Component,
properties: {
modeButton: {
type: cc.Button,
default: null
},
mapNode: {
type: cc.Node,
default: null
},
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
const modeBtnClickEventHandler = new cc.Component.EventHandler();
modeBtnClickEventHandler.target = this.mapNode;
modeBtnClickEventHandler.component = "Map";
modeBtnClickEventHandler.handler = "onGameRule1v1ModeClicked";
this.modeButton.clickEvents.push(modeBtnClickEventHandler);
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "dd92b295-cbc1-4963-bbaa-de27a8359099",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,243 @@
/**
* Creates a binary heap.
*
* @constructor
* @param {function} customCompare An optional custom node comparison
* function.
*/
var BinaryHeap = function (customCompare) {
/**
* The backing data of the heap.
* @type {Object[]}
* @private
*/
this.list = [];
if (customCompare) {
this.compare = customCompare;
}
};
/**
* Builds a heap with the provided keys and values, this will discard the
* heap's current data.
*
* @param {Array} keys An array of keys.
* @param {Array} values An array of values. This must be the same size as the
* key array.
*/
BinaryHeap.prototype.buildHeap = function (keys, values) {
if (typeof values !== 'undefined' && values.length !== keys.length) {
throw new Error('Key array must be the same length as value array');
}
var nodeArray = [];
for (var i = 0; i < keys.length; i++) {
nodeArray.push(new Node(keys[i], values ? values[i] : undefined));
}
buildHeapFromNodeArray(this, nodeArray);
};
/**
* Clears the heap's data, making it an empty heap.
*/
BinaryHeap.prototype.clear = function () {
this.list.length = 0;
};
/**
* Extracts and returns the minimum node from the heap.
*
* @return {Node} node The heap's minimum node or undefined if the heap is
* empty.
*/
BinaryHeap.prototype.extractMinimum = function () {
if (!this.list.length) {
return undefined;
}
if (this.list.length === 1) {
return this.list.shift();
}
var min = this.list[0];
this.list[0] = this.list.pop();
heapify(this, 0);
return min;
};
/**
* Returns the minimum node from the heap.
*
* @return {Node} node The heap's minimum node or undefined if the heap is
* empty.
*/
BinaryHeap.prototype.findMinimum = function () {
return this.isEmpty() ? undefined : this.list[0];
};
/**
* Inserts a new key-value pair into the heap.
*
* @param {Object} key The key to insert.
* @param {Object} value The value to insert.
* @return {Node} node The inserted node.
*/
BinaryHeap.prototype.insert = function (key, value) {
var i = this.list.length;
var node = new Node(key, value);
this.list.push(node);
var parent = getParent(i);
while (typeof parent !== 'undefined' &&
this.compare(this.list[i], this.list[parent]) < 0) {
swap(this.list, i, parent);
i = parent;
parent = getParent(i);
}
return node;
};
/**
* @return {boolean} Whether the heap is empty.
*/
BinaryHeap.prototype.isEmpty = function () {
return !this.list.length;
};
/**
* @return {number} The size of the heap.
*/
BinaryHeap.prototype.size = function () {
return this.list.length;
};
/**
* Joins another heap to this one.
*
* @param {BinaryHeap} otherHeap The other heap.
*/
BinaryHeap.prototype.union = function (otherHeap) {
var array = this.list.concat(otherHeap.list);
buildHeapFromNodeArray(this, array);
};
/**
* Compares two nodes with each other.
*
* @private
* @param {Object} a The first key to compare.
* @param {Object} b The second key to compare.
* @return -1, 0 or 1 if a < b, a == b or a > b respectively.
*/
BinaryHeap.prototype.compare = function (a, b) {
if (a.key > b.key) {
return 1;
}
if (a.key < b.key) {
return -1;
}
return 0;
};
/**
* Heapifies a node.
*
* @private
* @param {BinaryHeap} heap The heap containing the node to heapify.
* @param {number} i The index of the node to heapify.
*/
function heapify(heap, i) {
var l = getLeft(i);
var r = getRight(i);
var smallest = i;
if (l < heap.list.length &&
heap.compare(heap.list[l], heap.list[i]) < 0) {
smallest = l;
}
if (r < heap.list.length &&
heap.compare(heap.list[r], heap.list[smallest]) < 0) {
smallest = r;
}
if (smallest !== i) {
swap(heap.list, i, smallest);
heapify(heap, smallest);
}
}
/**
* Builds a heap from a node array, this will discard the heap's current data.
*
* @private
* @param {BinaryHeap} heap The heap to override.
* @param {Node[]} nodeArray The array of nodes for the new heap.
*/
function buildHeapFromNodeArray(heap, nodeArray) {
heap.list = nodeArray;
for (var i = Math.floor(heap.list.length / 2); i >= 0; i--) {
heapify(heap, i);
}
}
/**
* Swaps two values in an array.
*
* @private
* @param {Array} array The array to swap on.
* @param {number} a The index of the first element.
* @param {number} b The index of the second element.
*/
function swap(array, a, b) {
var temp = array[a];
array[a] = array[b];
array[b] = temp;
}
/**
* Gets the index of a node's parent.
*
* @private
* @param {number} i The index of the node to get the parent of.
* @return {number} The index of the node's parent.
*/
function getParent(i) {
if (i === 0) {
return undefined;
}
return Math.floor((i - 1) / 2);
}
/**
* Gets the index of a node's left child.
*
* @private
* @param {number} i The index of the node to get the left child of.
* @return {number} The index of the node's left child.
*/
function getLeft(i) {
return 2 * i + 1;
}
/**
* Gets the index of a node's right child.
*
* @private
* @param {number} i The index of the node to get the right child of.
* @return {number} The index of the node's right child.
*/
function getRight(i) {
return 2 * i + 2;
}
/**
* Creates a node.
*
* @constructor
* @param {Object} key The key of the new node.
* @param {Object} value The value of the new node.
*/
function Node(key, value) {
this.key = key;
this.value = value;
}
module.exports = BinaryHeap;

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "247b7613-6c6e-4f01-b1d6-5f8f041b5688",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,69 @@
cc.Class({
extends: cc.Component,
properties: {},
setInputControls: function() {
const self = this;
// add keyboard event listener
// When there is a key being pressed down, judge if it's the designated directional button and set up acceleration in the corresponding direction
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(event) {
switch (event.keyCode) {
case cc.macro.KEY.w:
self.activeDirection.dPjY = +1.0;
break;
case cc.macro.KEY.s:
self.activeDirection.dPjY = -1.0;
break;
case cc.macro.KEY.a:
self.activeDirection.dPjX = -2.0;
break;
case cc.macro.KEY.d:
self.activeDirection.dPjX = +2.0;
break;
default:
break;
}
}, self.node);
// when releasing the button, stop acceleration in this direction
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, function(event) {
switch (event.keyCode) {
case cc.macro.KEY.w:
if (+1.0 == self.activeDirection.dPjY) {
self.activeDirection.dPjY = 0.0;
}
break;
case cc.macro.KEY.s:
if (-1.0 == self.activeDirection.dPjY) {
self.activeDirection.dPjY = 0.0;
}
break;
case cc.macro.KEY.a:
if (-2.0 == self.activeDirection.dPjX) {
self.activeDirection.dPjX = 0.0;
}
break;
case cc.macro.KEY.d:
if (+2.0 == self.activeDirection.dPjX) {
self.activeDirection.dPjX = 0.0;
}
break;
default:
break;
}
}, self.node);
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
// Properties deliberately hidden from GUI panel.
this.activeDirection = {
dPjY: 0.0,
dPjX: 0.0
};
this.setInputControls();
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "4561a173-bfd2-4f64-b7ba-888cce0e4d9d",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,555 @@
const i18n = require('LanguageData');
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
cc.Class({
extends: cc.Component,
properties: {
cavasNode: {
default: null,
type: cc.Node
},
backgroundNode: {
default: null,
type: cc.Node
},
interactiveControls: {
default: null,
type: cc.Node
},
phoneLabel: {
default: null,
type: cc.Node
},
smsLoginCaptchaLabel: {
default: null,
type: cc.Node
},
phoneCountryCodeInput: {
default: null,
type: cc.Node
},
phoneNumberInput: {
type: cc.Node,
default: null
},
phoneNumberTips: {
type: cc.Node,
default: null
},
smsLoginCaptchaInput: {
type: cc.Node,
default: null
},
smsLoginCaptchaButton: {
type: cc.Node,
default: null
},
captchaTips: {
type: cc.Node,
default: null
},
loginButton: {
type: cc.Node,
default: null
},
smsWaitCountdownPrefab: {
default: null,
type: cc.Prefab
},
loadingPrefab: {
default: null,
type: cc.Prefab
},
wechatLoginTips: {
default: null,
type: cc.Label,
},
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
//kobako: 腾讯统计代码
//WARN: 打包到微信小游戏的时候会导致出错
/*
(function() {
var mta = document.createElement("script");
mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4";
mta.setAttribute("name", "MTAH5");
mta.setAttribute("sid", "500674632");
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(mta, s);
})();
*/
window.atFirstLocationHref = window.location.href.split('#')[0];
const self = this;
self.getRetCodeList();
self.getRegexList();
const isUsingX5BlinkKernelOrWebkitWeChatKernel = window.isUsingX5BlinkKernelOrWebkitWeChatKernel();
//const isUsingX5BlinkKernelOrWebkitWeChatKernel = true;
if (!CC_DEBUG) {
self.phoneNumberTips.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.smsLoginCaptchaButton.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.captchaTips.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.phoneCountryCodeInput.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.phoneNumberInput.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.smsLoginCaptchaInput.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.phoneLabel.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.smsLoginCaptchaLabel.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
self.loginButton.active = !isUsingX5BlinkKernelOrWebkitWeChatKernel;
}
self.checkPhoneNumber = self.checkPhoneNumber.bind(self);
self.checkIntAuthTokenExpire = self.checkIntAuthTokenExpire.bind(self);
self.checkCaptcha = self.checkCaptcha.bind(self);
self.onSMSCaptchaGetButtonClicked = self.onSMSCaptchaGetButtonClicked.bind(self);
self.smsLoginCaptchaButton.on('click', self.onSMSCaptchaGetButtonClicked);
self.loadingNode = cc.instantiate(this.loadingPrefab);
self.smsGetCaptchaNode = self.smsLoginCaptchaButton.getChildByName('smsGetCaptcha');
self.smsWaitCountdownNode = cc.instantiate(self.smsWaitCountdownPrefab);
const qDict = window.getQueryParamDict();
if (null != qDict && qDict["expectedRoomId"]) {
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
}
cc.loader.loadRes("pbfiles/room_downsync_frame", function(err, textAsset /* cc.TextAsset */ ) {
if (err) {
cc.error(err.message || err);
return;
}
if (false == (cc.sys.platform == cc.sys.WECHAT_GAME)) {
// Otherwise, `window.RoomDownsyncFrame` is already assigned.
let protoRoot = new protobuf.Root;
window.protobuf.parse(textAsset.text, protoRoot);
window.RoomDownsyncFrame = protoRoot.lookupType("treasurehunterx.RoomDownsyncFrame");
window.BattleColliderInfo = protoRoot.lookupType("treasurehunterx.BattleColliderInfo");
window.WsReq = protoRoot.lookupType("treasurehunterx.WsReq");
window.WsResp = protoRoot.lookupType("treasurehunterx.WsResp");
}
self.checkIntAuthTokenExpire().then(
() => {
const intAuthToken = JSON.parse(cc.sys.localStorage.getItem('selfPlayer')).intAuthToken;
self.useTokenLogin(intAuthToken);
},
() => {
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
if ( (CC_DEBUG || isUsingX5BlinkKernelOrWebkitWeChatKernel) ) {
if (null != qDict && qDict["code"]) {
const code = qDict["code"];
console.log("Got the wx authcode: ", code, "while at full url: " + window.location.href);
self.useWXCodeLogin(code);
} else {
if (isUsingX5BlinkKernelOrWebkitWeChatKernel) {
self.getWechatCode(null);
} else {
// Deliberately left blank.
}
}
}
}
);
});
},
getRetCodeList() {
const self = this;
self.retCodeDict = constants.RET_CODE;
},
getRegexList() {
const self = this;
self.regexList = {
EMAIL: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
PHONE: /^\+?[0-9]{8,14}$/,
STREET_META: /^.{5,100}$/,
LNG_LAT_TEXT: /^[0-9]+(\.[0-9]{4,6})$/,
SEO_KEYWORD: /^.{2,50}$/,
PASSWORD: /^.{6,50}$/,
SMS_CAPTCHA_CODE: /^[0-9]{4}$/,
ADMIN_HANDLE: /^.{4,50}$/,
};
},
onSMSCaptchaGetButtonClicked(evt) {
var timerEnable = true;
const self = this;
if (!self.checkPhoneNumber('getCaptcha')) {
return;
}
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER +
constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.SMS_CAPTCHA + constants.ROUTE_PATH.GET,
type: 'GET',
data: {
phoneCountryCode: self.phoneCountryCodeInput.getComponent(cc.EditBox).string,
phoneNum: self.phoneNumberInput.getComponent(cc.EditBox).string
},
success: function(res) {
switch (res.ret) {
case self.retCodeDict.OK:
self.phoneNumberTips.getComponent(cc.Label).string = '';
self.captchaTips.getComponent(cc.Label).string = '';
break;
case self.retCodeDict.DUPLICATED:
self.phoneNumberTips.getComponent(cc.Label).string = constants.ALERT.TIP_LABEL.LOG_OUT;
break;
case self.retCodeDict.INCORRECT_PHONE_COUNTRY_CODE_OR_NUMBER:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.PHONE_ERR");
break;
case self.retCodeDict.IS_TEST_ACC:
self.smsLoginCaptchaInput.getComponent(cc.EditBox).string = res.smsLoginCaptcha;
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.TEST_USER");
timerEnable = false;
// clearInterval(self.countdownTimer);
break;
case self.retCodeDict.SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_FREEQUENT_REQUIRE");
default:
break;
}
if (timerEnable)
self.countdownTime(self);
}
});
},
countdownTime(self) {
self.smsLoginCaptchaButton.off('click', self.onSMSCaptchaGetButtonClicked);
self.smsLoginCaptchaButton.removeChild(self.smsGetCaptchaNode);
self.smsWaitCountdownNode.parent = self.smsLoginCaptchaButton;
var total = 20; // Magic number
self.countdownTimer = setInterval(function() {
if (total === 0) {
self.smsWaitCountdownNode.parent.removeChild(self.smsWaitCountdownNode);
self.smsGetCaptchaNode.parent = self.smsLoginCaptchaButton;
self.smsWaitCountdownNode.getChildByName('WaitTimeLabel').getComponent(cc.Label).string = 20;
self.smsLoginCaptchaButton.on('click', self.onSMSCaptchaGetButtonClicked);
clearInterval(self.countdownTimer);
} else {
total--;
self.smsWaitCountdownNode.getChildByName('WaitTimeLabel').getComponent(cc.Label).string = total;
}
}, 1000)
},
checkIntAuthTokenExpire() {
return new Promise((resolve, reject) => {
if (!cc.sys.localStorage.getItem('selfPlayer')) {
reject();
return;
}
const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
(selfPlayer.intAuthToken && new Date().getTime() < selfPlayer.expiresAt) ? resolve() : reject();
})
},
checkPhoneNumber(type) {
const self = this;
const phoneNumberRegexp = self.regexList.PHONE;
var phoneNumberString = self.phoneNumberInput.getComponent(cc.EditBox).string;
if (phoneNumberString) {
return true;
if (!phoneNumberRegexp.test(phoneNumberString)) {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.PHONE_ERR");
return false;
} else {
return true;
}
} else {
if (type === 'getCaptcha' || type === 'login') {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.PHONE_ERR");
}
return false;
}
},
checkCaptcha(type) {
const self = this;
const captchaRegexp = self.regexList.SMS_CAPTCHA_CODE;
var captchaString = self.smsLoginCaptchaInput.getComponent(cc.EditBox).string;
if (captchaString) {
if (self.smsLoginCaptchaInput.getComponent(cc.EditBox).string.length !== 4 || (!captchaRegexp.test(captchaString))) {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.CAPTCHA_ERR");
return false;
} else {
return true;
}
} else {
if ('login' == type) {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.CAPTCHA_ERR");
}
return false;
}
},
useTokenLogin(_intAuthToken) {
var self = this;
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.INT_AUTH_TOKEN + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: {
intAuthToken: _intAuthToken
},
success: function(resp) {
self.onLoggedIn(resp);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `useTokenLogin` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage()
},
timeout: function() {
self.enableInteractiveControls(true);
},
});
},
enableInteractiveControls(enabled) {
this.smsLoginCaptchaButton.getComponent(cc.Button).interactable = enabled;
this.loginButton.getComponent(cc.Button).interactable = enabled;
this.phoneCountryCodeInput.getComponent(cc.EditBox).enabled = enabled;
this.phoneNumberInput.getComponent(cc.EditBox).enabled = enabled;
this.smsLoginCaptchaInput.getComponent(cc.EditBox).enabled = enabled;
if (enabled) {
setVisible(this.interactiveControls);
} else {
setInvisible(this.interactiveControls);
}
},
onLoginButtonClicked(evt) {
const self = this;
if (!self.checkPhoneNumber('login') || !self.checkCaptcha('login')) {
return;
}
self.loginParams = {
phoneCountryCode: self.phoneCountryCodeInput.getComponent(cc.EditBox).string,
phoneNum: self.phoneNumberInput.getComponent(cc.EditBox).string,
smsLoginCaptcha: self.smsLoginCaptchaInput.getComponent(cc.EditBox).string
};
self.enableInteractiveControls(false);
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER +
constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.SMS_CAPTCHA + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: self.loginParams,
success: function(resp) {
self.onLoggedIn(resp);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `onLoginButtonClicked` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage()
},
timeout: function() {
self.enableInteractiveControls(true);
}
});
},
onWechatLoggedIn(res) {
const self = this;
if (res.ret === self.retCodeDict.OK) {
self.enableInteractiveControls(false);
const date = Number(res.expiresAt);
const selfPlayer = {
expiresAt: date,
playerId: res.playerId,
intAuthToken: res.intAuthToken,
displayName: res.displayName,
avatar: res.avatar,
}
cc.sys.localStorage.setItem('selfPlayer', JSON.stringify(selfPlayer));
const qDict = window.getQueryParamDict();
const expectedRoomId = qDict["expectedRoomId"];
if (null != expectedRoomId) {
console.log("onWechatLoggedIn using expectedRoomId == " + expectedRoomId);
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
}
// To remove "code=XXX" in "query string".
window.history.replaceState(qDict, null, window.location.pathname);
self.useTokenLogin(res.intAuthToken);
} else {
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.wechatLoginTips.string = constants.ALERT.TIP_LABEL.WECHAT_LOGIN_FAILS + ", errorCode = " + res.ret;
// To remove "code=XXX" in "query string".
window.history.replaceState({}, null, window.location.pathname);
}
},
onLoggedIn(res) {
const self = this;
cc.log(`OnLoggedIn ${JSON.stringify(res)}.`)
if (res.ret === self.retCodeDict.OK) {
if(window.isUsingX5BlinkKernelOrWebkitWeChatKernel()) {
window.initWxSdk = self.initWxSdk.bind(self);
window.initWxSdk();
}
self.enableInteractiveControls(false);
const date = Number(res.expiresAt);
const selfPlayer = {
expiresAt: date,
playerId: res.playerId,
intAuthToken: res.intAuthToken,
avatar: res.avatar,
displayName: res.displayName,
name: res.name,
}
cc.sys.localStorage.setItem('selfPlayer', JSON.stringify(selfPlayer));
console.log("cc.sys.localStorage.selfPlayer = ", cc.sys.localStorage.getItem('selfPlayer'));
if (self.countdownTimer) {
clearInterval(self.countdownTimer);
}
const inputControls = self.backgroundNode.getChildByName("InteractiveControls");
self.backgroundNode.removeChild(inputControls);
safelyAddChild(self.backgroundNode, self.loadingNode);
self.loadingNode.getChildByName('loadingSprite').runAction(
cc.repeatForever(cc.rotateBy(1.0, 360))
);
cc.director.loadScene('default_map');
} else {
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.enableInteractiveControls(true);
switch (res.ret) {
case self.retCodeDict.DUPLICATED:
this.phoneNumberTips.getComponent(cc.Label).string = constants.ALERT.TIP_LABEL.LOG_OUT;
break;
case this.retCodeDict.TOKEN_EXPIRED:
this.captchaTips.getComponent(cc.Label).string = constants.ALERT.TIP_LABEL.TOKEN_EXPIRED;
break;
case this.retCodeDict.SMS_CAPTCHA_NOT_MATCH:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_NOT_MATCH");
break;
case this.retCodeDict.INCORRECT_CAPTCHA:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_NOT_MATCH");
break;
case this.retCodeDict.SMS_CAPTCHA_CODE_NOT_EXISTING:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_NOT_MATCH");
break;
case this.retCodeDict.INCORRECT_PHONE_NUMBER:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.INCORRECT_PHONE_NUMBER");
break;
case this.retCodeDict.INVALID_REQUEST_PARAM:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.INCORRECT_PHONE_NUMBER");
break;
case this.retCodeDict.INCORRECT_PHONE_COUNTRY_CODE:
this.captchaTips.getComponent(cc.Label).string = constants.ALERT.TIP_LABEL.INCORRECT_PHONE_COUNTRY_CODE;
break;
default:
break;
}
}
},
useWXCodeLogin(_code) {
const self = this;
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.WECHAT + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: {
code: _code
},
success: function(res) {
self.onWechatLoggedIn(res);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `useWXCodeLogin` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.wechatLoginTips.string = constants.ALERT.TIP_LABEL.WECHAT_LOGIN_FAILS + ", errorMsg =" + errMsg;
window.history.replaceState({}, null, window.location.pathname);
},
});
},
getWechatCode(evt) {
let self = this;
self.wechatLoginTips.string = "";
const wechatServerEndpoint = wechatAddress.PROTOCOL + "://" + wechatAddress.HOST + ((null != wechatAddress.PORT && "" != wechatAddress.PORT.trim()) ? (":" + wechatAddress.PORT) : "");
const url = wechatServerEndpoint + constants.WECHAT.AUTHORIZE_PATH + "?" + wechatAddress.APPID_LITERAL + "&" + constants.WECHAT.REDIRECT_RUI_KEY + NetworkUtils.encode(window.location.href) + "&" + constants.WECHAT.RESPONSE_TYPE + "&" + constants.WECHAT.SCOPE + constants.WECHAT.FIN;
console.log("To visit wechat auth addr: " + url);
window.location.href = url;
},
initWxSdk() {
const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
const origUrl = window.location.protocol + "//" + window.location.host + window.location.pathname;
/*
* The `shareLink` must
* - have its 2nd-order-domain registered as trusted 2nd-order under the targetd `res.jsConfig.app_id`, and
* - extracted from current window.location.href.
*/
const shareLink = origUrl;
const updateAppMsgShareDataObj = {
type: 'link', // 分享类型,music、video或link不填默认为link
dataUrl: '', // 如果type是music或video则要提供数据链接默认为空
title: document.title, // 分享标题
desc: 'Let\'s play together!', // 分享描述
link: shareLink + (cc.sys.localStorage.getItem('boundRoomId') ? "" : ("?expectedRoomId=" + cc.sys.localStorage.getItem('boundRoomId'))),
imgUrl: origUrl + "/favicon.ico", // 分享图标
success: function() {
// 设置成功
}
};
const menuShareTimelineObj = {
title: document.title, // 分享标题
link: shareLink + (cc.sys.localStorage.getItem('boundRoomId') ? "" : ("?expectedRoomId=" + cc.sys.localStorage.getItem('boundRoomId'))),
imgUrl: origUrl + "/favicon.ico", // 分享图标
success: function() {}
};
const wxConfigUrl = (window.isUsingWebkitWechatKernel() ? window.atFirstLocationHref : window.location.href);
//接入微信登录接口
NetworkUtils.ajax({
"url": backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.WECHAT + constants.ROUTE_PATH.JSCONFIG,
type: "POST",
data: {
"url": wxConfigUrl,
"intAuthToken": selfPlayer.intAuthToken,
},
success: function(res) {
if (constants.RET_CODE.OK != res.ret) {
console.log("cannot get the wsConfig. retCode == " + res.ret);
return;
}
const jsConfig = res.jsConfig;
console.log(updateAppMsgShareDataObj);
const configData = {
debug: CC_DEBUG, // 开启调试模式,调用的所有api的返回值会在客户端alert出来若要查看传入的参数可以在pc端打开参数信息会通过log打出仅在pc端时才会打印。
appId: jsConfig.app_id, // 必填,公众号的唯一标识
timestamp: jsConfig.timestamp.toString(), // 必填,生成签名的时间戳
nonceStr: jsConfig.nonce_str, // 必填,生成签名的随机串
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline'],
signature: jsConfig.signature, // 必填,签名
};
console.log("config url: " + wxConfigUrl);
console.log("wx.config: ");
console.log(configData);
wx.config(configData);
console.log("Current window.location.href: " + window.location.href);
wx.ready(function() {
console.log("Here is wx.ready.")
wx.onMenuShareAppMessage(updateAppMsgShareDataObj);
wx.onMenuShareTimeline(menuShareTimelineObj);
});
wx.error(function(res) {
console.error("wx config fails and error is " + JSON.stringify(res));
});
},
error: function(xhr, status, errMsg) {
console.log("cannot get the wsConfig. errMsg == " + errMsg);
},
});
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "12a3d94d-56bd-42d2-8a2e-da1d27168980",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "41d304ce-6a68-4d2d-92ab-5219de6e8638",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,66 @@
cc.Class({
extends: cc.Component,
properties: {
BGMEffect: {
type: cc.AudioClip,
default: null
},
crashedByTrapBullet: {
type: cc.AudioClip,
default: null
},
highScoreTreasurePicked: {
type: cc.AudioClip,
default: null
},
treasurePicked: {
type: cc.AudioClip,
default: null
},
countDown10SecToEnd: {
type: cc.AudioClip,
default: null
},
mapNode: {
type: cc.Node,
default: null
},
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
cc.audioEngine.setEffectsVolume(1);
cc.audioEngine.setMusicVolume(0.5);
},
stopAllMusic() {
cc.audioEngine.stopAll();
},
playBGM() {
if(this.BGMEffect) {
cc.audioEngine.playMusic(this.BGMEffect, true);
}
},
playCrashedByTrapBullet() {
if(this.crashedByTrapBullet) {
cc.audioEngine.playEffect(this.crashedByTrapBullet, false);
}
},
playHighScoreTreasurePicked() {
if(this.highScoreTreasurePicked) {
cc.audioEngine.playEffect(this.highScoreTreasurePicked, false);
}
},
playTreasurePicked() {
if(this.treasurePicked) {
cc.audioEngine.playEffect(this.treasurePicked, false);
}
},
playCountDown10SecToEnd() {
if(this.countDown10SecToEnd) {
cc.audioEngine.playEffect(this.countDown10SecToEnd, false);
}
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "09e1bfed-132e-4ada-a68f-229a870db69e",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,337 @@
const COLLISION_WITH_PLAYER_STATE = {
WALKING_COLLIDABLE: 0,
STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM: 1,
STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM: 2,
STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM: 3,
STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM: 4,
STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM: 5,
STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM: 6,
WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER: 7,
STILL_NEAR_NOBODY_PLAYING_ANIM: 8,
};
const STILL_NEAR_SELF_PLAYER_STATE_SET = new Set();
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM);
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM);
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM);
STILL_NEAR_SELF_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM);
const STILL_NEAR_OTHER_PLAYER_STATE_SET = new Set();
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM);
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM);
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM);
STILL_NEAR_OTHER_PLAYER_STATE_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM);
const STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET = new Set();
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM);
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM);
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM);
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM);
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM);
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM);
STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.add(COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM);
function transitWalkingConditionallyCollidableToUnconditionallyCollidable(currentCollisionWithPlayerState) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER:
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE;
}
return currentCollisionWithPlayerState;
}
function transitUponSelfPlayerLeftProximityArea(currentCollisionWithPlayerState) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM:
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM:
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER;
}
return currentCollisionWithPlayerState;
}
function transitDueToNoBodyInProximityArea(currentCollisionWithPlayerState) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM:
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM:
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM:
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM:
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER;
}
return currentCollisionWithPlayerState;
}
function transitToPlayingStunnedAnim(currentCollisionWithPlayerState, dueToSelfPlayer, dueToOtherPlayer) {
if (dueToSelfPlayer) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE:
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM;
}
}
if (dueToOtherPlayer) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM;
}
}
// TODO: Any error to throw?
return currentCollisionWithPlayerState;
}
function transitDuringPlayingStunnedAnim(currentCollisionWithPlayerState, dueToSelfPlayerComesIntoProximity, dueToOtherPlayerComesIntoProximity) {
if (dueToSelfPlayerComesIntoProximity) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM;
}
}
if (dueToOtherPlayerComesIntoProximity) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM;
}
}
// TODO: Any error to throw?
return currentCollisionWithPlayerState;
}
function transitStunnedAnimPlayingToPlayed(currentCollisionWithPlayerState, forceNotCollidableWithOtherPlayer) {
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYING_ANIM:
return COLLISION_WITH_PLAYER_STATE.STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM;
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_NOBODY_PLAYING_ANIM:
return (true == forceNotCollidableWithOtherPlayer ? COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER : COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE);
}
// TODO: Any error to throw?
return currentCollisionWithPlayerState;
}
function transitStunnedAnimPlayedToWalking(currentCollisionWithPlayerState) {
/*
* Intentionally NOT transiting for
*
* - STILL_NEAR_SELF_PLAYER_NEAR_OTHER_PLAYER_PLAYED_ANIM, or
* - STILL_NEAR_SELF_PLAYER_ONLY_PLAYED_ANIM,
*
* which should be transited upon leaving of "SelfPlayer".
*/
switch (currentCollisionWithPlayerState) {
case COLLISION_WITH_PLAYER_STATE.STILL_NEAR_OTHER_PLAYER_ONLY_PLAYED_ANIM:
return COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER;
}
// TODO: Any error to throw?
return currentCollisionWithPlayerState;
}
const BasePlayer = require("./BasePlayer");
cc.Class({
extends: BasePlayer,
// LIFE-CYCLE CALLBACKS:
start() {
BasePlayer.prototype.start.call(this);
this.scheduleNewDirection(this._generateRandomDirectionExcluding(0, 0));
},
onLoad() {
BasePlayer.prototype.onLoad.call(this);
const self = this;
this.collisionWithPlayerState = COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE;
this.clips = {
'01': 'FlatHeadSisterRunTop',
'0-1': 'FlatHeadSisterRunBottom',
'-20': 'FlatHeadSisterRunLeft',
'20': 'FlatHeadSisterRunRight',
'-21': 'FlatHeadSisterRunTopLeft',
'21': 'FlatHeadSisterRunTopRight',
'-2-1': 'FlatHeadSisterRunBottomLeft',
'2-1': 'FlatHeadSisterRunBottomRight'
};
self.onStunnedAnimPlayedSafe = () => {
const oldCollisionWithPlayerState = self.collisionWithPlayerState;
self.collisionWithPlayerState = transitStunnedAnimPlayingToPlayed(this.collisionWithPlayerState, true);
if (oldCollisionWithPlayerState == self.collisionWithPlayerState || !self.node) return;
// TODO: Be more specific with "toExcludeDx" and "toExcludeDy".
self.scheduleNewDirection(self._generateRandomDirectionExcluding(0, 0));
self.collisionWithPlayerState = transitStunnedAnimPlayedToWalking(self.collisionWithPlayerState);
setTimeout(() => {
self.collisionWithPlayerState = transitWalkingConditionallyCollidableToUnconditionallyCollidable(self.collisionWithPlayerState);
}, 5000);
};
self.onStunnedAnimPlayedSafeAction = cc.callFunc(self.onStunnedAnimPlayedSafe, self);
self.playStunnedAnim = () => {
let colliededAction1 = cc.rotateTo(0.2, -15);
let colliededAction2 = cc.rotateTo(0.3, 15);
let colliededAction3 = cc.rotateTo(0.2, 0);
self.node.runAction(cc.sequence(
cc.callFunc(() => {
self.player.pause()
}, self),
colliededAction1,
colliededAction2,
colliededAction3,
cc.callFunc(() => {
self.player.resume()
}, self),
self.onStunnedAnimPlayedSafeAction
));
// NOTE: Use <cc.Animation>.on('stop', self.onStunnedAnimPlayedSafe) if necessary.
}
},
_canMoveBy(vecToMoveBy) {
if (COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE_WITH_SELF_PLAYER_BUT_NOT_OTHER_PLAYER != this.collisionWithPlayerState && COLLISION_WITH_PLAYER_STATE.WALKING_COLLIDABLE != this.collisionWithPlayerState) {
return false;
}
const superRet = BasePlayer.prototype._canMoveBy.call(this, vecToMoveBy);
const self = this;
const computedNewDifferentPosLocalToParentWithinCurrentFrame = self.node.position.add(vecToMoveBy);
const currentSelfColliderCircle = self.node.getComponent("cc.CircleCollider");
let nextSelfColliderCircle = null;
if (0 < self.contactedBarriers.length || 0 < self.contactedNPCPlayers.length || 0 < self.contactedControlledPlayers) {
/* To avoid unexpected buckling. */
const mutatedVecToMoveBy = vecToMoveBy.mul(2);
nextSelfColliderCircle = {
position: self.node.position.add(vecToMoveBy.mul(2)).add(currentSelfColliderCircle.offset),
radius: currentSelfColliderCircle.radius,
};
} else {
nextSelfColliderCircle = {
position: computedNewDifferentPosLocalToParentWithinCurrentFrame.add(currentSelfColliderCircle.offset),
radius: currentSelfColliderCircle.radius,
};
}
for (let aCircleCollider of self.contactedControlledPlayers) {
let contactedCircleLocalToParentWithinCurrentFrame = {
position: aCircleCollider.node.position.add(aCircleCollider.offset),
radius: aCircleCollider.radius,
};
if (cc.Intersection.circleCircle(contactedCircleLocalToParentWithinCurrentFrame, nextSelfColliderCircle)) {
return false;
}
}
return superRet;
},
update(dt) {
const self = this;
BasePlayer.prototype.update.call(this, dt);
if (0 < self.contactedBarriers.length) {
self.scheduleNewDirection(self._generateRandomDirectionExcluding(self.scheduledDirection.dx, self.scheduledDirection.dy));
}
if (tileCollisionManager.isOutOfMapNode(self.mapNode, self.computedNewDifferentPosLocalToParentWithinCurrentFrame)) {
self.scheduleNewDirection(self._generateRandomDirectionExcluding(self.scheduledDirection.dx, self.scheduledDirection.dy));
}
},
onCollisionEnter(other, self) {
BasePlayer.prototype.onCollisionEnter.call(this, other, self);
const playerScriptIns = self.getComponent(self.node.name);
switch (other.node.name) {
case "SelfPlayer":
playerScriptIns._addContactedControlledPlayers(other);
if (1 == playerScriptIns.contactedControlledPlayers.length) {
// When "SelfPlayer" comes into proximity area.
if (!STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.has(playerScriptIns.collisionWithPlayerState)) {
playerScriptIns.collisionWithPlayerState = transitToPlayingStunnedAnim(playerScriptIns.collisionWithPlayerState, true, false);
playerScriptIns.playStunnedAnim();
} else {
playerScriptIns.collisionWithPlayerState = transitDuringPlayingStunnedAnim(playerScriptIns.collisionWithPlayerState, true, false);
}
}
break;
case "NPCPlayer":
if (1 == playerScriptIns.contactedNPCPlayers.length) {
// When one of the other "OtherPlayer"s comes into proximity area.
if (!STILL_SHOULD_NOT_PLAY_STUNNED_ANIM_SET.has(playerScriptIns.collisionWithPlayerState)) {
const oldState = playerScriptIns.collisionWithPlayerState;
playerScriptIns.collisionWithPlayerState = transitToPlayingStunnedAnim(oldState, false, true);
if (playerScriptIns.collisionWithPlayerState != oldState) {
playerScriptIns.playStunnedAnim();
}
} else {
playerScriptIns.collisionWithPlayerState = transitDuringPlayingStunnedAnim(playerScriptIns.collisionWithPlayerState, false, true);
}
}
break;
default:
break;
}
},
onCollisionStay(other, self) {
// TBD.
},
onCollisionExit(other, self) {
BasePlayer.prototype.onCollisionExit.call(this, other, self);
const playerScriptIns = self.getComponent(self.node.name);
switch (other.node.name) {
case "SelfPlayer":
playerScriptIns._removeContactedControlledPlayer(other);
if (0 == playerScriptIns.contactedControlledPlayers.length) {
// Special release step.
if (STILL_NEAR_SELF_PLAYER_STATE_SET.has(playerScriptIns.collisionWithPlayerState)) {
playerScriptIns.collisionWithPlayerState = transitUponSelfPlayerLeftProximityArea(playerScriptIns.collisionWithPlayerState);
}
}
if (0 == playerScriptIns.contactedControlledPlayers.length && 0 == playerScriptIns.contactedNPCPlayers.length) {
transitDueToNoBodyInProximityArea(playerScriptIns.collisionWithPlayerState);
}
break;
case "NPCPlayer":
if (0 == playerScriptIns.contactedControlledPlayers.length && 0 == playerScriptIns.contactedNPCPlayers.length) {
transitDueToNoBodyInProximityArea(playerScriptIns.collisionWithPlayerState);
}
break;
default:
break;
}
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "17759956-1f8c-421f-bac2-7f4dd7ccdcda",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,53 @@
cc.Class({
extends: cc.Component,
properties: {
listNode: {
type: cc.Node,
default: null,
}
},
// LIFE-CYCLE CALLBACKS:
updateData(playerMeta) {
const joinIndex = playerMeta.joinIndex;
const playerNode = this.listNode.getChildByName("player" + joinIndex);
if (!playerNode) {
return;
}
const playerNameLabelNode = playerNode.getChildByName("name");
function isEmptyString(str) {
return str == null || str == ''
}
const nameToDisplay = (() => {
if (!isEmptyString(playerMeta.displayName)) {
return playerMeta.displayName;
} else if (!isEmptyString(playerMeta.name)) {
return playerMeta.name;
} else {
return ""
}
})();
playerNameLabelNode.getComponent(cc.Label).string = nameToDisplay;
const score = (playerMeta.score ? playerMeta.score : 0);
const playerScoreLabelNode = playerNode.getChildByName("score");
playerScoreLabelNode.getComponent(cc.Label).string = score;
},
onLoad() {},
clearInfo() {
for (let i = 1; i < 3; i++) {
const playerNode = this.listNode.getChildByName('player' + i);
const playerScoreLabelNode = playerNode.getChildByName("score");
const playerNameLabelNode = playerNode.getChildByName("name");
playerScoreLabelNode.getComponent(cc.Label).string = '';
playerNameLabelNode.getComponent(cc.Label).string = '';
}
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "846cee45-4ca9-4383-8a74-c6a8f3c35617",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,13 @@
const Bullet = require("./Bullet");
cc.Class({
extends: Bullet,
// LIFE-CYCLE CALLBACKS:
properties: {
},
onLoad() {
Bullet.prototype.onLoad.call(this);
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "c3bb6519-af90-4641-bb5e-5abbbcdfa6da",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,163 @@
const i18n = require('LanguageData');
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
cc.Class({
extends: cc.Component,
properties: {
onCloseDelegate: {
type: cc.Object,
default: null
},
onAgainClicked: {
type: cc.Object,
default: null
},
myAvatarNode: {
type: cc.Node,
default: null,
},
myNameNode: {
type: cc.Node,
default: null,
},
rankingNodes: {
type: [cc.Node],
default: [],
},
winNode: {
type: cc.Node,
default: null,
},
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
},
againBtnOnClick(evt) {
this.onClose();
if (!this.onAgainClicked) return;
this.onAgainClicked();
},
homeBtnOnClick(evt) {
this.onClose();
window.clearLocalStorageAndBackToLoginScene();
},
showPlayerInfo(playerRichInfoDict) {
this.showRanking(playerRichInfoDict);
this.showMyAvatar();
this.showMyName();
},
showMyName() {
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
let name = 'No name';
if (null == selfPlayerInfo.displayName || "" == selfPlayerInfo.displayName) {
name = selfPlayerInfo.name;
} else {
name = selfPlayerInfo.displayName;
}
if (!this.myNameNode) return;
const myNameNodeLabel = this.myNameNode.getComponent(cc.Label);
if (!myNameNodeLabel || null == name) return;
myNameNodeLabel.string = name;
},
showRanking(playerRichInfoDict) {
const self = this;
const sortablePlayers = [];
for (let playerId in playerRichInfoDict) {
const p = playerRichInfoDict[playerId];
p.id = playerId;
if (null == p.score) {
p.score = playerRichInfoDict[playerId].score;
}
if (null == p.score) {
p.score = 0;
}
sortablePlayers.push(p);
}
const sortedPlayers = sortablePlayers.sort((a, b) => {
if (a.score != b.score) {
return (b.score - a.score);
} else {
return (a.id > b.id);
}
});
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
for (let k in sortedPlayers) {
const p = sortedPlayers[k];
const nameToDisplay = (() => {
function isEmptyString(str) {
return str == null || str == '';
}
if (!isEmptyString(p.displayName)) {
return p.displayName;
} else if (!isEmptyString(p.name)) {
return p.name;
} else {
return "";
}
})();
if (selfPlayerInfo.playerId == p.id) {
const rank = k + 1;
if (1 != rank && null != self.winNode) {
self.winNode.active = false;
}
}
self.rankingNodes[k].getChildByName('name').getComponent(cc.Label).string = nameToDisplay;
self.rankingNodes[k].getChildByName('score').getComponent(cc.Label).string = playerRichInfoDict[p.id].score;
}
},
showMyAvatar() {
const self = this;
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
let remoteUrl = selfPlayerInfo.avatar;
if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for myself, check storage.`);
return;
} else {
cc.loader.load({
url: remoteUrl,
type: 'jpg'
}, function(err, texture) {
if (err != null || texture == null) {
console.log(err);
} else {
const sf = new cc.SpriteFrame();
sf.setTexture(texture);
self.myAvatarNode.getComponent(cc.Sprite).spriteFrame = sf;
}
});
}
},
showRibbon(winnerInfo, ribbonNode) {
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
const texture = (selfPlayerInfo.playerId == winnerInfo.id) ? "textures/resultPanel/WinRibbon" : "textures/resultPanel/loseRibbon";
cc.loader.loadRes(texture, cc.SpriteFrame, function(err, spriteFrame) {
if (err) {
console.log(err);
return;
}
ribbonNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
});
},
onClose(evt) {
if (this.node.parent) {
this.node.parent.removeChild(this.node);
}
if (!this.onCloseDelegate) {
return;
}
this.onCloseDelegate();
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "5ae774fb-4f9c-445d-a057-5d32522b975d",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,49 @@
const BasePlayer = require("./BasePlayer");
cc.Class({
extends: BasePlayer,
// LIFE-CYCLE CALLBACKS:
properties: {
arrowTipNode: {
type: cc.Node,
default: null
}
},
start() {
BasePlayer.prototype.start.call(this);
},
onLoad() {
BasePlayer.prototype.onLoad.call(this);
this.attackedClips = {
'01': 'attackedLeft',
'0-1': 'attackedRight',
'-20': 'attackedLeft',
'20': 'attackedRight',
'-21': 'attackedLeft',
'21': 'attackedRight',
'-2-1': 'attackedLeft',
'2-1': 'attackedRight'
};
this.arrowTipNode.active = false;
},
showArrowTipNode() {
const self = this;
if (null == self.arrowTipNode) {
return;
}
self.arrowTipNode.active = true;
window.setTimeout(function(){
if (null == self.arrowTipNode) {
return;
}
self.arrowTipNode.active = false;
}, 3000)
},
update(dt) {
BasePlayer.prototype.update.call(this, dt);
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "b74b0e58-0ea6-4546-8e0e-919445657f24",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,26 @@
cc.Class({
extends: cc.Component,
properties: {
},
start() {
},
onLoad() {
},
update(dt) {
},
dismissDialog(postDismissalByYes, evt) {
const self = this;
const target = evt.target;
self.node.parent.removeChild(self.node);
if ("Yes" == target._name) {
// This is a dirty hack!
postDismissalByYes();
}
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "27562abf-fe68-427f-b598-b8e53aca6e87",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,784 @@
"use strict";
window.ALL_DISCRETE_DIRECTIONS_CLOCKWISE = [{
dx: 0,
dy: 1
}, {
dx: 2,
dy: 1
}, {
dx: 2,
dy: 0
}, {
dx: 2,
dy: -1
}, {
dx: 0,
dy: -1
}, {
dx: -2,
dy: -1
}, {
dx: -2,
dy: 0
}, {
dx: -2,
dy: 1
}];
function TileCollisionManager() { }
TileCollisionManager.prototype._continuousFromCentreOfDiscreteTile = function (tiledMapNode, tiledMapIns, layerIns, discretePosX, discretePosY) {
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
var mapAnchorOffset = cc.v2(0, 0);
var tileSize = {
width: 0,
height: 0
};
var layerOffset = cc.v2(0, 0);
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
return null;
case cc.TiledMap.Orientation.ISO:
var tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width / 4 + mapTileRectilinearSize.height * mapTileRectilinearSize.height / 4);
tileSize = {
width: tileSizeUnifiedLength,
height: tileSizeUnifiedLength
};
var cosineThetaRadian = mapTileRectilinearSize.width / 2 / tileSizeUnifiedLength;
var sineThetaRadian = mapTileRectilinearSize.height / 2 / tileSizeUnifiedLength;
mapAnchorOffset = cc.v2(
tiledMapNode.getContentSize().width * (0.5 - tiledMapNode.getAnchorPoint().x),
tiledMapNode.getContentSize().height * (1 - tiledMapNode.getAnchorPoint().y)
);
layerOffset = cc.v2(0, 0);
var transMat = [
[cosineThetaRadian, -cosineThetaRadian],
[-sineThetaRadian, -sineThetaRadian]
];
var tmpContinuousX = (parseFloat(discretePosX) + 0.5) * tileSizeUnifiedLength;
var tmpContinuousY = (parseFloat(discretePosY) + 0.5) * tileSizeUnifiedLength;
var dContinuousXWrtMapNode = transMat[0][0] * tmpContinuousX + transMat[0][1] * tmpContinuousY;
var dContinuousYWrtMapNode = transMat[1][0] * tmpContinuousX + transMat[1][1] * tmpContinuousY;
return cc.v2(dContinuousXWrtMapNode, dContinuousYWrtMapNode).add(mapAnchorOffset);
default:
return null;
}
};
TileCollisionManager.prototype._continuousToDiscrete = function (tiledMapNode, tiledMapIns, continuousNewPosLocalToMap, continuousOldPosLocalToMap) {
/*
* References
* - http://cocos2d-x.org/docs/api-ref/creator/v1.5/classes/TiledMap.html
* - http://cocos2d-x.org/docs/api-ref/creator/v1.5/classes/TiledLayer.html
* - http://docs.mapeditor.org/en/stable/reference/tmx-map-format/?highlight=orientation#map
*/
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
var mapAnchorOffset = {
x: 0,
y: 0
};
var tileSize = {
width: 0,
height: 0
};
var layerOffset = {
x: 0,
y: 0
};
var convertedContinuousOldXInTileCoordinates = null;
var convertedContinuousOldYInTileCoordinates = null;
var convertedContinuousNewXInTileCoordinates = null;
var convertedContinuousNewYInTileCoordinates = null;
var oldWholeMultipleX = 0;
var oldWholeMultipleY = 0;
var newWholeMultipleX = 0;
var newWholeMultipleY = 0;
var discretePosX = 0;
var discretePosY = 0;
var exactBorderX = 0;
var exactBorderY = 0; // These tmp variables are NOT NECESSARILY useful.
var oldTmpX = 0;
var oldTmpY = 0;
var newTmpX = 0;
var newTmpY = 0;
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
mapAnchorOffset = {
x: -(tiledMapNode.getContentSize().width * tiledMapNode.getAnchorPoint().x),
y: tiledMapNode.getContentSize().height * (1 - tiledMapNode.getAnchorPoint().y)
};
layerOffset = {
x: 0,
y: 0
};
tileSize = mapTileRectilinearSize;
convertedContinuousOldXInTileCoordinates = continuousOldPosLocalToMap.x - layerOffset.x - mapAnchorOffset.x;
convertedContinuousOldYInTileCoordinates = mapAnchorOffset.y - (continuousOldPosLocalToMap.y - layerOffset.y);
convertedContinuousNewXInTileCoordinates = continuousNewPosLocalToMap.x - layerOffset.x - mapAnchorOffset.x;
convertedContinuousNewYInTileCoordinates = mapAnchorOffset.y - (continuousNewPosLocalToMap.y - layerOffset.y);
break;
case cc.TiledMap.Orientation.ISO:
var tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width / 4 + mapTileRectilinearSize.height * mapTileRectilinearSize.height / 4);
tileSize = {
width: tileSizeUnifiedLength,
height: tileSizeUnifiedLength
};
var cosineThetaRadian = mapTileRectilinearSize.width / 2 / tileSizeUnifiedLength;
var sineThetaRadian = mapTileRectilinearSize.height / 2 / tileSizeUnifiedLength;
mapAnchorOffset = {
x: tiledMapNode.getContentSize().width * (0.5 - tiledMapNode.getAnchorPoint().x),
y: tiledMapNode.getContentSize().height * (1 - tiledMapNode.getAnchorPoint().y)
};
layerOffset = {
x: 0,
y: 0
};
oldTmpX = continuousOldPosLocalToMap.x - layerOffset.x - mapAnchorOffset.x;
oldTmpY = continuousOldPosLocalToMap.y - layerOffset.y - mapAnchorOffset.y;
newTmpX = continuousNewPosLocalToMap.x - layerOffset.x - mapAnchorOffset.x;
newTmpY = continuousNewPosLocalToMap.y - layerOffset.y - mapAnchorOffset.y;
var transMat = [[1 / (2 * cosineThetaRadian), -1 / (2 * sineThetaRadian)], [-1 / (2 * cosineThetaRadian), -1 / (2 * sineThetaRadian)]];
convertedContinuousOldXInTileCoordinates = transMat[0][0] * oldTmpX + transMat[0][1] * oldTmpY;
convertedContinuousOldYInTileCoordinates = transMat[1][0] * oldTmpX + transMat[1][1] * oldTmpY;
convertedContinuousNewXInTileCoordinates = transMat[0][0] * newTmpX + transMat[0][1] * newTmpY;
convertedContinuousNewYInTileCoordinates = transMat[1][0] * newTmpX + transMat[1][1] * newTmpY;
break;
default:
break;
}
if (null == convertedContinuousOldXInTileCoordinates || null == convertedContinuousOldYInTileCoordinates || null == convertedContinuousNewXInTileCoordinates || null == convertedContinuousNewYInTileCoordinates) {
return null;
}
oldWholeMultipleX = Math.floor(convertedContinuousOldXInTileCoordinates / tileSize.width);
oldWholeMultipleY = Math.floor(convertedContinuousOldYInTileCoordinates / tileSize.height);
newWholeMultipleX = Math.floor(convertedContinuousNewXInTileCoordinates / tileSize.width);
newWholeMultipleY = Math.floor(convertedContinuousNewYInTileCoordinates / tileSize.height); // Mind that the calculation of `exactBorderY` is different for `convertedContinuousOldYInTileCoordinates <> convertedContinuousNewYInTileCoordinates`.
if (convertedContinuousOldYInTileCoordinates < convertedContinuousNewYInTileCoordinates) {
exactBorderY = newWholeMultipleY * tileSize.height;
if (convertedContinuousNewYInTileCoordinates > exactBorderY && convertedContinuousOldYInTileCoordinates <= exactBorderY) {
// Will try to cross the border if (newWholeMultipleY != oldWholeMultipleY).
discretePosY = newWholeMultipleY;
} else {
discretePosY = oldWholeMultipleY;
}
} else if (convertedContinuousOldYInTileCoordinates > convertedContinuousNewYInTileCoordinates) {
exactBorderY = oldWholeMultipleY * tileSize.height;
if (convertedContinuousNewYInTileCoordinates < exactBorderY && convertedContinuousOldYInTileCoordinates >= exactBorderY) {
// Will try to cross the border if (newWholeMultipleY != oldWholeMultipleY).
discretePosY = newWholeMultipleY;
} else {
discretePosY = oldWholeMultipleY;
}
} else {
discretePosY = oldWholeMultipleY;
} // Mind that the calculation of `exactBorderX` is different for `convertedContinuousOldXInTileCoordinates <> convertedContinuousNewXInTileCoordinates`.
if (convertedContinuousOldXInTileCoordinates < convertedContinuousNewXInTileCoordinates) {
exactBorderX = newWholeMultipleX * tileSize.width;
if (convertedContinuousNewXInTileCoordinates > exactBorderX && convertedContinuousOldXInTileCoordinates <= exactBorderX) {
// Will cross the border if (newWholeMultipleX != oldWholeMultipleX).
discretePosX = newWholeMultipleX;
} else {
discretePosX = oldWholeMultipleX;
}
} else if (convertedContinuousOldXInTileCoordinates > convertedContinuousNewXInTileCoordinates) {
exactBorderX = oldWholeMultipleX * tileSize.width;
if (convertedContinuousNewXInTileCoordinates < exactBorderX && convertedContinuousOldXInTileCoordinates >= exactBorderX) {
// Will cross the border if (newWholeMultipleX != oldWholeMultipleX).
discretePosX = newWholeMultipleX;
} else {
discretePosX = oldWholeMultipleX;
}
} else {
discretePosX = oldWholeMultipleX;
}
return {
x: discretePosX,
y: discretePosY
};
};
TileCollisionManager.prototype.continuousMapNodeVecToContinuousObjLayerVec = function (withTiledMapNode, continuousMapNodeVec) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
case cc.TiledMap.Orientation.ISO:
var tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width * 0.25 + mapTileRectilinearSize.height * mapTileRectilinearSize.height * 0.25);
var isometricObjectLayerPointOffsetScaleFactor = (tileSizeUnifiedLength / mapTileRectilinearSize.height);
var inverseIsometricObjectLayerPointOffsetScaleFactor = 1 / isometricObjectLayerPointOffsetScaleFactor;
var cosineThetaRadian = (mapTileRectilinearSize.width * 0.5) / tileSizeUnifiedLength;
var sineThetaRadian = (mapTileRectilinearSize.height * 0.5) / tileSizeUnifiedLength;
var inverseTransMat = [
[inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / cosineThetaRadian), - inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / sineThetaRadian)],
[- inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / cosineThetaRadian), - inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / sineThetaRadian)]
];
var convertedVecX = inverseTransMat[0][0] * continuousMapNodeVec.x + inverseTransMat[0][1] * continuousMapNodeVec.y;
var convertedVecY = inverseTransMat[1][0] * continuousMapNodeVec.x + inverseTransMat[1][1] * continuousMapNodeVec.y;
return cc.v2(convertedVecX, convertedVecY);
default:
return null;
}
}
TileCollisionManager.prototype.continuousObjLayerVecToContinuousMapNodeVec = function (withTiledMapNode, continuousObjLayerVec) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
case cc.TiledMap.Orientation.ISO:
var tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width * 0.25 + mapTileRectilinearSize.height * mapTileRectilinearSize.height * 0.25);
var isometricObjectLayerPointOffsetScaleFactor = (tileSizeUnifiedLength / mapTileRectilinearSize.height);
var cosineThetaRadian = (mapTileRectilinearSize.width * 0.5) / tileSizeUnifiedLength;
var sineThetaRadian = (mapTileRectilinearSize.height * 0.5) / tileSizeUnifiedLength;
var transMat = [
[isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian, - isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian],
[- isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian, - isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian]
];
var convertedVecX = transMat[0][0] * continuousObjLayerVec.x + transMat[0][1] * continuousObjLayerVec.y;
var convertedVecY = transMat[1][0] * continuousObjLayerVec.x + transMat[1][1] * continuousObjLayerVec.y;
return cc.v2(convertedVecX, convertedVecY);
default:
return null;
}
}
TileCollisionManager.prototype.continuousObjLayerOffsetToContinuousMapNodePos = function (withTiledMapNode, continuousObjLayerOffset) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
case cc.TiledMap.Orientation.ISO:
const calibratedVec = continuousObjLayerOffset; // TODO: Respect the real offsets!
// The immediately following statement takes a magic assumption that the anchor of `withTiledMapNode` is (0.5, 0.5) which is NOT NECESSARILY true.
const layerOffset = cc.v2(0, +(withTiledMapNode.getContentSize().height * 0.5));
return layerOffset.add(this.continuousObjLayerVecToContinuousMapNodeVec(withTiledMapNode, calibratedVec));
default:
return null;
}
}
TileCollisionManager.prototype.continuousMapNodePosToContinuousObjLayerOffset = function (withTiledMapNode, continuousMapNodePos) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
case cc.TiledMap.Orientation.ISO:
// The immediately following statement takes a magic assumption that the anchor of `withTiledMapNode` is (0.5, 0.5) which is NOT NECESSARILY true.
var layerOffset = cc.v2(0, +(withTiledMapNode.getContentSize().height * 0.5));
var calibratedVec = continuousMapNodePos.sub(layerOffset); // TODO: Respect the real offsets!
return this.continuousMapNodeVecToContinuousObjLayerVec(withTiledMapNode, calibratedVec);
default:
return null;
}
}
/**
* Note that `TileCollisionManager.extractBoundaryObjects` returns everything with coordinates local to `withTiledMapNode`!
*/
window.battleEntityTypeNameToGlobalGid = {};
TileCollisionManager.prototype.extractBoundaryObjects = function (withTiledMapNode) {
let toRet = {
barriers: [],
shelters: [],
shelterChainTails: [],
shelterChainHeads: [],
sheltersZReducer: [],
frameAnimations: [],
grandBoundaries: [],
};
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
const mapTileSize = tiledMapIns.getTileSize();
const mapOrientation = tiledMapIns.getMapOrientation();
/*
* Copies from https://github.com/cocos-creator/engine/blob/master/cocos2d/tilemap/CCTiledMap.js as a hack to parse advanced <tile> info
* of a TSX file. [BEGINS]
*/
const file = tiledMapIns._tmxFile;
const texValues = file.textures;
const texKeys = file.textureNames;
const textures = {};
for (let texIdx = 0; texIdx < texValues.length; ++texIdx) {
textures[texKeys[texIdx]] = texValues[texIdx];
}
const tsxFileNames = file.tsxFileNames;
const tsxFiles = file.tsxFiles;
let tsxMap = {};
for (let tsxFilenameIdx = 0; tsxFilenameIdx < tsxFileNames.length; ++tsxFilenameIdx) {
if (0 >= tsxFileNames[tsxFilenameIdx].length) continue;
tsxMap[tsxFileNames[tsxFilenameIdx]] = tsxFiles[tsxFilenameIdx].text;
}
const mapInfo = new cc.TMXMapInfo(file.tmxXmlStr, tsxMap, textures);
const tileSets = mapInfo.getTilesets();
/*
* Copies from https://github.com/cocos-creator/engine/blob/master/cocos2d/tilemap/CCTiledMap.js as a hack to parse advanced <tile> info
* of a TSX file. [ENDS]
*/
let gidBoundariesMap = {};
const tilesElListUnderTilesets = {};
for (let tsxFilenameIdx = 0; tsxFilenameIdx < tsxFileNames.length; ++tsxFilenameIdx) {
const tsxOrientation = tileSets[tsxFilenameIdx].orientation;
if (cc.TiledMap.Orientation.ORTHO == tsxOrientation) {
cc.error("Error at tileset %s: We proceed with ONLY tilesets in ORTHO orientation for all map orientations by now.", tsxFileNames[tsxFilenameIdx]);
continue;
};
const tsxXMLStr = tsxMap[tsxFileNames[tsxFilenameIdx]];
const selTileset = mapInfo._parser._parseXML(tsxXMLStr).documentElement;
const firstGid = (parseInt(selTileset.getAttribute('firstgid')) || tileSets[tsxFilenameIdx].firstGid || 0);
const currentTiles = selTileset.getElementsByTagName('tile');
if (!currentTiles) continue;
tilesElListUnderTilesets[tsxFileNames[tsxFilenameIdx]] = currentTiles;
for (let tileIdx = 0; tileIdx < currentTiles.length; ++tileIdx) {
const currentTile = currentTiles[tileIdx];
const parentGid = parseInt(firstGid) + parseInt(currentTile.getAttribute('id') || 0);
let childrenOfCurrentTile = null;
if (cc.sys.isNative) {
childrenOfCurrentTile = currentTile.getElementsByTagName("objectgroup");
} else if (cc.sys.platform == cc.sys.WECHAT_GAME) {
childrenOfCurrentTile = currentTile.childNodes;
} else {
childrenOfCurrentTile = currentTile.children;
}
for (let childIdx = 0; childIdx < childrenOfCurrentTile.length; ++childIdx) {
const ch = childrenOfCurrentTile[childIdx];
if ('objectgroup' != ch.nodeName) continue;
var currentObjectGroupUnderTile = mapInfo._parseObjectGroup(ch);
gidBoundariesMap[parentGid] = {
barriers: [],
shelters: [],
sheltersZReducer: [],
};
for (let oidx = 0; oidx < currentObjectGroupUnderTile._objects.length; ++oidx) {
const oo = currentObjectGroupUnderTile._objects[oidx];
const polylinePoints = oo.polylinePoints;
if (null == polylinePoints) continue;
const boundaryType = oo.boundary_type;
switch (boundaryType) {
case "LowScoreTreasure":
case "HighScoreTreasure":
case "GuardTower":
const spriteFrameInfoForGid = getOrCreateSpriteFrameForGid(parentGid, mapInfo, tilesElListUnderTilesets);
if (null != spriteFrameInfoForGid) {
window.battleEntityTypeNameToGlobalGid[boundaryType] = parentGid;
}
break;
case "barrier":
let brToPushTmp = [];
for (let bidx = 0; bidx < polylinePoints.length; ++bidx) {
brToPushTmp.push(cc.v2(oo.x, oo.y).add(polylinePoints[bidx]));
}
brToPushTmp.boundaryType = boundaryType;
gidBoundariesMap[parentGid].barriers.push(brToPushTmp);
break;
case "shelter":
let shToPushTmp = [];
for (let shidx = 0; shidx < polylinePoints.length; ++shidx) {
shToPushTmp.push(cc.v2(oo.x, oo.y).add(polylinePoints[shidx]));
}
shToPushTmp.boundaryType = boundaryType;
gidBoundariesMap[parentGid].shelters.push(shToPushTmp);
break;
case "shelter_z_reducer":
let shzrToPushTmp = [];
for (let shzridx = 0; shzridx < polylinePoints.length; ++shzridx) {
shzrToPushTmp.push(cc.v2(oo.x, oo.y).add(polylinePoints[shzridx]));
}
shzrToPushTmp.boundaryType = boundaryType;
gidBoundariesMap[parentGid].sheltersZReducer.push(shzrToPushTmp);
break;
default:
break;
}
}
}
}
}
// Reference http://docs.cocos.com/creator/api/en/classes/TiledMap.html.
let allObjectGroups = tiledMapIns.getObjectGroups();
for (var i = 0; i < allObjectGroups.length; ++i) {
// Reference http://docs.cocos.com/creator/api/en/classes/TiledObjectGroup.html.
var objectGroup = allObjectGroups[i];
if ("frame_anim" != objectGroup.getProperty("type")) continue;
var allObjects = objectGroup.getObjects();
for (var j = 0; j < allObjects.length; ++j) {
var object = allObjects[j];
var gid = object.gid;
if (!gid || gid <= 0) {
continue;
}
var animationClipInfoForGid = getOrCreateAnimationClipForGid(gid, mapInfo, tilesElListUnderTilesets);
if (!animationClipInfoForGid) continue;
toRet.frameAnimations.push({
posInMapNode: this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset),
origSize: animationClipInfoForGid.origSize,
sizeInMapNode: cc.size(object.width, object.height),
animationClip: animationClipInfoForGid.animationClip
});
}
}
for (let i = 0; i < allObjectGroups.length; ++i) {
var objectGroup = allObjectGroups[i];
if ("barrier_and_shelter" != objectGroup.getProperty("type")) continue;
var allObjects = objectGroup.getObjects();
for (let j = 0; j < allObjects.length; ++j) {
let object = allObjects[j];
let gid = object.gid;
if (0 < gid) {
continue;
}
const polylinePoints = object.polylinePoints;
if (null == polylinePoints) {
continue
}
for (let k = 0; k < polylinePoints.length; ++k) {
/* Since CocosCreatorv2.1.3, the Y-coord of object polylines DIRECTLY DRAWN ON tmx with ISOMETRIC ORIENTATION is inverted. -- YFLu, 2019-11-01. */
polylinePoints[k].y = -polylinePoints[k].y;
}
const boundaryType = object.boundary_type;
switch (boundaryType) {
case "barrier":
let toPushBarriers = [];
for (let k = 0; k < polylinePoints.length; ++k) {
const tmp = object.offset.add(polylinePoints[k]);
toPushBarriers.push(this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, tmp));
}
if (null != object.debug_mark) {
console.log("Transformed ", polylinePoints, ", to ", toPushBarriers);
}
toPushBarriers.boundaryType = boundaryType;
toRet.barriers.push(toPushBarriers);
break;
case "shelter":
let toPushShelters = [];
for (let kk = 0; kk < polylinePoints.length; ++kk) {
toPushShelters.push(this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset.add(polylinePoints[kk])));
}
toPushShelters.boundaryType = boundaryType;
toRet.shelters.push(toPushShelters);
break;
case "shelter_z_reducer":
let toPushSheltersZReducer = [];
for (let kkk = 0; kkk < polylinePoints.length; ++kkk) {
toPushSheltersZReducer.push(this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset.add(polylinePoints[kkk])));
}
toPushSheltersZReducer.boundaryType = boundaryType;
toRet.sheltersZReducer.push(toPushSheltersZReducer);
break;
default:
break;
}
}
}
const allLayers = tiledMapIns.getLayers();
let layerDOMTrees = [];
const mapDomTree = mapInfo._parser._parseXML(tiledMapIns.tmxAsset.tmxXmlStr).documentElement;
const mapDOMAllChildren = (cc.sys.platform == cc.sys.WECHAT_GAME ? mapDomTree.childNodes : mapDomTree.children);
for (let mdtIdx = 0; mdtIdx < mapDOMAllChildren.length; ++mdtIdx) {
const tmpCh = mapDOMAllChildren[mdtIdx];
if (mapInfo._shouldIgnoreNode(tmpCh)) {
continue;
}
if (tmpCh.nodeName != 'layer') {
continue;
}
layerDOMTrees.push(tmpCh);
}
for (let j = 0; j < allLayers.length; ++j) {
// TODO: Respect layer offset!
const currentTileLayer = allLayers[j];
const currentTileset = currentTileLayer.getTileSet();
if (!currentTileset) {
continue;
}
const currentLayerSize = currentTileLayer.getLayerSize();
const currentLayerTileSize = currentTileset._tileSize;
const firstGidInCurrentTileset = currentTileset.firstGid;
for (let discreteXInLayer = 0; discreteXInLayer < currentLayerSize.width; ++discreteXInLayer) {
for (let discreteYInLayer = 0; discreteYInLayer < currentLayerSize.height; ++discreteYInLayer) {
const currentGid = currentTileLayer.getTileGIDAt(discreteXInLayer, discreteYInLayer);
if (0 >= currentGid) continue;
const gidBoundaries = gidBoundariesMap[currentGid];
if (!gidBoundaries) continue;
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return toRet;
case cc.TiledMap.Orientation.ISO:
const centreOfAnchorTileInMapNode = this._continuousFromCentreOfDiscreteTile(withTiledMapNode, tiledMapIns, currentTileLayer, discreteXInLayer, discreteYInLayer);
const topLeftOfWholeTsxTileInMapNode = centreOfAnchorTileInMapNode.add(cc.v2(-0.5 * mapTileSize.width, currentLayerTileSize.height - 0.5 * mapTileSize.height));
for (let bidx = 0; bidx < gidBoundaries.barriers.length; ++bidx) {
const theBarrier = gidBoundaries.barriers[bidx]; // An array of cc.v2 points.
let brToPushTmp = [];
for (let tbidx = 0; tbidx < theBarrier.length; ++tbidx) {
brToPushTmp.push(topLeftOfWholeTsxTileInMapNode.add(cc.v2(theBarrier[tbidx].x, -theBarrier[tbidx].y /* Mind the reverse y-axis here. */)));
}
toRet.barriers.push(brToPushTmp);
}
for (let shidx = 0; shidx < gidBoundaries.shelters.length; ++shzridx) {
const theShelter = gidBoundaries.shelters[shidx]; // An array of cc.v2 points.
let shToPushTmp = [];
for (let tshidx = 0; tshidx < theShelter.length; ++tshidx) {
shToPushTmp.push(topLeftOfWholeTsxTileInMapNode.add(cc.v2(theShelter[tshidx].x, -theShelter[tshidx].y)));
}
toRet.shelters.push(shToPushTmp);
}
for (let shzridx = 0; shzridx < gidBoundaries.sheltersZReducer.length; ++shzridx) {
const theShelter = gidBoundaries.sheltersZReducer[shzridx]; // An array of cc.v2 points.
let shzrToPushTmp = [];
for (let tshzridx = 0; tshzridx < theShelter.length; ++tshzridx) {
shzrToPushTmp.push(topLeftOfWholeTsxTileInMapNode.add(cc.v2(theShelter[tshzridx].x, -theShelter[tshzridx].y)));
}
toRet.sheltersZReducer.push(shzrToPushTmp);
}
continue;
default:
return toRet;
}
}
}
}
return toRet;
}
TileCollisionManager.prototype.isOutOfMapNode = function (tiledMapNode, continuousPosLocalToMap) {
var tiledMapIns = tiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
var mapContentSize = cc.size(tiledMapIns.getTileSize().width * tiledMapIns.getMapSize().width, tiledMapIns.getTileSize().height * tiledMapIns.getMapSize().height);
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return true;
case cc.TiledMap.Orientation.ISO:
var continuousObjLayerOffset = this.continuousMapNodePosToContinuousObjLayerOffset(tiledMapNode, continuousPosLocalToMap);
return 0 > continuousObjLayerOffset.x || 0 > continuousObjLayerOffset.y || mapContentSize.width < continuousObjLayerOffset.x || mapContentSize.height < continuousObjLayerOffset.y;
default:
return true;
}
return true;
};
TileCollisionManager.prototype.initMapNodeByTiledBoundaries = function(mapScriptIns, mapNode, extractedBoundaryObjs) {
const tiledMapIns = mapNode.getComponent(cc.TiledMap);
if (extractedBoundaryObjs.grandBoundaries) {
window.grandBoundary = [];
for (let boundaryObj of extractedBoundaryObjs.grandBoundaries) {
for (let p of boundaryObj) {
if (CC_DEBUG) {
const labelNode = new cc.Node();
labelNode.setPosition(p);
const label = labelNode.addComponent(cc.Label);
label.string = "GB_(" + p.x.toFixed(2) + ", " + p.y.toFixed(2) + ")";
safelyAddChild(mapNode, labelNode);
setLocalZOrder(labelNode, 999);
}
window.grandBoundary.push(p);
}
break;
}
}
mapScriptIns.dictOfTiledFrameAnimationList = {};
for (let frameAnim of extractedBoundaryObjs.frameAnimations) {
if (!frameAnim.type) {
cc.warn("should bind a type to the frameAnim object layer");
continue
}
const tiledMapIns = mapScriptIns.node.getComponent(cc.TiledMap);
let frameAnimInType = mapScriptIns.dictOfTiledFrameAnimationList[frameAnim.type];
if (!frameAnimInType) {
mapScriptIns.dictOfTiledFrameAnimationList[frameAnim.type] = [];
frameAnimInType = mapScriptIns.dictOfTiledFrameAnimationList[frameAnim.type];
}
const animNode = cc.instantiate(mapScriptIns.tiledAnimPrefab);
const anim = animNode.getComponent(cc.Animation);
animNode.setPosition(frameAnim.posInMapNode);
animNode.width = frameAnim.sizeInMapNode.width;
animNode.height = frameAnim.sizeInMapNode.height;
animNode.setScale(frameAnim.sizeInMapNode.width / frameAnim.origSize.width, frameAnim.sizeInMapNode.height / frameAnim.origSize.height);
animNode.opacity = 0;
animNode.setAnchorPoint(cc.v2(0.5, 0)); // A special requirement for "image-type Tiled object" by "CocosCreator v2.0.1".
safelyAddChild(mapScriptIns.node, animNode);
setLocalZOrder(animNode, 5);
anim.addClip(frameAnim.animationClip, "default");
anim.play("default");
frameAnimInType.push(animNode);
}
for (let boundaryObj of extractedBoundaryObjs.shelterChainTails) {
const newShelter = cc.instantiate(mapScriptIns.polygonBoundaryShelterPrefab);
const newBoundaryOffsetInMapNode = cc.v2(boundaryObj[0].x, boundaryObj[0].y);
newShelter.setPosition(newBoundaryOffsetInMapNode);
newShelter.setAnchorPoint(cc.v2(0, 0));
const newShelterColliderIns = newShelter.getComponent(cc.PolygonCollider);
newShelterColliderIns.points = [];
for (let p of boundaryObj) {
newShelterColliderIns.points.push(p.sub(newBoundaryOffsetInMapNode));
}
newShelter.pTiledLayer = boundaryObj.pTiledLayer;
newShelter.tileDiscretePos = boundaryObj.tileDiscretePos;
if (null != boundaryObj.imageObject) {
newShelter.imageObject = boundaryObj.imageObject;
newShelter.tailOrHead = "tail";
window.addToGlobalShelterChainVerticeMap(newShelter.imageObject.imageObjectNode); // Deliberately NOT adding at the "traversal of shelterChainHeads".
}
newShelter.boundaryObj = boundaryObj;
mapScriptIns.node.addChild(newShelter);
}
for (let boundaryObj of extractedBoundaryObjs.shelterChainHeads) {
const newShelter = cc.instantiate(mapScriptIns.polygonBoundaryShelterPrefab);
const newBoundaryOffsetInMapNode = cc.v2(boundaryObj[0].x, boundaryObj[0].y);
newShelter.setPosition(newBoundaryOffsetInMapNode);
newShelter.setAnchorPoint(cc.v2(0, 0));
const newShelterColliderIns = newShelter.getComponent(cc.PolygonCollider);
newShelterColliderIns.points = [];
for (let p of boundaryObj) {
newShelterColliderIns.points.push(p.sub(newBoundaryOffsetInMapNode));
}
newShelter.pTiledLayer = boundaryObj.pTiledLayer;
newShelter.tileDiscretePos = boundaryObj.tileDiscretePos;
if (null != boundaryObj.imageObject) {
newShelter.imageObject = boundaryObj.imageObject;
newShelter.tailOrHead = "head";
}
newShelter.boundaryObj = boundaryObj;
mapScriptIns.node.addChild(newShelter);
}
mapScriptIns.barrierColliders = [];
for (let boundaryObj of extractedBoundaryObjs.barriers) {
const newBarrier = cc.instantiate(mapScriptIns.polygonBoundaryBarrierPrefab);
const newBoundaryOffsetInMapNode = cc.v2(boundaryObj[0].x, boundaryObj[0].y);
newBarrier.setPosition(newBoundaryOffsetInMapNode);
newBarrier.setAnchorPoint(cc.v2(0, 0));
const newBarrierColliderIns = newBarrier.getComponent(cc.PolygonCollider);
newBarrierColliderIns.points = [];
for (let p of boundaryObj) {
newBarrierColliderIns.points.push(p.sub(newBoundaryOffsetInMapNode));
}
mapScriptIns.barrierColliders.push(newBarrierColliderIns);
mapScriptIns.node.addChild(newBarrier);
}
for (let boundaryObj of extractedBoundaryObjs.sheltersZReducer) {
const newShelter = cc.instantiate(mapScriptIns.polygonBoundaryShelterZReducerPrefab);
const newBoundaryOffsetInMapNode = cc.v2(boundaryObj[0].x, boundaryObj[0].y);
newShelter.setPosition(newBoundaryOffsetInMapNode);
newShelter.setAnchorPoint(cc.v2(0, 0));
const newShelterColliderIns = newShelter.getComponent(cc.PolygonCollider);
newShelterColliderIns.points = [];
for (let p of boundaryObj) {
newShelterColliderIns.points.push(p.sub(newBoundaryOffsetInMapNode));
}
mapScriptIns.node.addChild(newShelter);
}
const allLayers = tiledMapIns.getLayers();
for (let layer of allLayers) {
const layerType = layer.getProperty("type");
switch (layerType) {
case "barrier_and_shelter":
setLocalZOrder(layer.node, 3);
break;
case "shelter_preview":
layer.node.opacity = 100;
setLocalZOrder(layer.node, 500);
break;
default:
break;
}
}
const allObjectGroups = tiledMapIns.getObjectGroups();
for (let objectGroup of allObjectGroups) {
const objectGroupType = objectGroup.getProperty("type");
switch (objectGroupType) {
case "barrier_and_shelter":
setLocalZOrder(objectGroup.node, 3);
break;
default:
break;
}
}
}
window.tileCollisionManager = new TileCollisionManager();

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "91a92fb7-f06a-4b7e-8438-eb743ee49e4e",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,387 @@
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],
];
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;
},
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);
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],
dy: mapped[1]
}
},
getDiscretizedDirection() {
return this.discretizeDirection(this.cachedStickHeadPosition.x, this.cachedStickHeadPosition.y, this.joyStickEps);
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "d34e3738-8dde-4da9-8b60-f25b4bf50493",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,26 @@
window.LOW_SCORE_TREASURE_TYPE = 1;
window.HIGH_SCORE_TREASURE_TYPE = 2;
window.LOW_SCORE_TREASURE_SCORE = 100;
window.HIGH_SCORE_TREASURE_SCORE = 200;
cc.Class({
extends: cc.Component,
properties: {
},
setData (treasureInfo) {
const self = this;
this.score = treasureInfo.score;
this.type = treasureInfo.type;
this.treasureInfo = treasureInfo;
const spriteComponent = this.node.getComponent(cc.Sprite);
const targetGid = (window.LOW_SCORE_TREASURE_TYPE == treasureInfo.type ? window.battleEntityTypeNameToGlobalGid["LowScoreTreasure"] : window.battleEntityTypeNameToGlobalGid["HighScoreTreasure"])
spriteComponent.spriteFrame = window.getOrCreateSpriteFrameForGid(targetGid).spriteFrame;
},
start() {},
})

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "5eea6ce5-0343-4776-80a4-fccd69bd099b",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,84 @@
cc.Class({
extends: cc.Component,
properties: {
pickedUpAnimNode: {
type: cc.Node,
default: null
},
durationMillis: {
default: 0
},
binglingAnimNode: {
type: cc.Node,
default: null
},
binglingAnimDurationMillis: {
default: 0
},
scoreLabelNode: {
type: cc.Node,
default: null
}
},
setData (treasureInfo) {
const self = this;
this.score = treasureInfo.score ? treasureInfo.score : 100 ;
this.type = treasureInfo.type ? treasureInfo.type : 1;
this.scoreLabelNode.getComponent(cc.Label).string = this.score;
const spriteComponent = this.pickedUpAnimNode.getComponent(cc.Sprite);
//hardcode treasurePNG's path.
cc.loader.loadRes("textures/treasures/"+ this.type, cc.SpriteFrame, function (err, frame) {
if(err){
cc.warn(err);
return;
}
spriteComponent.spriteFrame = frame;
})
},
// LIFE-CYCLE CALLBACKS:
update (dt) {
const changingNode = this.pickedUpAnimNode;
const elapsedMillis = Date.now() - this.startedAtMillis;
if(elapsedMillis >= this.binglingAnimDurationMillis && null != this.binglingAnimNode && true == this.binglingAnimNode.active) {
this.binglingAnimNode.active = false;
this.startedAtMillis = Date.now();
}
if(this.binglingAnimNode.active)
return;
if (elapsedMillis > this.durationMillis) {
this.node.destroy();
return;
}
if (elapsedMillis <= this.firstDurationMillis) {
let posDiff = cc.v2(0, dt * this.yIncreaseSpeed);
changingNode.setPosition(changingNode.position.add(posDiff));
this.scoreLabelNode.setPosition(this.scoreLabelNode.position.add(posDiff));
changingNode.scale += (this.scaleIncreaseSpeed*dt);
} else {
let posDiff = cc.v2(dt * this.xIncreaseSpeed , ( -1 *dt * this.yDecreaseSpeed));
changingNode.setPosition(changingNode.position.add(posDiff));
this.scoreLabelNode.setPosition(this.scoreLabelNode.position.add(posDiff));
changingNode.opacity -= dt * this.opacityDegradeSpeed;
this.scoreLabelNode.opacity -= dt * this.opacityDegradeSpeed;
}
},
onLoad() {
this.pickedUpAnimNode.scale = 0;
this.startedAtMillis = Date.now();
this.firstDurationMillis = (0.8*this.durationMillis);
this.yIncreaseSpeed = (200 *1000/this.firstDurationMillis);
this.scaleIncreaseSpeed = (2 * 1000/this.firstDurationMillis);
this.scondDurationMillis = (0.2 * this.durationMillis );
this.opacityDegradeSpeed = (255*1000/this.scondDurationMillis);
this.yDecreaseSpeed = (30*1000/this.scondDurationMillis);
this.xIncreaseSpeed = (20*1000/this.scondDurationMillis);
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "697ef72c-27ee-4184-9ae3-885808d58153",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,28 @@
const BasePlayer = require("./BasePlayer");
cc.Class({
extends: BasePlayer,
// LIFE-CYCLE CALLBACKS:
start() {
BasePlayer.prototype.start.call(this);
},
onLoad() {
BasePlayer.prototype.onLoad.call(this);
this.clips = {
'01': 'FlatHeadSisterRunTop',
'0-1': 'FlatHeadSisterRunBottom',
'-20': 'FlatHeadSisterRunLeft',
'20': 'FlatHeadSisterRunRight',
'-21': 'FlatHeadSisterRunTopLeft',
'21': 'FlatHeadSisterRunTopRight',
'-2-1': 'FlatHeadSisterRunBottomLeft',
'2-1': 'FlatHeadSisterRunBottomRight'
};
},
update(dt) {
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "233a1795-0de3-4d7c-9ce6-c5736ade723f",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,628 @@
const i18n = require('LanguageData');
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
const WECHAT_ON_HIDE_TARGET_ACTION = {
SHARE_CHAT_MESSAGE: 8,
CLOSE: 3,
};
const pbStructRoot = require('./modules/room_downsync_frame_proto_bundle.forcemsg.js');
window.RoomDownsyncFrame = pbStructRoot.treasurehunterx.RoomDownsyncFrame;
window.BattleColliderInfo = pbStructRoot.treasurehunterx.BattleColliderInfo;
cc.Class({
extends: cc.Component,
properties: {
cavasNode: {
default: null,
type: cc.Node
},
backgroundNode: {
default: null,
type: cc.Node
},
loadingPrefab: {
default: null,
type: cc.Prefab
},
tipsLabel: {
default: null,
type: cc.Label,
},
downloadProgress: {
default: null,
type: cc.ProgressBar,
},
writtenBytes: {
default: null,
type: cc.Label,
},
expectedToWriteBytes: {
default: null,
type: cc.Label,
},
handlerProgress: {
default: null,
type: cc.ProgressBar,
},
handledUrlsCount: {
default: null,
type: cc.Label,
},
toHandledUrlsCount: {
default: null,
type: cc.Label,
},
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
wx.onShow((res) => {
console.log("+++++ wx onShow(), onShow.res ", res);
window.expectedRoomId = res.query.expectedRoomId;
});
wx.onHide((res) => {
// Reference https://developers.weixin.qq.com/minigame/dev/api/wx.exitMiniProgram.html.
console.log("+++++ wx onHide(), onHide.res: ", res);
if (
WECHAT_ON_HIDE_TARGET_ACTION == res.targetAction
||
"back" == res.mode // After "WeChat v7.0.4 on iOS"
||
"close" == res.mode
) {
window.clearLocalStorageAndBackToLoginScene();
} else {
// Deliberately left blank.
}
});
const self = this;
self.getRetCodeList();
self.getRegexList();
self.showTips(i18n.t("login.tips.AUTO_LOGIN_1"));
self.checkIntAuthTokenExpire().then(
() => {
self.showTips(i18n.t("login.tips.AUTO_LOGIN_2"));
const intAuthToken = JSON.parse(cc.sys.localStorage.getItem('selfPlayer')).intAuthToken;
self.useTokenLogin(intAuthToken);
},
() => {
// 调用wx.login然后请求登录。
wx.authorize({
scope: "scope.userInfo",
success() {
self.showTips(i18n.t("login.tips.WECHAT_AUTHORIZED_AND_INT_AUTH_TOKEN_LOGGING_IN"));
wx.login({
success(res) {
console.log("wx login success, res: ", res);
const code = res.code;
wx.getUserInfo({
success(res) {
const userInfo = res.userInfo;
console.log("Get user info ok: ", userInfo);
self.useWxCodeMiniGameLogin(code, userInfo);
},
fail(err) {
console.error(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"), err);
self.showTips(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"));
self.createAuthorizeThenLoginButton();
},
})
},
fail(err) {
if (err) {
console.error(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"), err);
self.showTips(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"));
self.createAuthorizeThenLoginButton();
}
},
});
},
fail(err) {
console.error(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"), err);
self.showTips(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"));
self.createAuthorizeThenLoginButton();
}
})
}
);
},
createAuthorizeThenLoginButton(tips) {
const self = this;
let sysInfo = wx.getSystemInfoSync();
//获取微信界面大小
let width = sysInfo.screenWidth;
let height = sysInfo.screenHeight;
let button = wx.createUserInfoButton({
type: 'text',
text: '',
style: {
left: 0,
top: 0,
width: width,
height: height,
backgroundColor: '#00000000', //最后两位为透明度
color: '#ffffff',
fontSize: 20,
textAlign: "center",
lineHeight: height,
},
});
button.onTap((res) => {
console.log(res);
if (null != res.userInfo) {
const userInfo = res.userInfo;
self.showTips(i18n.t("login.tips.WECHAT_AUTHORIZED_AND_INT_AUTH_TOKEN_LOGGING_IN"));
wx.login({
success(res) {
console.log('wx.login success, res:', res);
const code = res.code;
self.useWxCodeMiniGameLogin(code, userInfo);
button.destroy();
},
fail(err) {
console.err(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"), err);
self.showTips(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"));
},
});
} else {
self.showTips(i18n.t("login.tips.PLEASE_AUTHORIZE_WECHAT_LOGIN_FIRST"));
}
})
},
onDestroy() {
console.log("+++++++ WechatGameLogin onDestroy()");
},
showTips(text) {
if (this.tipsLabel != null) {
this.tipsLabel.string = text;
} else {
console.log('Login scene showTips failed')
}
},
getRetCodeList() {
const self = this;
self.retCodeDict = constants.RET_CODE;
},
getRegexList() {
const self = this;
self.regexList = {
EMAIL: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
PHONE: /^\+?[0-9]{8,14}$/,
STREET_META: /^.{5,100}$/,
LNG_LAT_TEXT: /^[0-9]+(\.[0-9]{4,6})$/,
SEO_KEYWORD: /^.{2,50}$/,
PASSWORD: /^.{6,50}$/,
SMS_CAPTCHA_CODE: /^[0-9]{4}$/,
ADMIN_HANDLE: /^.{4,50}$/,
};
},
onSMSCaptchaGetButtonClicked(evt) {
var timerEnable = true;
const self = this;
if (!self.checkPhoneNumber('getCaptcha')) {
return;
}
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER +
constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.SMS_CAPTCHA + constants.ROUTE_PATH.GET,
type: 'GET',
data: {
phoneCountryCode: self.phoneCountryCodeInput.getComponent(cc.EditBox).string,
phoneNum: self.phoneNumberInput.getComponent(cc.EditBox).string
},
success: function(res) {
switch (res.ret) {
case constants.RET_CODE.OK:
self.phoneNumberTips.getComponent(cc.Label).string = '';
self.captchaTips.getComponent(cc.Label).string = '';
break;
case constants.RET_CODE.DUPLICATED:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.DUPLICATED");
break;
case constants.RET_CODE.INCORRECT_PHONE_COUNTRY_CODE:
case constants.RET_CODE.INCORRECT_PHONE_NUMBER:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.PHONE_ERR");
break;
case constants.RET_CODE.IS_TEST_ACC:
self.smsLoginCaptchaInput.getComponent(cc.EditBox).string = res.smsLoginCaptcha;
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.TEST_USER");
timerEnable = false;
// clearInterval(self.countdownTimer);
break;
case constants.RET_CODE.SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_FREEQUENT_REQUIRE");
default:
break;
}
if (timerEnable)
self.countdownTime(self);
}
});
},
countdownTime(self) {
self.smsLoginCaptchaButton.off('click', self.onSMSCaptchaGetButtonClicked);
self.smsLoginCaptchaButton.removeChild(self.smsGetCaptchaNode);
self.smsWaitCountdownNode.parent = self.smsLoginCaptchaButton;
var total = 20; // Magic number
self.countdownTimer = setInterval(function() {
if (total === 0) {
self.smsWaitCountdownNode.parent.removeChild(self.smsWaitCountdownNode);
self.smsGetCaptchaNode.parent = self.smsLoginCaptchaButton;
self.smsWaitCountdownNode.getChildByName('WaitTimeLabel').getComponent(cc.Label).string = 20;
self.smsLoginCaptchaButton.on('click', self.onSMSCaptchaGetButtonClicked);
clearInterval(self.countdownTimer);
} else {
total--;
self.smsWaitCountdownNode.getChildByName('WaitTimeLabel').getComponent(cc.Label).string = total;
}
}, 1000)
},
checkIntAuthTokenExpire() {
return new Promise((resolve, reject) => {
if (!cc.sys.localStorage.getItem("selfPlayer")) {
reject();
return;
}
const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
(selfPlayer.intAuthToken && new Date().getTime() < selfPlayer.expiresAt) ? resolve() : reject();
})
},
checkPhoneNumber(type) {
const self = this;
const phoneNumberRegexp = self.regexList.PHONE;
var phoneNumberString = self.phoneNumberInput.getComponent(cc.EditBox).string;
if (phoneNumberString) {
return true;
if (!phoneNumberRegexp.test(phoneNumberString)) {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.PHONE_ERR");
return false;
} else {
return true;
}
} else {
if (type === 'getCaptcha' || type === 'login') {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.PHONE_ERR");
}
return false;
}
},
checkCaptcha(type) {
const self = this;
const captchaRegexp = self.regexList.SMS_CAPTCHA_CODE;
var captchaString = self.smsLoginCaptchaInput.getComponent(cc.EditBox).string;
if (captchaString) {
if (self.smsLoginCaptchaInput.getComponent(cc.EditBox).string.length !== 4 || (!captchaRegexp.test(captchaString))) {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.CAPTCHA_ERR");
return false;
} else {
return true;
}
} else {
if (type === 'login') {
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.CAPTCHA_ERR");
}
return false;
}
},
useTokenLogin(_intAuthToken) {
var self = this;
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.INT_AUTH_TOKEN + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: {
intAuthToken: _intAuthToken
},
success: function(resp) {
self.onLoggedIn(resp);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `useTokenLogin` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage()
self.showTips(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"));
self.createAuthorizeThenLoginButton();
},
timeout: function() {
self.enableInteractiveControls(true);
},
});
},
enableInteractiveControls(enabled) {},
onLoginButtonClicked(evt) {
const self = this;
if (!self.checkPhoneNumber('login') || !self.checkCaptcha('login')) {
return;
}
self.loginParams = {
phoneCountryCode: self.phoneCountryCodeInput.getComponent(cc.EditBox).string,
phoneNum: self.phoneNumberInput.getComponent(cc.EditBox).string,
smsLoginCaptcha: self.smsLoginCaptchaInput.getComponent(cc.EditBox).string
};
self.enableInteractiveControls(false);
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER +
constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.SMS_CAPTCHA + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: self.loginParams,
success: function(resp) {
self.onLoggedIn(resp);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `onLoginButtonClicked` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage()
},
timeout: function() {
self.enableInteractiveControls(true);
}
});
},
onWechatLoggedIn(res) {
const self = this;
if (constants.RET_CODE.OK == res.ret) {
//根据服务器返回信息设置selfPlayer
self.enableInteractiveControls(false);
const date = Number(res.expiresAt);
const selfPlayer = {
expiresAt: date,
playerId: res.playerId,
intAuthToken: res.intAuthToken,
displayName: res.displayName,
avatar: res.avatar,
}
cc.sys.localStorage.setItem('selfPlayer', JSON.stringify(selfPlayer));
self.useTokenLogin(res.intAuthToken);
} else {
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.showTips(i18n.t("login.tips.WECHAT_LOGIN_FAILED_TAP_SCREEN_TO_RETRY") + ", errorCode = " + res.ret);
self.createAuthorizeThenLoginButton();
}
},
onLoggedIn(res) {
const self = this;
console.log("OnLoggedIn: ", res);
if (constants.RET_CODE.OK == res.ret) {
if (window.isUsingX5BlinkKernelOrWebkitWeChatKernel()) {
window.initWxSdk = self.initWxSdk.bind(self);
window.initWxSdk();
}
self.enableInteractiveControls(false);
const date = Number(res.expiresAt);
const selfPlayer = {
expiresAt: date,
playerId: res.playerId,
intAuthToken: res.intAuthToken,
avatar: res.avatar,
displayName: res.displayName,
name: res.name,
}
cc.sys.localStorage.setItem("selfPlayer", JSON.stringify(selfPlayer));
console.log("cc.sys.localStorage.selfPlayer = ", cc.sys.localStorage.getItem("selfPlayer"));
if (self.countdownTimer) {
clearInterval(self.countdownTimer);
}
cc.director.loadScene('default_map');
} else {
console.warn('onLoggedIn failed!')
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.enableInteractiveControls(true);
switch (res.ret) {
case constants.RET_CODE.DUPLICATED:
this.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.DUPLICATED");
break;
case constants.RET_CODE.TOKEN_EXPIRED:
this.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.LOGIN_TOKEN_EXPIRED");
break;
case constants.RET_CODE.SMS_CAPTCHA_NOT_MATCH:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_NOT_MATCH");
break;
case constants.RET_CODE.INCORRECT_CAPTCHA:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_NOT_MATCH");
break;
case constants.RET_CODE.SMS_CAPTCHA_CODE_NOT_EXISTING:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.SMS_CAPTCHA_NOT_MATCH");
break;
case constants.RET_CODE.INCORRECT_PHONE_NUMBER:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.INCORRECT_PHONE_NUMBER");
break;
case constants.RET_CODE.INVALID_REQUEST_PARAM:
self.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.INCORRECT_PHONE_NUMBER");
break;
case constants.RET_CODE.INCORRECT_PHONE_COUNTRY_CODE:
case constants.RET_CODE.INCORRECT_PHONE_NUMBER:
this.captchaTips.getComponent(cc.Label).string = i18n.t("login.tips.INCORRECT_PHONE_NUMBER");
break;
default:
break;
}
self.showTips(i18n.t("login.tips.AUTO_LOGIN_FAILED_WILL_USE_MANUAL_LOGIN"));
self.createAuthorizeThenLoginButton();
}
},
useWXCodeLogin(_code) {
const self = this;
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.WECHAT + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: {
code: _code
},
success: function(res) {
self.onWechatLoggedIn(res);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `onLoginButtonClicked` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.showTips(i18n.t("login.tips.WECHAT_LOGIN_FAILED_TAP_SCREEN_TO_RETRY") + ", errorMsg =" + errMsg);
},
timeout: function() {
console.log("Login attempt `onLoginButtonClicked` timed out, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.showTips(i18n.t("login.tips.WECHAT_LOGIN_FAILED_TAP_SCREEN_TO_RETRY") + ", errorMsg =" + errMsg);
},
});
},
// 对比useWxCodeLogin函数只是请求了不同url
useWxCodeMiniGameLogin(_code, _userInfo) {
const self = this;
NetworkUtils.ajax({
url: backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.WECHATGAME + constants.ROUTE_PATH.LOGIN,
type: "POST",
data: {
code: _code,
avatarUrl: _userInfo.avatarUrl,
nickName: _userInfo.nickName,
},
success: function(res) {
self.onWechatLoggedIn(res);
},
error: function(xhr, status, errMsg) {
console.log("Login attempt `onLoginButtonClicked` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.showTips(i18n.t("login.tips.WECHAT_LOGIN_FAILED_TAP_SCREEN_TO_RETRY") + ", errorMsg =" + errMsg);
self.createAuthorizeThenLoginButton();
},
timeout: function() {
console.log("Login attempt `onLoginButtonClicked` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.showTips(i18n.t("login.tips.WECHAT_LOGIN_FAILED_TAP_SCREEN_TO_RETRY"));
self.createAuthorizeThenLoginButton();
},
});
},
getWechatCode(evt) {
let self = this;
self.showTips("");
const wechatServerEndpoint = wechatAddress.PROTOCOL + "://" + wechatAddress.HOST + ((null != wechatAddress.PORT && "" != wechatAddress.PORT.trim()) ? (":" + wechatAddress.PORT) : "");
const url = wechatServerEndpoint + constants.WECHAT.AUTHORIZE_PATH + "?" + wechatAddress.APPID_LITERAL + "&" + constants.WECHAT.REDIRECT_RUI_KEY + NetworkUtils.encode(window.location.href) + "&" + constants.WECHAT.RESPONSE_TYPE + "&" + constants.WECHAT.SCOPE + constants.WECHAT.FIN;
console.log("To visit wechat auth addr: ", url);
window.location.href = url;
},
initWxSdk() {
const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
const origUrl = window.location.protocol + "//" + window.location.host + window.location.pathname;
/*
* The `shareLink` must
* - have its 2nd-order-domain registered as trusted 2nd-order under the targetd `res.jsConfig.app_id`, and
* - extracted from current window.location.href.
*/
const shareLink = origUrl;
const updateAppMsgShareDataObj = {
type: 'link', // 分享类型,music、video或link不填默认为link
dataUrl: '', // 如果type是music或video则要提供数据链接默认为空
title: document.title, // 分享标题
desc: 'Let\'s play together!', // 分享描述
link: shareLink + (cc.sys.localStorage.getItem('boundRoomId') ? "" : ("?expectedRoomId=" + cc.sys.localStorage.getItem('boundRoomId'))),
imgUrl: origUrl + "/favicon.ico", // 分享图标
success: function() {
// 设置成功
}
};
const menuShareTimelineObj = {
title: document.title, // 分享标题
link: shareLink + (cc.sys.localStorage.getItem('boundRoomId') ? "" : ("?expectedRoomId=" + cc.sys.localStorage.getItem('boundRoomId'))),
imgUrl: origUrl + "/favicon.ico", // 分享图标
success: function() {}
};
const wxConfigUrl = (window.isUsingWebkitWechatKernel() ? window.atFirstLocationHref : window.location.href);
//接入微信登录接口
NetworkUtils.ajax({
"url": backendAddress.PROTOCOL + '://' + backendAddress.HOST + ':' + backendAddress.PORT + constants.ROUTE_PATH.API + constants.ROUTE_PATH.PLAYER + constants.ROUTE_PATH.VERSION + constants.ROUTE_PATH.WECHAT + constants.ROUTE_PATH.JSCONFIG,
type: "POST",
data: {
"url": wxConfigUrl,
"intAuthToken": selfPlayer.intAuthToken,
},
success: function(res) {
if (constants.RET_CODE.OK != res.ret) {
console.warn("Failed to get `wsConfig`: ", res);
return;
}
const jsConfig = res.jsConfig;
const configData = {
debug: CC_DEBUG, // 开启调试模式,调用的所有api的返回值会在客户端alert出来若要查看传入的参数可以在pc端打开参数信息会通过log打出仅在pc端时才会打印。
appId: jsConfig.app_id, // 必填,公众号的唯一标识
timestamp: jsConfig.timestamp.toString(), // 必填,生成签名的时间戳
nonceStr: jsConfig.nonce_str, // 必填,生成签名的随机串
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline'],
signature: jsConfig.signature, // 必填,签名
};
console.log("config url: ", wxConfigUrl);
console.log("wx.config: ", configData);
wx.config(configData);
console.log("Current window.location.href: ", window.location.href);
wx.ready(function() {
console.log("Here is wx.ready.")
wx.onMenuShareAppMessage(updateAppMsgShareDataObj);
wx.onMenuShareTimeline(menuShareTimelineObj);
});
wx.error(function(res) {
console.error("wx config fails and error is ", JSON.stringify(res));
});
},
error: function(xhr, status, errMsg) {
console.error("Failed to get `wsConfig`: ", errMsg);
},
});
},
update(dt) {
const self = this;
if (null != wxDownloader && 0 < wxDownloader.totalBytesExpectedToWriteForAllTasks) {
self.writtenBytes.string = wxDownloader.totalBytesWrittenForAllTasks;
self.expectedToWriteBytes.string = wxDownloader.totalBytesExpectedToWriteForAllTasks;
self.downloadProgress.progress = 1.0*wxDownloader.totalBytesWrittenForAllTasks/wxDownloader.totalBytesExpectedToWriteForAllTasks;
}
const totalUrlsToHandle = (wxDownloader.immediateHandleItemCount + wxDownloader.immediateReadFromLocalCount + wxDownloader.immediatePackDownloaderCount);
const totalUrlsHandled = (wxDownloader.immediateHandleItemCompleteCount + wxDownloader.immediateReadFromLocalCompleteCount + wxDownloader.immediatePackDownloaderCompleteCount);
if (null != wxDownloader && 0 < totalUrlsToHandle) {
self.handledUrlsCount.string = totalUrlsHandled;
self.toHandledUrlsCount.string = totalUrlsToHandle;
self.handlerProgress.progress = 1.0*totalUrlsHandled/totalUrlsToHandle;
}
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "8264fb72-e348-45e4-9ab3-5bffb9a561ee",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,263 @@
window.UPSYNC_MSG_ACT_HB_PING = 1;
window.UPSYNC_MSG_ACT_PLAYER_CMD = 2;
window.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK = 3;
window.DOWNSYNC_MSG_ACT_HB_REQ = 1;
window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2;
window.DOWNSYNC_MSG_ACT_ROOM_FRAME = 3;
window.sendSafely = function(msgStr) {
/**
* - "If the data can't be sent (for example, because it needs to be buffered but the buffer is full), the socket is closed automatically."
*
* from https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send.
*/
if (null == window.clientSession || window.clientSession.readyState != WebSocket.OPEN) return false;
window.clientSession.send(msgStr);
}
window.sendUint8AsBase64Safely = function(msgUint8Arr) {
if (null == window.clientSession || window.clientSession.readyState != WebSocket.OPEN) return false;
window.clientSession.send(_uint8ToBase64(msgUint8Arr));
}
window.closeWSConnection = function() {
if (null == window.clientSession || window.clientSession.readyState != WebSocket.OPEN) return;
console.log(`Closing "window.clientSession" from the client-side.`);
window.clientSession.close();
}
window.getBoundRoomIdFromPersistentStorage = function() {
const boundRoomIdExpiresAt = parseInt(cc.sys.localStorage.getItem("boundRoomIdExpiresAt"));
if (!boundRoomIdExpiresAt || Date.now() >= boundRoomIdExpiresAt) {
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
return null;
}
return cc.sys.localStorage.getItem("boundRoomId");
};
window.clearBoundRoomIdInBothVolatileAndPersistentStorage = function() {
window.boundRoomId = null;
cc.sys.localStorage.removeItem("boundRoomId");
cc.sys.localStorage.removeItem("boundRoomIdExpiresAt");
};
window.clearSelfPlayer = function() {
cc.sys.localStorage.removeItem("selfPlayer");
};
window.boundRoomId = getBoundRoomIdFromPersistentStorage();
window.handleHbRequirements = function(resp) {
if (constants.RET_CODE.OK != resp.ret) return;
if (null == window.boundRoomId) {
window.boundRoomId = resp.bciFrame.boundRoomId;
cc.sys.localStorage.setItem('boundRoomId', window.boundRoomId);
cc.sys.localStorage.setItem('boundRoomIdExpiresAt', Date.now() + 10 * 60 * 1000); // Temporarily hardcoded, for `boundRoomId` only.
}
if (window.handleBattleColliderInfo) {
window.handleBattleColliderInfo(resp.bciFrame);
}
};
function _uint8ToBase64(uint8Arr) {
return window.btoa(uint8Arr);
}
function _base64ToUint8Array(base64) {
var origBytes = null;
if (null != window.atob) {
var origBinaryStr = window.atob(base64);
var origLen = origBinaryStr.length;
origBytes = new Uint8Array(origLen);
for (var i = 0; i < origLen; i++) {
origBytes[i] = origBinaryStr.charCodeAt(i);
}
return origBytes;
} else if (cc.sys.platform == cc.sys.WECHAT_GAME) {
return Buffer.from(base64, 'base64');
} else {
return null;
}
}
function _base64ToArrayBuffer(base64) {
return _base64ToUint8Array(base64).buffer;
}
window.getExpectedRoomIdSync = function() {
if (cc.sys.platform == cc.sys.WECHAT_GAME) {
return window.expectedRoomId;
} else {
const qDict = window.getQueryParamDict();
if (qDict) {
return qDict["expectedRoomId"];
} else {
if (window.history && window.history.state) {
return window.history.state.expectedRoomId;
}
}
}
return null;
};
window.unsetClientSessionCloseOrErrorFlag = function() {
cc.sys.localStorage.removeItem("ClientSessionCloseOrErrorFlag");
return;
}
window.setClientSessionCloseOrErrorFlag = function() {
const oldVal = cc.sys.localStorage.getItem("ClientSessionCloseOrErrorFlag");
if (true == oldVal) return false;
cc.sys.localStorage.setItem("ClientSessionCloseOrErrorFlag", true);
return true;
}
window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
if (window.clientSession && window.clientSession.readyState == WebSocket.OPEN) {
if (null != onopenCb) {
onopenCb();
}
return;
}
const intAuthToken = cc.sys.localStorage.getItem("selfPlayer") ? JSON.parse(cc.sys.localStorage.getItem('selfPlayer')).intAuthToken : "";
let urlToConnect = backendAddress.PROTOCOL.replace('http', 'ws') + '://' + backendAddress.HOST + ":" + backendAddress.PORT + backendAddress.WS_PATH_PREFIX + "?intAuthToken=" + intAuthToken;
if (null != expectedRoomId) {
console.log("initPersistentSessionClient with expectedRoomId == " + expectedRoomId);
urlToConnect = urlToConnect + "&expectedRoomId=" + expectedRoomId;
if (cc.sys.platform == cc.sys.WECHAT_GAME) {
// This is a dirty hack. -- YFLu
window.expectedRoomId = null;
}
} else {
window.boundRoomId = getBoundRoomIdFromPersistentStorage();
if (null != window.boundRoomId) {
console.log("initPersistentSessionClient with boundRoomId == " + boundRoomId);
urlToConnect = urlToConnect + "&boundRoomId=" + window.boundRoomId;
}
}
const currentHistoryState = window.history && window.history.state ? window.history.state : {};
if (cc.sys.platform != cc.sys.WECHAT_GAME) {
window.history.replaceState(currentHistoryState, document.title, window.location.pathname);
}
const clientSession = new WebSocket(urlToConnect);
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
clientSession.onopen = function(event) {
console.log("The WS clientSession is opened.");
window.clientSession = clientSession;
if (null == onopenCb) return;
onopenCb();
};
clientSession.onmessage = function(event) {
if (null == event || null == event.data) {
return;
}
try {
const resp = window.WsResp.decode(new Uint8Array(event.data));
switch (resp.act) {
case window.DOWNSYNC_MSG_ACT_HB_REQ:
window.handleHbRequirements(resp); // 获取boundRoomId并存储到localStorage
break;
case window.DOWNSYNC_MSG_ACT_ROOM_FRAME:
if (window.handleRoomDownsyncFrame) {
window.handleRoomDownsyncFrame(resp.rdf);
}
break;
case window.DOWNSYNC_MSG_ACT_INPUT_BATCH:
if (window.handleInputFrameDownsyncBatch) {
window.handleInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);
}
break;
default:
break;
}
} catch (e) {
console.error("Unexpected error when parsing data of:", event.data, e);
}
};
clientSession.onerror = function(event) {
if (!window.setClientSessionCloseOrErrorFlag()) {
return;
}
console.error("Error caught on the WS clientSession: ", event);
if (window.clientSessionPingInterval) {
clearInterval(window.clientSessionPingInterval);
}
if (window.handleClientSessionCloseOrError) {
window.handleClientSessionCloseOrError();
}
window.unsetClientSessionCloseOrErrorFlag();
};
clientSession.onclose = function(event) {
if (!window.setClientSessionCloseOrErrorFlag()) {
return;
}
console.warn("The WS clientSession is closed: ", event);
if (window.clientSessionPingInterval) {
clearInterval(window.clientSessionPingInterval);
}
if (false == event.wasClean) {
// Chrome doesn't allow the use of "CustomCloseCode"s (yet) and will callback with a "WebsocketStdCloseCode 1006" and "false == event.wasClean" here. See https://tools.ietf.org/html/rfc6455#section-7.4 for more information.
if (window.handleClientSessionCloseOrError) {
window.handleClientSessionCloseOrError();
}
} else {
switch (event.code) {
case constants.RET_CODE.PLAYER_NOT_FOUND:
case constants.RET_CODE.PLAYER_CHEATING:
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
break;
default:
break;
}
if (window.handleClientSessionCloseOrError) {
window.handleClientSessionCloseOrError();
}
}
window.unsetClientSessionCloseOrErrorFlag();
};
};
window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
console.warn("+++++++ Calling `clearLocalStorageAndBackToLoginScene`");
if (window.mapIns && window.mapIns.musicEffectManagerScriptIns) {
window.mapIns.musicEffectManagerScriptIns.stopAllMusic();
}
/**
* Here I deliberately removed the callback in the "common `handleClientSessionCloseOrError` callback"
* within which another invocation to `clearLocalStorageAndBackToLoginScene` will be made.
*
* It'll be re-assigned to the common one upon reentrance of `Map.onLoad`.
*
* -- YFLu 2019-04-06
*/
window.handleClientSessionCloseOrError = () => {
console.warn("+++++++ Special handleClientSessionCloseOrError() assigned within `clearLocalStorageAndBackToLoginScene`");
// TBD.
window.handleClientSessionCloseOrError = null; // To ensure that it's called at most once.
};
window.closeWSConnection();
window.clearSelfPlayer();
if (true != shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
}
if (cc.sys.platform == cc.sys.WECHAT_GAME) {
cc.director.loadScene('wechatGameLogin');
} else {
cc.director.loadScene('login');
}
};

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "07a29622-1fef-4e3a-b892-7e203315ca91",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.1",
"uuid": "40cf5957-2ccf-450f-b78e-6d65eb2fe420",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "f9cd97f6-3533-4a27-afc8-cf302da003b2",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
{
"ver": "1.0.1",
"uuid": "e646fbd9-7821-4567-9846-fb6e45aeb921",
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "77ed160f-d4d5-4654-a502-66b008197da0",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}