如何计算xna中目标光标的位置和方向?

时间:2013-01-31 12:51:16

标签: c# xna cursor position game-engine

我开发了像“我的世界”这样的小游戏。我在计算光标方向上停留了几天。 让我解释。 我想用光标在屏幕中间定位一个立方体,然后点击一下就消失。但我没有看到任何如何恢复这些信息.. 有人能指点我“样本/教程”或解释吗? 非常感谢你。

我的屏幕拍摄图片游戏: enter image description here

2 个答案:

答案 0 :(得分:2)

当然,它在很大程度上取决于您如何组织数据。 但是如果你的多边形和网格存储在某个地方(我不是在谈论顶点缓冲区!!),就像在八叉树中一样,你可以这样做:

您可以从相机设置中创建光线并在场景中“触发”它。通常可以扩展八叉树或类似结构,以便轻松地进行射线测试以返回命中元素。当然你可以通过强制迭代所有的四边形,但这很快就会成为性能瓶颈。 从那里你可以使用你想要的结果。

整个过程通常称为“挑选”,this是一个非常好的教程。

答案 1 :(得分:1)

我对大部分内容都不予理睬 - 这就是我在3D XNA游戏中使用的内容。这些评论很有说服力。基本上它会从光标位置直接投射Ray,并检查它是否Intersects()是否是任何地图对象的边界(在这种情况下为Unit

    /// <summary>
    /// Creates a Ray translating screen cursor position into screen position
    /// </summary>
    /// <param name="projectionMatrix"></param>
    /// <param name="viewMatrix"></param>
    /// <returns></returns>
    public Ray CalculateCursorRay(Matrix projectionMatrix, Matrix viewMatrix)
    {
        // create 2 positions in screenspace using the cursor position. 0 is as
        // close as possible to the camera, 1 is as far away as possible.
        Vector3 nearSource = new Vector3(mousePosition, 0f);
        Vector3 farSource = new Vector3(mousePosition, 1f);

        // use Viewport.Unproject to tell what those two screen space positions
        // would be in world space. we'll need the projection matrix and view
        // matrix, which we have saved as member variables. We also need a world
        // matrix, which can just be identity.
        Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearSource,
            projectionMatrix, viewMatrix, Matrix.Identity);

        Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farSource,
            projectionMatrix, viewMatrix, Matrix.Identity);

        // find the direction vector that goes from the nearPoint to the farPoint
        // and normalize it....
        Vector3 direction = farPoint - nearPoint;
        direction.Normalize();

        // and then create a new ray using nearPoint as the source.
        return new Ray(nearPoint, direction);
    }

    private Vector3 cursorRayToCoords(Ray ray, Vector3 cameraPos)
    {
        Nullable<float> distance = ray.Intersects(new Plane(Vector3.Up, 0.0f));
        if (distance == null)
            return Vector3.Zero;
        else
        {
            return cameraPos + ray.Direction * (float)distance;
        }
    }

    public override void Update(GameTime gameTime)
    {
        cursorRay = CalculateCursorRay(camera.Projection, camera.View);
        cursorOnMapPos = cursorRayToCoords(cursorRay, cursorRay.Position);
        checkInput(gameTime);

        base.Update(gameTime);
    }

    /// <summary>
    /// Returns the nearest unit to the cursor
    /// </summary>
    /// <returns>The unit nearest to the cursor</returns>
    private Unit getCursorUnit()
    {
        Unit closestUnit = null;
        float? nearestDistance = null;
        float? checkIntersect = null;

        foreach (Unit unit in map.Units)//checks to see if unit selection
        {
            checkIntersect = cursorRay.Intersects(unit.BoundingSphere);
            if (checkIntersect != null)//if intersection detected
            {
                if (nearestDistance == null) //first unit found
                {
                    closestUnit = unit;
                    nearestDistance = (float)checkIntersect;
                }
                else if ((float)checkIntersect < (float)nearestDistance)//for any others, only find the nearest
                {
                    closestUnit = unit;
                    nearestDistance = (float)checkIntersect;
                }
            }
        }

        return closestUnit;
    }