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

射线与方块碰撞检测

Dettan
2021-07-10 / 0 评论 / 0 点赞 / 96 阅读 / 3,356 字
温馨提示:
本文最后更新于 2022-04-30,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
// 参数:起始点,结束点,不忽略液体,忽略非固体方块
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

评论区