侧边栏壁纸
  • 累计撰写 793 篇文章
  • 累计创建 1 个标签
  • 累计收到 1 条评论
标签搜索

目 录CONTENT

文章目录
MC

射线与方块碰撞检测

Dettan
2021-07-10 / 0 评论 / 0 点赞 / 169 阅读 / 694 字
温馨提示:
本文最后更新于 2022-07-23,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
// 参数:起始点,结束点,不忽略液体,忽略非固体方块
public MovingObjectPosition rayTraceBlocks_do_do(Vec3 start, Vec3 end, boolean fluid, boolean noNonSolid)
{
    if (!Double.isNaN(start.xCoord) && !Double.isNaN(start.yCoord) && !Double.isNaN(start.zCoord))
    {
        if (!Double.isNaN(end.xCoord) && !Double.isNaN(end.yCoord) && !Double.isNaN(end.zCoord))
        {
            // 终点方块坐标
            int intX2 = MathHelper.floor_double(end.xCoord);
            int intY2 = MathHelper.floor_double(end.yCoord);
            int intZ2 = MathHelper.floor_double(end.zCoord);
            // 起点(当前)方块坐标
            int intX1 = MathHelper.floor_double(start.xCoord);
            int intY1 = MathHelper.floor_double(start.yCoord);
            int intZ1 = MathHelper.floor_double(start.zCoord);

            // 检测起点方块
            int id = this.getBlockId(intX1, intY1, intZ1);
            int data = this.getBlockMetadata(intX1, intY1, intZ1);
            Block block = Block.blocksList[id];
  
            if (block != null && (!noNonSolid || block == null || block.getCollisionBoundingBoxFromPool(this, intX1, intY1, intZ1) != null) && id > 0 && block.canCollideCheck(data, fluid))
            {
                MovingObjectPosition movingobjectposition = block.collisionRayTrace(this, intX1, intY1, intZ1, start, end);

                if (movingobjectposition != null)
                {
                    return movingobjectposition;
                }
            }

            id = 200; // 最多检测201个方块

            while (id-- >= 0)
            {
                if (Double.isNaN(start.xCoord) || Double.isNaN(start.yCoord) || Double.isNaN(start.zCoord))
                {
                    return null;
                }
                // 检测了终点方块
                if (intX1 == intX2 && intY1 == intY2 && intZ1 == intZ2)
                {
                    return null;
                }

                // 起点(当前)方块和终点方块XYZ不同(向某方向选了候选方块)
                boolean Xchanged = true;
                boolean Ychanged = true;
                boolean Zchanged = true;
                // 各方向候选方块坐标
                double newX;
                double newY;
                double newZ;

                // 尝试向X方向选候选方块
                if (intX2 > intX1)
                {
                    newX = (double)intX1 + 1.0D;
                }
                else if (intX2 < intX1)
                {
                    newX = (double)intX1;
                }
                else
                {
                    Xchanged = false;
                }

                if (intY2 > intY1)
                {
                    newY = (double)intY1 + 1.0D;
                }
                else if (intY2 < intY1)
                {
                    newY = (double)intY1;
                }
                else
                {
                    Ychanged = false;
                }

                if (intZ2 > intZ1)
                {
                    newZ = (double)intZ1 + 1.0D;
                }
                else if (intZ2 < intZ1)
                {
                    newZ = (double)intZ1;
                }
                else
                {
                    Zchanged = false;
                }

                // 各方向候选方块离起点(当前)有多近,初始化为很大的数
                double Xt = 999.0D;
                double Yt = 999.0D;
                double Zt = 999.0D;
                double dX = end.xCoord - start.xCoord;
                double dY = end.yCoord - start.yCoord;
                double dZ = end.zCoord - start.zCoord;

                // 向X方向选了候选方块
                if (Xchanged)
                {
                    Xt = (newX - start.xCoord) / dX;
                }

                if (Ychanged)
                {
                    Yt = (newY - start.yCoord) / dY;
                }

                if (Zchanged)
                {
                    Zt = (newZ - start.zCoord) / dZ;
                }

                // 最终选了哪个方向的候选方块
                byte direction;

                // 选出候选方块中离起点(当前)最近的,更新起点、要检测的方块坐标
                if (Xt < Yt && Xt < Zt)
                {
                    if (intX2 > intX1)
                    {
                        direction = 4;
                    }
                    else
                    {
                        direction = 5;
                    }
  
                    start.xCoord = newX;
                    start.yCoord += dY * Xt;
                    start.zCoord += dZ * Xt;
                }
                else if (Yt < Zt)
                {
                    if (intY2 > intY1)
                    {
                        direction = 0;
                    }
                    else
                    {
                        direction = 1;
                    }

                    start.xCoord += dX * Yt;
                    start.yCoord = newY;
                    start.zCoord += dZ * Yt;
                }
                else
                {
                    if (intZ2 > intZ1)
                    {
                        direction = 2;
                    }
                    else
                    {
                        direction = 3;
                    }

                    start.xCoord += dX * Zt;
                    start.yCoord += dY * Zt;
                    start.zCoord = newZ;
                }
  
                intX1 = MathHelper.floor_double(start.xCoord);

                if (direction == 5) // X-方向
                {
                    // MC以方块内各轴最小坐标为方块坐标,这里得到的是X上最大坐标所以要-1
                    --intX1;
                }

                intY1 = MathHelper.floor_double(start.yCoord);

                if (direction == 1) // Y-方向
                {
                    --intY1;
                }

                intZ1 = MathHelper.floor_double(start.zCoord);

                if (direction == 3) // Z-方向
                {
                    --intZ1;
                }

                // 检测新起点方块
                int id2 = this.getBlockId(intX1, intY1, intZ1);
                int data2 = this.getBlockMetadata(intX1, intY1, intZ1);
                Block block2 = Block.blocksList[id2];

                if ((!noNonSolid || block2 == null || block2.getCollisionBoundingBoxFromPool(this, intX1, intY1, intZ1) != null) && id2 > 0 && block2.canCollideCheck(data2, fluid))
                {
                    MovingObjectPosition movingobjectposition1 = block2.collisionRayTrace(this, intX1, intY1, intZ1, start, end);

                    if (movingobjectposition1 != null)
                    {
                        return movingobjectposition1;
                    }
                }
            }
            return null;
        }
        else
        {
            return null;
        }
    }
    else
    {
        return null;
    }
}

0

评论区