您的位置:首页 > 编程语言 > Java开发

六边形格子地图坐标计算与转换

2017-04-12 13:29 127 查看
// 世界场景的一些数据管理,如提供坐标转换之类的接口

var WorldMapManager = function () {
this.mapSize = null;     // 地图大小,像素
this.curViewPos = null;  // 当前大地图视野坐标

// 初始化世界地图的数据
this.init = function (mapSize, tileSize) {
this.mapSize = {
width  : globalConsts.WorldMapSize.width * globalConsts.TileSize.width + globalConsts.TileSize.width / 2,
height : globalConsts.WorldMapSize.height * ((globalConsts.TileSize.height - globalConsts.TileSize.hex) / 2 + globalConsts.TileSize.hex) +
(globalConsts.TileSize.height - globalConsts.TileSize.hex) / 2
};
this.tileSize = globalConsts.TileSize;
};

// 大地图坐标转成蜂窝cell
this.mapPosToTile = function (pos) {
// 算出缩放成正六边形后边长 a 的值
var a = this.tileSize.width / Math.sqrt(3);
var x = pos.x, y = (this.mapSize.height - pos.y) / this.tileSize.height * a * 2 + a / 2;    // 加 a / 2 是因为矩形网格计算时会在底部增加 a / 2

//位于矩形网格边线上的三个CELL中心点
var points = new Array(cc.p(0, 0), cc.p(0, 0), cc.p(0, 0));
//当前距离的平方
var dist;
//      index:被捕获的索引
var i, index;
//二分之根号3 边长的平方,如果距离比它还小,就必然捕获
var g_MinDistance2 = Math.pow(a * Math.sqrt(3) / 2, 2);
// 网格宽、高
var g_unitx = a * Math.sqrt(3);     //sqrt(3) * a
var g_unity = a * 1.5;              //a * 3 / 2
// 网格对角线平方向上取整
var mindist= Math.ceil(Math.pow(g_unitx, 2) + Math.pow(g_unity, 2));
//计算出鼠标点位于哪一个矩形网格中
var cx = parseInt(x/g_unitx);
var cy = parseInt(y/g_unity);

points[0].x = parseInt(g_unitx * cx);
points[1].x = parseInt(g_unitx * (cx+0.5));
points[2].x = parseInt(g_unitx * (cx+1));
//根据cy是否是偶数,决定三个点的纵坐标
if(cy % 2 == 0)
{
//偶数时,三个点组成倒立三角
points[0].y = points[2].y = parseInt(g_unity * cy);
points[1].y = parseInt(g_unity * (cy+1));
}
else
{
//奇数时,三个点组成正立三角
points[0].y = points[2].y = parseInt(g_unity * (cy+1));
points[1].y = parseInt(g_unity * cy);
}

// 计算两点间距离的平方
function distance2(x1, y1, x2, y2)
{
return ((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}

//现在找出鼠标距离哪一个点最近
for(i = 0; i < 3; ++i)
{
//求出距离的平方
dist = distance2(x, y, points[i].x, points[i].y);

//如果已经肯定被捕获
if(dist < g_MinDistance2)
{
index = i;
break;
}

//更新最小距离值和索引
if(dist < mindist)
{
mindist = dist;
index = i;
}
}

// x 第 0 个点的列值减 1 等于cell.x ( x 最左半格有 -1 值 )
// cy 偶数时中间点 + 1,奇数时两边点 + 1,减 1 是因为初始为了计算方便 y 补了 a / 2 ( y 最上半格 也会存在 -1 )
return {x : cx - (index > 0? 0 : 1), y : cy + (cy % 2 + index % 2) % 2 - 1};
};

// 格子坐标转成地图坐标
this.tilePosToMap = function (pos) {
var tileCenter, xPixel, yPixel;

tileCenter = (pos.x * this.tileSize.width) + this.tileSize.width / 2;
xPixel = tileCenter + (pos.y % 2) * this.tileSize.width / 2;
yPixel = this.tileSize.height / 2 + pos.y * (this.tileSize.height / 2 + this.tileSize.hex / 2);

// 因为锚点的关系,y值需要倒过来,这很重要
yPixel = this.mapSize.height - yPixel;

return cc.p(xPixel, yPixel);
};

// 获取相邻两个六边形格子中心点距离
this.getAdjacentHexagonCenterPointDistance = function (isLeftAndRight) {
if (isLeftAndRight) {
return this.tileSize.width;
} else {
return Math.sqrt(Math.pow((this.tileSize.height + this.tileSize.hex) / 2, 2) + Math.pow(this.tileSize.width / 2, 2));
}
};
};

// 单例

WorldMapManager.sharedInstance = null;

WorldMapManager.getInstance = function(){
if (WorldMapManager.sharedInstance == null) {
WorldMapManager.sharedInstance = new WorldMapManager();
WorldMapManager.sharedInstance.init();
}
return WorldMapManager.sharedInstance;
};


var tileCalculate = {

// 两六边形 tilePos 获取 无视阻挡的最短距离格子数 0~1 return 1
getTwoTileDistance : function(lightTilePos, findTilePos) {
var offX = 1, offY = 1; // 初始 findTilePos 在 lightTilePos 左上,往右下寻
var tilePos, count;

if (lightTilePos.y === findTilePos.y) {
return Math.abs(lightTilePos.x - findTilePos.x);
} else if (lightTilePos.x === findTilePos.x) {
return Math.abs(lightTilePos.y - findTilePos.y);
} else {
count = 0;
tilePos = {x:findTilePos.x, y:findTilePos.y};
// 在右,往左寻
if (lightTilePos.x < tilePos.x) {
offX = -1;
}
// 在下,往上寻
if (lightTilePos.y < tilePos.y) {
offY = -1;
}
do {
++count;
tilePos.x += tilePos.y % 2 > 0 ? (offX > 0 ? offX : 0) : (offX < 0 ? offX : 0);
tilePos.y += offY;
} while (lightTilePos.x !== tilePos.x && lightTilePos.y !== tilePos.y);
count += Math.abs(lightTilePos.x - tilePos.x) + Math.abs(lightTilePos.y - tilePos.y);
return count;
}
},

// 获取格子周围一圈,共六个格子的格子坐标
getAroundTilePos : function(tilePos) {
if (tilePos.y % 2 > 0) {
return [{x : tilePos.x, y : tilePos.y - 1}, {x : tilePos.x, y : tilePos.y + 1}, // 上下
{x : tilePos.x - 1, y : tilePos.y}, {x : tilePos.x + 1, y : tilePos.y}, // 左右
{x : tilePos.x + 1, y : tilePos.y - 1}, {x : tilePos.x + 1, y : tilePos.y + 1}]; // 右上,右下
} else {
return [{x : tilePos.x, y : tilePos.y - 1}, {x : tilePos.x, y : tilePos.y + 1}, // 上下
{x : tilePos.x - 1, y : tilePos.y}, {x : tilePos.x + 1, y : tilePos.y}, // 左右
{x : tilePos.x - 1, y : tilePos.y - 1}, {x : tilePos.x - 1, y : tilePos.y + 1}]; // 左上,左下
}
},

// 获取格子周围两圈,共十八个格子的格子坐标
getAroundTwoLapsTilePos : function(tilePos) {
var i, j, tiles1, tiles2 = [];
var tilePoses = {};

// 把第一圈及第一圈每一个的第一圈都收集起来
tiles1 = this.getAroundTilePos(tilePos);
for (i in tiles1) {
tiles2 = this.getAroundTilePos(tiles1[i]);
for (j in tiles2) {
if (tiles2[j].x !== tilePos.x || tiles2[j].y !== tilePos.y) {
tilePoses[JSON.stringify(tiles2[j])] = tiles2[j];
}
}

4000
}

return tilePoses;
},

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息