XNA ViewPort投影和SpriteBatch

时间:2010-08-25 21:06:03

标签: c# matrix xna

我正在开发一个XNA游戏,我使用ViewPort.Project和ViewPort.Unproject来转换世界坐标和从世界坐标转换。目前我将这些用于我使用SpriteBatch绘制的每个对象。我想做的是计算一个我可以发送到SpriteBatch.Begin的矩阵来为我做屏幕空间转换。

以下是我目前用于翻译屏幕空间的功能:

        Vector2 ToWorldCoordinates(Vector2 pixels)
    {
        Vector3 worldPosition = graphics.GraphicsDevice.Viewport.Unproject(new Vector3(pixels, 0),
                Projection, View, Matrix.Identity);
        return new Vector2(worldPosition.X, worldPosition.Y);
    }

    Vector2 ToScreenCoordinates(Vector2 worldCoords)
    {
        var screenPositon = graphics.GraphicsDevice.Viewport.Project(new Vector3(worldCoords, 0),
                Projection, View, Matrix.Identity);
        return new Vector2(screenPositon.X, screenPositon.Y);
    }

视图设置为Matrix.Identity,Projection设置如下:

Projection = Matrix.CreateOrthographic(40 * graphics.GraphicsDevice.Viewport.AspectRatio, 40, 0, 1);

以下是我目前的绘画方式:

            spriteBatch.Begin();
        foreach (var thing in thingsToDraw)
        {
            spriteBatch.Draw(thing.Texture, ToScreenCoordinates(thing.PositionInWorldCoordinates), thing.Color);
            spriteBatch.End();
        }
        spriteBatch.End();

这就是我想做的事情(使用XNA 4.0版本的SpriteBatch.Begin())

            // how do I calculate this matrix?
        Matrix myTransformationMatrix = GetMyTransformationMatrix();

        spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null,
            myTransformationMatrix);

        foreach (var thing in thingsToDraw)
        {
            // note: no longer converting each object's position to screen coordinates
            spriteBatch.Draw(thing.Texture, thing.PositionInWorldCoordinates, thing.Color);
            spriteBatch.End();
        }
        spriteBatch.End();

1 个答案:

答案 0 :(得分:12)

我写过关于SpriteBatch和各种“空格”(世界,投影,客户等)hereherehere的文章。这些答案可能值得一读。

SpriteBatch假设你的世界空间与客户空间是一样的 - 然而,视口的高度和宽度都是很多,原点是左上角,Y +是向下的。

看起来(基于您对CreateOrthographic的使用),您希望您的世界空间在屏幕上显示为40个单位高,然而许多单位将适合宽度。您还希望世界原点位于屏幕中央,Y +已启动。

所以你必须在两者之间插入另一个矩阵才能将你的世界空间转换为客户空间。我相信正确的矩阵是(在psudocode中):scale(40/viewport.Height) * scale(1, -1) * translate(viewport.Width/2, viewport.Height/2)。缩放,翻转和翻译,从世界到客户。

你还必须记住,精灵假设Y +已经失效。所以你必须将(1, -1)比例传递给SpriteBatch.Draw,否则它们将被反转(并且由于背面剔除,不可见)。