Fixed frontend tmx parsing for ortho map.

This commit is contained in:
genxium
2022-11-16 22:11:56 +08:00
parent 7b9172c27b
commit 22fb72afbc
113 changed files with 2880 additions and 912 deletions

View File

@@ -74,25 +74,6 @@ module.export = cc.Class({
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();

View File

@@ -352,7 +352,7 @@ cc.Class({
window.mapIns = self;
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
self.showCriticalCoordinateLabels = false;
self.showCriticalCoordinateLabels = true;
console.warn("+++++++ Map onLoad()");
window.handleClientSessionError = function() {
@@ -435,6 +435,7 @@ cc.Class({
const tiledMapIns = self.node.getComponent(cc.TiledMap);
// It's easier to just use the "barrier"s extracted by the backend (all anchor points in world coordinates), but I'd like to verify frontend tmx parser logic as well.
const fullPathOfTmxFile = cc.js.formatStr("map/%s/map", parsedBattleColliderInfo.stageName);
cc.loader.loadRes(fullPathOfTmxFile, cc.TiledMapAsset, (err, tmxAsset) => {
if (null != err) {
@@ -472,43 +473,42 @@ cc.Class({
let barrierIdCounter = 0;
const boundaryObjs = tileCollisionManager.extractBoundaryObjects(self.node);
for (let boundaryObj of boundaryObjs.barriers) {
const x0 = boundaryObj[0].x,
y0 = boundaryObj[0].y;
let pts = [];
for (let i = 0; i < boundaryObj.length; ++i) {
const dx = boundaryObj[i].x - x0;
const dy = boundaryObj[i].y - y0;
pts.push([dx, dy]);
/*
if (self.showCriticalCoordinateLabels) {
const barrierVertLabelNode = new cc.Node();
switch (i % 4) {
case 0:
barrierVertLabelNode.color = cc.Color.RED;
break;
case 1:
barrierVertLabelNode.color = cc.Color.GRAY;
break;
case 2:
barrierVertLabelNode.color = cc.Color.BLACK;
break;
default:
barrierVertLabelNode.color = cc.Color.MAGENTA;
break;
}
barrierVertLabelNode.setPosition(cc.v2(x0+0.95*dx, y0+0.5*dy));
const barrierVertLabel = barrierVertLabelNode.addComponent(cc.Label);
barrierVertLabel.fontSize = 20;
barrierVertLabel.lineHeight = 22;
barrierVertLabel.string = `(${boundaryObj[i].x.toFixed(1)}, ${boundaryObj[i].y.toFixed(1)})`;
safelyAddChild(self.node, barrierVertLabelNode);
setLocalZOrder(barrierVertLabelNode, 5);
const x0 = boundaryObj.anchor.x,
y0 = boundaryObj.anchor.y;
const newBarrier = self.collisionSys.createPolygon(x0, y0, Array.from(boundaryObj, p => { return [p.x, p.y]; }));
if (self.showCriticalCoordinateLabels) {
for (let i = 0; i < boundaryObj.length; ++i) {
const barrierVertLabelNode = new cc.Node();
switch (i % 4) {
case 0:
barrierVertLabelNode.color = cc.Color.RED;
break;
case 1:
barrierVertLabelNode.color = cc.Color.GRAY;
break;
case 2:
barrierVertLabelNode.color = cc.Color.BLACK;
break;
default:
barrierVertLabelNode.color = cc.Color.MAGENTA;
break;
}
const wx = boundaryObj.anchor.x + boundaryObj[i].x,
wy = boundaryObj.anchor.y + boundaryObj[i].y;
barrierVertLabelNode.setPosition(cc.v2(wx, wy));
const barrierVertLabel = barrierVertLabelNode.addComponent(cc.Label);
barrierVertLabel.fontSize = 12;
barrierVertLabel.lineHeight = barrierVertLabel.fontSize+1;
barrierVertLabel.string = `(${wx.toFixed(1)}, ${wy.toFixed(1)})`;
safelyAddChild(self.node, barrierVertLabelNode);
setLocalZOrder(barrierVertLabelNode, 5);
barrierVertLabelNode.active = true;
}
barrierVertLabelNode.active = true;
}
*/
}
const newBarrier = self.collisionSys.createPolygon(x0, y0, pts);
// console.log("Created barrier: ", newBarrier);
++barrierIdCounter;
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);
@@ -520,27 +520,11 @@ cc.Class({
id: self.selfPlayerInfo.playerId
});
const fullPathOfBackgroundMapTmxFile = cc.js.formatStr("map/%s/BackgroundMap/map", parsedBattleColliderInfo.stageName);
cc.loader.loadRes(fullPathOfBackgroundMapTmxFile, cc.TiledMapAsset, (err, backgroundMapTmxAsset) => {
if (null != err) {
console.error(err);
return;
}
self.backgroundMapTiledIns.tmxAsset = null;
self.backgroundMapTiledIns.node.removeAllChildren();
self.backgroundMapTiledIns.tmxAsset = backgroundMapTmxAsset;
const newBackgroundMapSize = self.backgroundMapTiledIns.getMapSize();
const newBackgroundMapTileSize = self.backgroundMapTiledIns.getTileSize();
self.backgroundMapTiledIns.node.setContentSize(newBackgroundMapSize.width * newBackgroundMapTileSize.width, newBackgroundMapSize.height * newBackgroundMapTileSize.height);
self.backgroundMapTiledIns.node.setPosition(cc.v2(0, 0));
const reqData = window.pb.protos.WsReq.encode({
msgId: Date.now(),
act: window.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK,
}).finish();
window.sendSafely(reqData);
});
const reqData = window.pb.protos.WsReq.encode({
msgId: Date.now(),
act: window.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK,
}).finish();
window.sendSafely(reqData);
});
};

View File

@@ -159,7 +159,7 @@ cc.Class({
start() {
BasePlayer.prototype.start.call(this);
this.scheduleNewDirection(this._generateRandomDirectionExcluding(0, 0));
this.scheduleNewDirection(this._generateRandomDirection());
},
onLoad() {
@@ -185,8 +185,7 @@ cc.Class({
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.scheduleNewDirection(self._generateRandomDirection());
self.collisionWithPlayerState = transitStunnedAnimPlayedToWalking(self.collisionWithPlayerState);
setTimeout(() => {
self.collisionWithPlayerState = transitWalkingConditionallyCollidableToUnconditionallyCollidable(self.collisionWithPlayerState);
@@ -257,17 +256,7 @@ cc.Class({
},
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) {

View File

@@ -1,247 +1,32 @@
"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() {
}
function TileCollisionManager() { }
TileCollisionManager.prototype.continuousMapNodeVecToContinuousObjLayerVec = function(withTiledMapNode, continuousMapNodeVec) {
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
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);
const mapOrientation = tiledMapIns.getMapOrientation();
const mapTileRectilinearSize = tiledMapIns.getTileSize();
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
return null;
return continuousMapNodeVec;
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]
const tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width * 0.25 + mapTileRectilinearSize.height * mapTileRectilinearSize.height * 0.25);
const isometricObjectLayerPointOffsetScaleFactor = (tileSizeUnifiedLength / mapTileRectilinearSize.height);
const inverseIsometricObjectLayerPointOffsetScaleFactor = 1 / isometricObjectLayerPointOffsetScaleFactor;
const cosineThetaRadian = (mapTileRectilinearSize.width * 0.5) / tileSizeUnifiedLength;
const sineThetaRadian = (mapTileRectilinearSize.height * 0.5) / tileSizeUnifiedLength;
const inverseTransMat = [
[inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / cosineThetaRadian), -inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / sineThetaRadian)],
[-inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / cosineThetaRadian), -inverseIsometricObjectLayerPointOffsetScaleFactor * 0.5 * (1 / 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;
const convertedVecX = inverseTransMat[0][0] * continuousMapNodeVec.x + inverseTransMat[0][1] * continuousMapNodeVec.y;
const convertedVecY = inverseTransMat[1][0] * continuousMapNodeVec.x + inverseTransMat[1][1] * continuousMapNodeVec.y;
return cc.v2(convertedVecX, convertedVecY);
@@ -250,7 +35,7 @@ TileCollisionManager.prototype.continuousMapNodeVecToContinuousObjLayerVec = fun
}
}
TileCollisionManager.prototype.continuousObjLayerVecToContinuousMapNodeVec = function (withTiledMapNode, continuousObjLayerVec) {
TileCollisionManager.prototype.continuousObjLayerVecToContinuousMapNodeVec = function(withTiledMapNode, continuousObjLayerVec) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
@@ -258,22 +43,21 @@ TileCollisionManager.prototype.continuousObjLayerVecToContinuousMapNodeVec = fun
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
return cc.v2(continuousObjLayerVec.x, -continuousObjLayerVec.y);
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);
const tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width * 0.25 + mapTileRectilinearSize.height * mapTileRectilinearSize.height * 0.25);
const isometricObjectLayerPointOffsetScaleFactor = (tileSizeUnifiedLength / mapTileRectilinearSize.height);
var cosineThetaRadian = (mapTileRectilinearSize.width * 0.5) / tileSizeUnifiedLength;
var sineThetaRadian = (mapTileRectilinearSize.height * 0.5) / tileSizeUnifiedLength;
const cosineThetaRadian = (mapTileRectilinearSize.width * 0.5) / tileSizeUnifiedLength;
const sineThetaRadian = (mapTileRectilinearSize.height * 0.5) / tileSizeUnifiedLength;
var transMat = [
[isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian, - isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian],
[- isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian, - isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian]
const 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;
const convertedVecX = transMat[0][0] * continuousObjLayerVec.x + transMat[0][1] * continuousObjLayerVec.y;
const convertedVecY = transMat[1][0] * continuousObjLayerVec.x + transMat[1][1] * continuousObjLayerVec.y;
return cc.v2(convertedVecX, convertedVecY);
@@ -282,46 +66,37 @@ TileCollisionManager.prototype.continuousObjLayerVecToContinuousMapNodeVec = fun
}
}
TileCollisionManager.prototype.continuousObjLayerOffsetToContinuousMapNodePos = function (withTiledMapNode, continuousObjLayerOffset) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
TileCollisionManager.prototype.continuousObjLayerOffsetToContinuousMapNodePos = function(withTiledMapNode, continuousObjLayerOffset) {
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
const mapOrientation = tiledMapIns.getMapOrientation();
let layerOffset = null;
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
layerOffset = cc.v2(-(withTiledMapNode.getContentSize().width * 0.5), +(withTiledMapNode.getContentSize().height * 0.5));
break;
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));
layerOffset = cc.v2(0, +(withTiledMapNode.getContentSize().height * 0.5));
break;
default:
return null;
}
return layerOffset.add(this.continuousObjLayerVecToContinuousMapNodeVec(withTiledMapNode, continuousObjLayerOffset));
}
TileCollisionManager.prototype.continuousMapNodePosToContinuousObjLayerOffset = function (withTiledMapNode, continuousMapNodePos) {
var tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
TileCollisionManager.prototype.continuousMapNodePosToContinuousObjLayerOffset = function(withTiledMapNode, continuousMapNodePos) {
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
const mapOrientation = tiledMapIns.getMapOrientation();
let layerOffset = null;
switch (mapOrientation) {
case cc.TiledMap.Orientation.ORTHO:
// TODO
return null;
layerOffset = cc.v2(+(withTiledMapNode.getContentSize().width * 0.5), +(withTiledMapNode.getContentSize().height * 0.5));
return cc.v2(continuousMapNodePos.x + layerOffset.x, continuousMapNodePos.y + layerOffset.y);
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!
layerOffset = cc.v2(0, +(withTiledMapNode.getContentSize().height * 0.5));
const calibratedVec = continuousMapNodePos.sub(layerOffset); // TODO: Respect the real offsets!
return this.continuousMapNodeVecToContinuousObjLayerVec(withTiledMapNode, calibratedVec);
default:
return null;
}
@@ -331,129 +106,13 @@ TileCollisionManager.prototype.continuousMapNodePosToContinuousObjLayerOffset =
* Note that `TileCollisionManager.extractBoundaryObjects` returns everything with coordinates local to `withTiledMapNode`!
*/
window.battleEntityTypeNameToGlobalGid = {};
TileCollisionManager.prototype.extractBoundaryObjects = function (withTiledMapNode) {
TileCollisionManager.prototype.extractBoundaryObjects = function(withTiledMapNode) {
let toRet = {
barriers: [],
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 don't proceed with tilesets in ORTHO orientation 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 {
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: [],
};
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;
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
});
}
}
const allObjectGroups = tiledMapIns.getObjectGroups();
for (let i = 0; i < allObjectGroups.length; ++i) {
var objectGroup = allObjectGroups[i];
if ("barrier_and_shelter" != objectGroup.getProperty("type")) continue;
@@ -468,22 +127,16 @@ TileCollisionManager.prototype.extractBoundaryObjects = function (withTiledMapNo
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;
let toPushBarriers = [];
toPushBarriers.boundaryType = boundaryType;
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));
/* Since CocosCreatorv2.1.3, the Y-coord of object polylines is inverted compared to that of the tmx file. */
toPushBarriers.push(this.continuousObjLayerVecToContinuousMapNodeVec(withTiledMapNode, cc.v2(polylinePoints[k].x, -polylinePoints[k].y)));
}
if (null != object.debug_mark) {
console.log("Transformed ", polylinePoints, ", to ", toPushBarriers);
}
toPushBarriers.boundaryType = boundaryType;
toPushBarriers.anchor = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset); // DON'T use "(object.x, object.y)" which are wrong/meaningless!
toRet.barriers.push(toPushBarriers);
break;
default:
@@ -492,85 +145,21 @@ TileCollisionManager.prototype.extractBoundaryObjects = function (withTiledMapNo
}
}
const allLayers = tiledMapIns.getLayers();
let layerDOMTrees = [];
const mapDomTree = mapInfo._parser._parseXML(tiledMapIns.tmxAsset.tmxXmlStr).documentElement;
const mapDOMAllChildren = (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);
}
continue;
default:
return toRet;
}
}
}
}
return toRet;
}
TileCollisionManager.prototype.isOutOfMapNode = function (tiledMapNode, continuousPosLocalToMap) {
var tiledMapIns = tiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
TileCollisionManager.prototype.isOutOfMapNode = function(tiledMapNode, continuousPosLocalToMap) {
const tiledMapIns = tiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
var mapOrientation = tiledMapIns.getMapOrientation();
var mapTileRectilinearSize = tiledMapIns.getTileSize();
const mapOrientation = tiledMapIns.getMapOrientation();
const mapTileRectilinearSize = tiledMapIns.getTileSize();
var mapContentSize = cc.size(tiledMapIns.getTileSize().width * tiledMapIns.getMapSize().width, tiledMapIns.getTileSize().height * tiledMapIns.getMapSize().height);
const 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);
const continuousObjLayerOffset = this.continuousMapNodePosToContinuousObjLayerOffset(tiledMapNode, continuousPosLocalToMap); // Already took care of both orientations
return 0 > continuousObjLayerOffset.x || 0 > continuousObjLayerOffset.y || mapContentSize.width < continuousObjLayerOffset.x || mapContentSize.height < continuousObjLayerOffset.y;
default:
@@ -580,63 +169,18 @@ TileCollisionManager.prototype.isOutOfMapNode = function (tiledMapNode, continuo
};
TileCollisionManager.prototype.initMapNodeByTiledBoundaries = function(mapScriptIns, mapNode, extractedBoundaryObjs) {
// TODO: TO DEPRECATE!
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);
}
mapScriptIns.barrierColliders = [];
for (let boundaryObj of extractedBoundaryObjs.barriers) {
const newBarrier = cc.instantiate(mapScriptIns.polygonBoundaryBarrierPrefab);
const newBoundaryOffsetInMapNode = cc.v2(boundaryObj[0].x, boundaryObj[0].y);
const newBoundaryOffsetInMapNode = cc.v2(boundaryObj.anchor.x, boundaryObj.anchor.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));
newBarrierColliderIns.points.push(p);
}
mapScriptIns.barrierColliders.push(newBarrierColliderIns);
mapScriptIns.node.addChild(newBarrier);