问题描述:

When you have to display a series of visual components (sprites) within the context of a game each taking a literal height and width that needs to be relative to the height & width of the Viewport (not necessarily aspect ratio) of the target device:

  • Is there a scaling class to help come up with scaling ratio in a dynamic fashion based on current device viewport size?
  • Will I need to roll my own scaling ratio algorithm?
  • Any cross platform issues I should be aware of?

This is not a question relating to the loading of assets based on target device nor is it a question of how to perform the scaling of the sprite (which is described here: http://msdn.microsoft.com/en-us/library/bb194913.aspx), rather a question of how to determine the scale of sprites based on view port size.

网友答案:

You can always create your own implementation of scaling.

For example, the default target viewport dimensions are:

const int defaultWidth = 1280, defaultHeight = 720;

And your current screen dimensions are 800×600, which gives you a (let's use a Vector2 instead of two floats):

int currentWidth  = GraphicsDevice.Viewport.Width,
    currentHeight = GraphicsDevice.Viewport.Height;

Vector2 scale = new Vector2(currentWidth  / defaultWidth,
                            currentHeight / defaultHeight);

This gives you a {0.625; 0.83333}. You can now use this in a handy SpriteBatch.Draw() overload that takes a Vector2 scaling variable:

public void Draw (
     Texture2D texture,
     Vector2 position,
     Nullable<Rectangle> sourceRectangle,
     Color color,
     float rotation,
     Vector2 origin,
     Vector2 scale,
     SpriteEffects effects,
     float layerDepth
)

Alternatively, you can draw all your stuff to a RenderTarget2D and copy the resulting image from there to a stretched texture on the main screen, but that will still require the above SpriteBatch.Draw() overload, though it might save you time if you have lots of draw calls.

网友答案:

Another Option to generate the scale would be to leverage:

var scaleMatrix = Matrix.CreateScale(
           (float)GraphicsDevice.Viewport.Width / View.Width,
           (float)GraphicsDevice.Viewport.Width / View.Width, 1f);

http://msdn.microsoft.com/en-gb/library/bb195692.aspx.

But this did not meet my needs, as I would then have to roll my own transform to map touch input location to the 'transformed' sprites (which respond to user touch input by knowing their own position and size).

In the end I used a percentage based approach.

I basically got the viewport height and width...

GraphicsDevice.Viewport.Width  
GraphicsDevice.Viewport.Height

...then calculated the Height and Width of my sprites (Note: "as mentioned in question they take a literal height and width") based on their relative size to the screen myself using percentages.

//I want the buttons height and width to be 20% of the viewport 
var x, y = GraphicsDevice.Viewport.Width * 0.2f; //20% of screen width
var btnsize = new Vector(x,y);
var button = new GameButton(btnsize);

Then once I have the size of the button I am able to calculate the position on the screen to render the button based of the size of the button and the available viewport size, against working in relative position based in percentages.

相关阅读:
Top