Проекция XNA ViewPort и SpriteBatch - PullRequest
4 голосов
/ 26 августа 2010

Я работаю над игрой 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 = 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();

Это то, что я хотел бы сделать вместо этого (используя версию SpriteBatch.Begin () XNA 4.0)

            // 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 Ответ

12 голосов
/ 26 августа 2010

Я написал о SpriteBatch и различных «пространствах» (мир, проекция, клиент и т. Д.) здесь , здесь и здесь .Эти ответы, вероятно, заслуживают прочтения.

SpriteBatch предполагает, что пространство World такое же, как и пространство Client, которое, тем не менее, имеет много пикселей в высоту и ширину в окне просмотра, начало слева вверху, Y + вниз.

Похоже (на основе вашего использования CreateOrthographic) вы хотите, чтобы ваше пространство Мира отображалось на экране как 40 единиц высоты, и сколько бы единиц не подходили ширине.Вы также хотите, чтобы начало координат Мира находилось в центре экрана, а Y + вверх.

Таким образом, вам нужно вставить другую матрицу между ними, чтобы преобразовать пространство Мира в пространство Клиента.Я считаю, что правильная матрица (в псевдокоде): scale(40/viewport.Height) * scale(1, -1) * translate(viewport.Width/2, viewport.Height/2).Масштабируйте, переворачивайте и переводите, чтобы перейти от мира к клиенту.

Вы также должны помнить, что спрайты предполагают, что Y + не работает.Таким образом, вы должны передать (1, -1) шкалу в SpriteBatch.Draw, в противном случае они будут нарисованы инвертированными (и, из-за отбраковки задней поверхности, будут невидимыми).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...