六边形格子地图

2 篇文章 0 订阅
2 篇文章 0 订阅

**作为一个平面地图 位置加载以及 像素 转 格子位置 以及 格子位置 转 唯一的key key 转 格子标识 格子转 像素 **

为了展示 效果 图片为 unity 实际 代码是 ts
3d 和 2d 平面 加载基本是一样的 都可以用这套代码 为什么要做 六边形加载 第一 范围 距离是一样的 第二 需求问题
在这里插入图片描述

首先 是像素坐标转换成 格子坐标

在这里插入代码片
```/**
     *  六边形 像素位置转换格子位置根据 位置转换
     * 3d 是 x z  2d 是 x y
    //  格子的 宽度
		    public static RANCH_TILE_WIDTH = 10;
		    // 格子的 高度
		    public static RANCH_TILE_HEIGHT = 8.66666;
		    // 左偏移量
		    public static SIDE_OFFSET_X = (ITileHelper.RANCH_TILE_WIDTH -(ITileHelper.RANCH_TILE_HEIGHT / 2)) / 2;
		    // 高的 偏移量
		    public static SIDE_OFFSET_Y = ITileHelper.RANCH_TILE_HEIGHT / 2;
		    //  行的高度
		    public static RANCH_ROW_HEIGHT = ITileHelper.RANCH_TILE_HEIGHT / 2;
		    // 列的宽度
		    public static RANCH_COLUMN_WIDTH =  ITileHelper.RANCH_TILE_HEIGHT / 2 + ITileHelper.SIDE_OFFSET_X;
     * @param x 
     * @param z
     */
    public getHexagonalPixelToTileWithPosition(x: number, z: number, factor: number = 1) {
		//  边的偏移 是 (格子的宽度 -  高度 /2)/ 2  
        let sideOffsetX = ITileHelper.SIDE_OFFSET_X
        //  这个是格子的宽度 / 2  + 偏移量 也就是格子的 4分之3 处;
        let columnWidth = ITileHelper.RANCH_COLUMN_WIDTH;
        // 这个是 高度 / 2
        let rowHeight = ITileHelper.RANCH_ROW_HEIGHT;
        // 这个是格子的高度
        let tileHeight = ITileHelper.RANCH_TILE_HEIGHT;
        // 宽度 / 2
        let sideLengthX = columnWidth / 2;
		// 一个 数租记录 距离的位置 来辅助 定位 记录四个位置 最后来比较 里那个位置最近来辅助定位
        if (!this._center) {
            let lift = sideLengthX / 2;
            let centerX = lift + columnWidth;
            let centerZ = tileHeight / 2;
            let arr: Vec3[] = [];
            arr.push(new Vec3(lift, 0, centerZ));
            arr.push(new Vec3(centerX, 0, centerZ - rowHeight));
            arr.push(new Vec3(lift, 0, centerZ + rowHeight));
            arr.push(new Vec3(centerX + columnWidth, 0, centerZ));
            this._center = arr;
        }

		// 获取理论的格子中心偏移点
        let xx = x - sideOffsetX;
        //  正反方向 如果  2d 则等于 z
        let zz = -z;
		
        let referenceX = Math.floor(xx / (columnWidth * 2));
        let referenceZ = Math.floor(zz / (rowHeight * 2));

        // Relative x and y position on the base square of the grid-aligned tile
        let rel = new Vec3(xx - referenceX * (columnWidth * 2), 0, zz - referenceZ * (rowHeight * 2));

        // Adjust the reference point to the correct tile coordinates
        referenceX *= 2;
		
        let nearest = 0;
        let minDist = 10000000;
		//  循环对比最近的距离
        for (let i = 0; i < this._center.length; ++i) {
            var dc = this._center[i].clone().subtract(rel).length();
            if (dc < minDist) {
                minDist = dc;
                nearest = i;
            }
        }
        let outTileV3 = v3(referenceX, 0, -referenceZ);
        outTileV3.add(PolygonRectControl._offsetsStaggerX[nearest]);
        outTileV3.multiplyScalar(factor);
        return outTileV3;
    }


    private static _offsetsStaggerX: Vec3[] = [
        new Vec3(0, 0, 0),
        new Vec3(1, 0, 1),
        new Vec3(1, 0, 0),
        new Vec3(2, 0, 0),
    ]

然后是 格子坐标转换成像素坐标

    /// <summary>
    /// 将格子坐标转像素坐标
    /// </summary>
    /// <param name="tileV3"></param>
    /// <param name="outPosV3"></param>
    public static TileToPixel(x: number, z: number, Vector3: Vec3 = null): Vec3 {
        let outPosV3 = new Vec3();

        let tileX = x;
        let tileZ = z;

        let Z = tileZ * (ITileHelper.RANCH_ROW_HEIGHT + ITileHelper.SIDE_OFFSET_Y);
        if (PolygonRectControl.DoStaggerX(tileX)) {
            Z -= ITileHelper.RANCH_ROW_HEIGHT;
        }

        let X = tileX * (ITileHelper.RANCH_COLUMN_WIDTH);

        outPosV3.x = X;
        outPosV3.y = 1;
        outPosV3.z = Z;
        return outPosV3;
    }


    public static DoStaggerX(x: number): boolean {
        return x % 2 != 0;
    }

所有的格子坐标会有一个 key 值作为记录 方便读取格子 或者 获取区域格子等等

    /// <summary>
    /// 将格子坐标转格子标识 注意 不能出现负数 出现负数会 出现错误
    /// </summary>
    /// <param name="tileX"></param>
    /// <param name="tileY"></param>
    /// <param name="tileZ"></param>
    /// <returns>格子标识</returns>
    public static TileToTileKey(tileX: number, tileY: number, tileZ: number): number {
        return 1000000000 + tileX * 1000000 + tileY * 1000 + tileZ;
    }

然后 通过 key值 转换成格子坐标

    /// <summary>
    /// 将格子标识转格子坐标
    /// </summary>
    /// <param name="tileKey"></param>
    /// <param name="outTileV3"></param>
    public static TileKeyToTile(tileKey: number): Vec3 {
        let baseKey = (tileKey - 1000000000) //;
        let x = (baseKey / 1000000) % 1000 | 0;
        let y = (baseKey / 1000) % 1000 | 0;
        //1040999999
        let z = (baseKey / 1) % 10000 | 0;
        // 这里片段就是 可能出现 负数  以后自己优化一下 正常来讲不会出现负坐标的格子 要是会有 负坐标的格子 就需要改//一下 key 的生成方式 和解析方式
        if(z >= 9000){
            z =  -(10000 - z);
            x+=1

        }else if(z < -9000){
            z = 10000 + z;
            x-=1
        }

        let outTileV3 = new Vec3();
        outTileV3.x = x;
        outTileV3.y = y;
        outTileV3.z = z;
        return outTileV3;
    }

以上就是完成的六边形格子 处理 以后有时间了在吧 摄像机 区域加载 动态显示 隐藏 或者缓冲池加载写上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值