Как мне масштабировать графику игры?

Я делаю игру на C# и XNA 4.0. Это в значительной степени закончено, но теперь я хочу добавить настройки, чтобы игроки могли изменить размер окна, если они захотят. Текущая настройка выглядит следующим образом:

void Initialize()
{
    //The window size is initally 800x480
    graphics.PreferredBackBufferWidth = 800;
    graphics.PreferredBackBufferHeight = 480;
    graphics.ApplyChanges();
}

void Update()
{
    //If the player completes an action, the window size is changed
    if (windowSizeChanged)
    {
        graphics.PreferredBackBufferWidth = 1024;
        graphics.PreferredBackBufferHeight = 720;
        graphics.ApplyChanges();
    }
}

Используя этот код, вот как выглядит игра в определенных разрешениях:

800x480

1024x720

Как можно надеяться, вы можете видеть, что при изменении размера окна это не влияет на реальную графику игры. Спрайты и хитбоксы всех объектов остаются одинакового размера, поэтому вместо этого они заполняют небольшую рамку в углу экрана, а не во всем окне. Может кто-нибудь сказать мне, как я могу масштабировать спрайтов, чтобы они заполняли окно? Я предполагаю, что мне нужно будет использовать какую-то матрицу, но может ли кто-нибудь указать мне правильное направление?

Редактировать:

Вот код розыгрыша.

void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    base.Draw(gameTime);

    spriteBatch.Begin();

    //Background texture drawn at default window size
    spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);

    //Each object in the level (player, block, etc.) is drawn with a specific texture and a rectangle variable specifying the size and coordinates
    //E.g. Each block is a size of 64x64 pixels and in this level they are placed at X-coordinates 0, 64, 128 and so on
    //Each Y-coordinate for the blocks in this level is '480 - 64' (Window height minus block height)
    foreach (/*Object in level*/)
    {
        spriteBatch.Draw(object.Texture, object.TextureSize, Color.White);
    }

    spriteBatch.End();
}

1 ответ

Решение

По умолчанию SpriteBatch предполагает, что ваше мировое пространство совпадает с пространством клиента, что соответствует размеру окна. Вы можете прочитать о SpriteBatch и различных местах в посте Эндрю Рассела.

Когда вы изменяете размер буфера, размер окна также изменяется, изменяя пространство мира вместе с ним (что вам не нужно). Чтобы этого не допустить, вы должны вставить матрицу преобразования между конвейером преобразования, чтобы сделать это исправление.

SpriteBatch.Begin позволяет именно это в одной из своих перегрузок.

Существует множество способов приблизиться к масштабированию, но я предполагаю, что вы хотите масштабировать равномерно, то есть спрайты не растягиваются при изменении соотношения сторон по сравнению с исходным соотношением сторон. Следующий код отрегулирует масштабирование в зависимости от начальной высоты экрана.

...

const float initialScreenHeight = 480f; 
Matrix transform = Matrix.CreateScale(GraphicsDevice.Viewport.Height / viewportHeightInWorldSpace);

spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, transform);

...

Обратите внимание, что при изменении разрешения таким образом, что соотношение сторон изменяется по сравнению с исходным соотношением сторон, вы столкнетесь с такими проблемами, как рисование за пределами экрана (вправо) или не рисование у правого края экрана (получение аналогичного синего цвета). фон как сейчас).

Кроме того, вы не хотите вычислять эту матрицу масштабирования для каждого кадра в методе Draw, а только при изменении разрешения.

Другие вопросы по тегам