2013-09-05 2 views
2

У меня есть игра, инициализированная для работы в 1920x1080. Все спрайты, векторы и т. Д. Специально размещены правильно, чтобы соответствовать жанру 1920x1080.Изменение и масштабирование разрешения игры XNA

У меня есть enum, в котором указано, что такое res, игра предлагается использовать. Стандарт 1920x1080. Есть ли способ, скажем, имеет разрешение 1280х960, на пути этого:

  • окно игры является 1280x960
  • разрешения игры (BackBuffer) по-прежнему 1920х1080, но масштабируется вниз установите окно - 1280x960.

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

+1

Если вы держите BackBuffer в этой резолюции и порт только отображается вид на более низкий, Арен» t вы вроде бы тратите много времени на GPU, потенциально отставая от игры, если машина пользователя не может запустить ее в полном HD? – Renan

+0

У вас могут быть переменные, основанные на разрешении, которое использует ваш код для рисования и масштабирования спрайтов. Вместо чего-то вроде 'Rectangle Destination = new Rectangle (0,0,1920/2,1080/2)' у вас может быть 'Rectangle Destination = новый Rectangle (0,0, width/2, height/2)', где ' width' и 'height' являются общедоступными переменными, которые равны разрешению экрана. – davidsbro

ответ

4

Я думаю, вы должны вручную изменить каждый Vector2 или Rectangle вам нужно сделать их отношение к вашей резолюции, или (если вы можете) использовать переменные, которые основаны на Window.ClientBounds.Width или Window.ClientBounds.Height, а davidsbro писал.
Что-то вроде этого:

Vector2 largeResolution = new Vector2(1920, 1080); 
Vector2 smallResolution = new Vector2(1280, 960); 
// you should have already set your currentResolution previously 
Vector2 screenRatio = currentResolution/largeResolution; 

И теперь ваша инициализация стала:

Vector2 position = new Vector2(200, 400) * screenRatio; 
Rectangle imageRect = new Rectangle((int)(100 * screenRatio.X), (int)(200 * screenRatio.Y), ...); 

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

5

На самом деле существует очень простое решение. Как отметил Пинкерманн, вам нужно знать соотношение сторон (коэффициент экрана), но вы будете использовать его в методе SpriteBatch.Begin, где вы пройдете масштаб Vector2 через Matrix.CreateScale (Vector3 Здесь, где Z 1) и использовать его в качестве окончательного аргумента в методе SpriteBatch.Begin.

Большинство других аргументов в этом случае можно оставить нулевым.

В основном, что он делает, он сообщает, что spritebatch рисует все со смещением (шкалой), применяемым как к положению, так и по размеру. Это означает, что когда в моем случае я помещаю что-то на 640x400, независимо от того, какое разрешение я запускаю на экране, оно все равно начинается с мертвой точки экрана. Очень полезно, если вы спросите меня.

Пример из моего текущего проекта:

/// <summary> 
/// Resolution 
/// </summary> 
public static class Resolution 
{ 
    private static Vector3 ScalingFactor; 
    private static int _preferredBackBufferWidth; 
    private static int _preferredBackBufferHeight; 

    /// <summary> 
    /// The virtual screen size. Default is 1280x800. See the non-existent documentation on how this works. 
    /// </summary> 
    public static Vector2 VirtualScreen = new Vector2(1280, 800); 

    /// <summary> 
    /// The screen scale 
    /// </summary> 
    public static Vector2 ScreenAspectRatio = new Vector2(1, 1); 

    /// <summary> 
    /// The scale used for beginning the SpriteBatch. 
    /// </summary> 
    public static Matrix Scale; 

    /// <summary> 
    /// The scale result of merging VirtualScreen with WindowScreen. 
    /// </summary> 
    public static Vector2 ScreenScale; 

    /// <summary> 
    /// Updates the specified graphics device to use the configured resolution. 
    /// </summary> 
    /// <param name="device">The device.</param> 
    /// <exception cref="System.ArgumentNullException">device</exception> 
    public static void Update(GraphicsDeviceManager device) 
    { 
     if (device == null) throw new ArgumentNullException("device"); 

     //Calculate ScalingFactor 
     _preferredBackBufferWidth = device.PreferredBackBufferWidth; 
     float widthScale = _preferredBackBufferWidth/VirtualScreen.X; 

     _preferredBackBufferHeight = device.PreferredBackBufferHeight; 
     float heightScale = _preferredBackBufferHeight/VirtualScreen.Y; 

     ScreenScale = new Vector2(widthScale, heightScale); 

     ScreenAspectRatio = new Vector2(widthScale/heightScale); 
     ScalingFactor = new Vector3(widthScale, heightScale, 1); 
     Scale = Matrix.CreateScale(ScalingFactor); 
     device.ApplyChanges(); 
    } 


    /// <summary> 
    /// <para>Determines the draw scaling.</para> 
    /// <para>Used to make the mouse scale correctly according to the virtual resolution, 
    /// no matter the actual resolution.</para> 
    /// <para>Example: 1920x1080 applied to 1280x800: new Vector2(1.5f, 1,35f)</para> 
    /// </summary> 
    /// <returns></returns> 
    public static Vector2 DetermineDrawScaling() 
    { 
     var x = _preferredBackBufferWidth/VirtualScreen.X; 
     var y = _preferredBackBufferHeight/VirtualScreen.Y; 
     return new Vector2(x, y); 
    } 
} 

И использование:

/// <summary> 
    /// Draws the game objects to the screen. Calls Root.Draw. 
    /// </summary> 
    /// <param name="gameTime">The game time.</param> 
    protected override void Draw(GameTime gameTime) 
    { 
     // TODO: Camera 
     SpriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, Resolution.Scale); 
     Root.Draw(SpriteBatch, gameTime); 
     SpriteBatch.End(); 

     base.Draw(gameTime); 
    } 

Надежда этот пример кода является полезным.

ПРИМЕЧАНИЕ: Выполнение этого способа, предложенного Пинкерманом, не является неправильным способом, однако я убежден, что помимо очевидного (изначально большего количества кода, но в конечном итоге меньше), то, что предложил Пинкерман, также может занимать больше производительности. Это только догадка, и это просто основано на том, что GPU, вероятно, более эффективен в расчетах, связанных с размещением экрана, чем у CPU.

Но не вешайте меня на нем.

@Edit:

Чтобы получить координаты мыши по отношению к объектам на экране:

public Vector2 GetMouseCoords() 
{ 
    var screenCoords = Mouse.GetPosition(); // Or whatever it's called. 
    var sceneCoords = screenCoords/Resolution.ScreenScale; 
    return sceneCoords; 
} 
+0

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

+0

Я обновил свой ответ, чтобы ответить на ваш вопрос (думаю) – Falgantil

+0

Спасибо! Это замечательно. –

Смежные вопросы