mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-27 12:08:21 +00:00
245 lines
11 KiB
JavaScript
245 lines
11 KiB
JavaScript
"use strict";
|
|
|
|
function TileCollisionManager() {
|
|
}
|
|
|
|
TileCollisionManager.prototype.continuousMapNodeVecToContinuousObjLayerVec = function(withTiledMapNode, continuousMapNodeVec) {
|
|
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
|
|
|
|
const mapOrientation = tiledMapIns.getMapOrientation();
|
|
const mapTileRectilinearSize = tiledMapIns.getTileSize();
|
|
|
|
switch (mapOrientation) {
|
|
case cc.TiledMap.Orientation.ORTHO:
|
|
return continuousMapNodeVec;
|
|
|
|
case cc.TiledMap.Orientation.ISO:
|
|
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)]
|
|
];
|
|
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);
|
|
|
|
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:
|
|
return cc.v2(continuousObjLayerVec.x, -continuousObjLayerVec.y);
|
|
|
|
case cc.TiledMap.Orientation.ISO:
|
|
const tileSizeUnifiedLength = Math.sqrt(mapTileRectilinearSize.width * mapTileRectilinearSize.width * 0.25 + mapTileRectilinearSize.height * mapTileRectilinearSize.height * 0.25);
|
|
const isometricObjectLayerPointOffsetScaleFactor = (tileSizeUnifiedLength / mapTileRectilinearSize.height);
|
|
|
|
const cosineThetaRadian = (mapTileRectilinearSize.width * 0.5) / tileSizeUnifiedLength;
|
|
const sineThetaRadian = (mapTileRectilinearSize.height * 0.5) / tileSizeUnifiedLength;
|
|
|
|
const transMat = [
|
|
[isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian, -isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian],
|
|
[-isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian, -isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian]
|
|
];
|
|
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);
|
|
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
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:
|
|
layerOffset = cc.v2(-(withTiledMapNode.getContentSize().width * 0.5), +(withTiledMapNode.getContentSize().height * 0.5));
|
|
break;
|
|
case cc.TiledMap.Orientation.ISO:
|
|
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) {
|
|
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap);
|
|
const mapOrientation = tiledMapIns.getMapOrientation();
|
|
let layerOffset = null;
|
|
switch (mapOrientation) {
|
|
case cc.TiledMap.Orientation.ORTHO:
|
|
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.
|
|
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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Note that `TileCollisionManager.extractBoundaryObjects` returns everything with coordinates local to `withTiledMapNode`!
|
|
*/
|
|
window.battleEntityTypeNameToGlobalGid = {};
|
|
TileCollisionManager.prototype.extractBoundaryObjects = function(withTiledMapNode) {
|
|
let toRet = {
|
|
playerStartingPositions: [],
|
|
barriers: [],
|
|
npcStartingPositions: [],
|
|
npcPatrolCues: [],
|
|
};
|
|
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
|
|
|
|
const allObjectGroups = tiledMapIns.getObjectGroups();
|
|
for (let i = 0; i < allObjectGroups.length; ++i) {
|
|
var objectGroup = allObjectGroups[i];
|
|
var allObjects = objectGroup.getObjects();
|
|
switch (objectGroup.getGroupName()) {
|
|
case "PlayerStartingPos":
|
|
for (let j = 0; j < allObjects.length; ++j) {
|
|
const cccMaskedX = allObjects[j].x,
|
|
cccMaskedY = allObjects[j].y;
|
|
const origX = cccMaskedX,
|
|
origY = withTiledMapNode.getContentSize().height - cccMaskedY; // FIXME: I don't know why CocosCreator did this, it's stupid and MIGHT NOT WORK IN ISOMETRIC orientation!
|
|
let wpos = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, cc.v2(origX, origY));
|
|
toRet.playerStartingPositions.push(wpos);
|
|
}
|
|
break;
|
|
case "NpcPatrolCue":
|
|
for (let j = 0; j < allObjects.length; ++j) {
|
|
const cccMaskedX = allObjects[j].x,
|
|
cccMaskedY = allObjects[j].y;
|
|
const origX = cccMaskedX,
|
|
origY = withTiledMapNode.getContentSize().height - cccMaskedY;
|
|
let wpos = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, cc.v2(origX, origY));
|
|
const cue = {
|
|
x: wpos.x,
|
|
y: wpos.y,
|
|
flAct: parseInt(allObjects[j].flAct),
|
|
frAct: parseInt(allObjects[j].frAct),
|
|
};
|
|
toRet.npcPatrolCues.push(cue);
|
|
}
|
|
break;
|
|
case "NpcStartingPos":
|
|
for (let j = 0; j < allObjects.length; ++j) {
|
|
const cccMaskedX = allObjects[j].x,
|
|
cccMaskedY = allObjects[j].y;
|
|
const origX = cccMaskedX,
|
|
origY = withTiledMapNode.getContentSize().height - cccMaskedY;
|
|
let wpos = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, cc.v2(origX, origY));
|
|
const npc = {
|
|
x: wpos.x,
|
|
y: wpos.y,
|
|
speciesId: parseInt(allObjects[j].speciesId),
|
|
dirX: parseInt(allObjects[j].dirX),
|
|
};
|
|
toRet.npcStartingPositions.push(npc);
|
|
}
|
|
break;
|
|
case "Barrier":
|
|
for (let j = 0; j < allObjects.length; ++j) {
|
|
let object = allObjects[j];
|
|
let gid = object.gid;
|
|
if (0 < gid) {
|
|
continue;
|
|
}
|
|
const boundaryType = object.boundary_type;
|
|
let toPushBarrier = [];
|
|
toPushBarrier.boundaryType = boundaryType;
|
|
let polylinePoints = object.polylinePoints;
|
|
if (null == polylinePoints) {
|
|
polylinePoints = [{
|
|
x: 0,
|
|
y: 0
|
|
}, {
|
|
x: object.width,
|
|
y: 0
|
|
}, {
|
|
x: object.width,
|
|
y: -object.height
|
|
}, {
|
|
x: 0,
|
|
y: -object.height
|
|
}];
|
|
}
|
|
for (let k = 0; k < polylinePoints.length; ++k) {
|
|
/* Since CocosCreatorv2.1.3, the Y-coord of object polylines is inverted compared to that of the tmx file. */
|
|
toPushBarrier.push(this.continuousObjLayerVecToContinuousMapNodeVec(withTiledMapNode, cc.v2(polylinePoints[k].x, -polylinePoints[k].y)));
|
|
}
|
|
toPushBarrier.anchor = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset); // DON'T use "(object.x, object.y)" which are wrong/meaningless!
|
|
toRet.barriers.push(toPushBarrier);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return toRet;
|
|
}
|
|
|
|
TileCollisionManager.prototype.isOutOfMapNode = function(tiledMapNode, continuousPosLocalToMap) {
|
|
const tiledMapIns = tiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
|
|
|
|
const mapOrientation = tiledMapIns.getMapOrientation();
|
|
const mapTileRectilinearSize = tiledMapIns.getTileSize();
|
|
|
|
const mapContentSize = cc.size(tiledMapIns.getTileSize().width * tiledMapIns.getMapSize().width, tiledMapIns.getTileSize().height * tiledMapIns.getMapSize().height);
|
|
|
|
switch (mapOrientation) {
|
|
case cc.TiledMap.Orientation.ORTHO:
|
|
case cc.TiledMap.Orientation.ISO:
|
|
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:
|
|
return true;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
TileCollisionManager.prototype.initMapNodeByTiledBoundaries = function(mapScriptIns, mapNode, extractedBoundaryObjs) {
|
|
const tiledMapIns = mapNode.getComponent(cc.TiledMap);
|
|
|
|
mapScriptIns.barrierColliders = [];
|
|
for (let boundaryObj of extractedBoundaryObjs.barriers) {
|
|
const newBarrier = cc.instantiate(mapScriptIns.polygonBoundaryBarrierPrefab);
|
|
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);
|
|
}
|
|
mapScriptIns.barrierColliders.push(newBarrierColliderIns);
|
|
mapScriptIns.node.addChild(newBarrier);
|
|
}
|
|
}
|
|
|
|
window.tileCollisionManager = new TileCollisionManager();
|