In my XNA game, I program and design the entire thing for 1920x1080 resolution and then scale scale and letterbox to fit the running system (XBox or PC).
This has been a great solution as it allows me to only ever worry about one resolution.
However, I'm now wondering if this will come back to bite me in the future as the game becomes more complex.
Since I'm having to scale everything with every draw (I scale SpriteBatch.Begin() with the scale factor only once, do all drawing, then call End()), is this going to have any detrimental effect on performance? I know the XBox already does this for XNA games for you when set to 720p natively (which, I actually am when running on XBox, it just gets the appropriate scaling factor).... so I can't imagine it's too bad, even for the PC.
The xbox does its scale in a specialized scaler in the video output - there is zero performance hit to your app.
The scale factor you pass in to SpriteBatch just translates the vertices of your sprite. Its done with a factor of 1 even if you don't pass in a scale so there is no extra load there.
With different screen sizes there will be different fill rates (more or less pixels) and texture lookups will be different too so that will show some variances.
Just using a 1028x720 backbuffer is the safest to do. The xbox can hardware scale that into ANY resolution or ratio without a single line of code or any perf issues. It will letter box properly and the hardware scaler is very good quality. You cannot claim 1080p support is really the only downside.
If you chose 1020x1080 as your back buffer note that the hardware scaler cannot scale that down to 480i and WILL fail in peer review (well it should if anyone notices)
On WIndows the easiest thing is probably to draw everything to a RenderTarget and then just scale the whole darn thing on one go at the end. See the SpaceWar starterkit for the few lines of code it takes to do that. (All inside #if !XBOX so you dont waste cycles doing it on the 360)
This shouldn't cost you. The scaling is done by he video card.
However, if this does worry you, another option to handle different resolutions is to change the render target to an off screen buffer, render to that, and then draw a square on the screen with the buffer as the texture. More pixels are rendered, but you don't need to do a transform on each vertex.
Related
I'm creating a 3D mobile game where my base reference screen size is the Galaxy S9, with an aspect ratio of 18:37 (portrait). The player controls a box where you can move +/- 5 units along X axis and objects fall down that you have to either avoid or catch.
That part is easy, the hard part is that when I change the aspect ratio or resolution, the game scale changes as well, and now +/- 5 units on the X axis means my box can be cut off, or completely off screen.
My goal is to limit the camera view so that it always shows the same coordinates no matter the aspect ratio or resolution, within reason (being portrait mode on a phone, obviously don't want to care about it working in landscape or on a PC/Mac).
How can I accomplish this with the minimum amount of stretching or distortion to the game objects? I saw some people show a way to accomplish this for orthographic views, but my camera must be in perspective for this. The default FoV I'm using is 60, and I'm thinking I can try scaling the FoV based on aspect ratio, but I'm at a loss for how to start. Any help is appreciated!
Supporting multiple aspect ratios for games is definitely one of the most frustrating things about making a game look professional.
Probably the most common technique is the same technique used by Film, called letterboxing.
TVs had to solve a problem when widescreen first came out: How do you show a 16:9 film on a TV with an aspect of 4:3? There are two options: either add black bars to the top and bottom of the screen to make the aspect 4:3, or you can make sure that everything important is happening in the middle area that will be shown by both aspect ratios and then just cut off part of the view if it doesn't fit within the aspect ratio.
My suggestion is to surround the playable area with something that looks good, but wont affect the game if it gets cut off. Then write a routine that will run when your level loads for your camera to zoom out until all of the play area is visible. Since you zoomed out, this means that devices which do not have the same aspect ratio as your play area will be able to see the area around the play area. As long as you have non-play area that is big enough, there won't be an issue.
Here are some good examples:
Note: Sorry the examples are orthographic, but the same should work for perspective, you just may have to be a little creative with doing a projection from the camera frustrum to determine if your play area is all visible
I'm making a shape matching game for toddlers.
I drew the shapes using gimp on my mac.
The images all seemed stretched out on the android devices.
Is there some mathematical way i could figure out how much shorter I have to make the images on the mac computer so they look correctly on the android devices?
This is a tough question. I have made several Apps for iOS and have pretty much the same problem with graphics for buttons and backgrounds when going between iPhone and iPad, which have different aspect ratios (which I suspect is the problem you are having). Throw orientation into the mix as well.
I use Gimp, Inkscape, Spine, Cocos2d-x, and lots of other tools for reference (see here).
As far as I know, the general options for "different screen geometry" issues are (if there are others, let me know):
Different graphics for each geometry.
Scaling the graphics proportionally for the geometry (I suspect you have this).
Same graphics for all, scale proportionally based on one dimension and then place graphics on screen using percentages for fixed stuff.
Option 1 means extra work...not acceptable for a hobbyist or indie (like me) developer.
Option 2 usually looks like junk. Frustration and sadness usually ensue.
Option 3 is the option I use most often. I find that occasionally I have to add small changes (read: hacks) based on the device or geometry. In the case of iOS, it is not too bad, because there are only two geometries to deal with. In the case of Android, where there are lots of different tablet geometries, you could cut it down by working with ranges of geometries and picking a fixed orientation for your application.
At the end of the day, proportional scaling by a single dimension (height or width) has gotten me the most bang for the buck.
I usually make the graphics a little "bigger" than I will need so I only have to scale down. This consumes a bit more memory, but I re-use a lot, use sprite sheets, etc. There is a definite tradeoff with managing every bit of memory (which you have to do in a large AAA rated game) and what you can get away with in a small independent application. I am not encouraging sloppiness or memory mismanagement; I'm encouraging balancing the resources against the developmental needs of simplicity...making the same graphics for different situations burns a lot of daylight.
ONE MORE NOTE:
For applications where I use a framework for the graphics (i.e. games), I use a "viewport" to let me match up the physics with the graphics...that is to say, dynamically scale the size of the graphics based on how much of the total scene I want the user to see. This lets me put the graphic for the "body" on top of it and match up the size statically or dynamically as needed. The code is in C++ and is only loosely tied to the framework...and the concept is applicable to general situations for games (i.e. scaling the graphics as needed). You can find some description and code here, if you are interested.
Was this helpful?
You need to design your application so that it can function correctly regardless of device resolution as many mobile devices have many different aspect ratios and resolutions.
If your images are being stretched then you need to change the ui design so that they are enlarged and spaced out to make use of whatever space there is.
I am going to play around with making an XNA game.
The windows store has two base resolutions it reccommends you support: 1024x768 and 1366x768
But after that there are no restrictions.
The common advice is to use a ViewBox that will scale your content for you.
But an XNA game does not have a viewbox. It has a draw method where you render your content.
What is the common way for Games (XNA or DirectX) to adapt to different resolutions?
I would rather not have to make images for each and evey resolution out there. It would be a lot of work and I am bound to miss some.
Is there a better way?
GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Widthand.Height will give you the current desktop resolution.
Then you can update Game.GraphicsDevice.Viewport variables to use these settings.
The above code usually goes in Game1.cs constructor
The link provided then documents one technique that makes your sprites, backgrounds etc look correct independently of the resolution(the theory should be sound if the code is not 100% up to date)
http://msdn.microsoft.com/en-us/library/bb447674%28v=xnagamestudio.10%29.aspx
There are two different approachs I read in a tutorial:
Resize everything to the new viewport (even with changing aspect ratio)
Just draw more surroundings around
Of course you can mix both: Resize everything as long as it can still be in the same aspect ratio (e.g. 4:3 or 16:9) and then show more or less background / surroundings.
You can also decide to display black content instead of the more surroundings, if it is important for everyone to have exactly the same sight (e.g. due to fairness), but in such a case it might be a better idea to use fog of war to reduce sight.
I have been using XNA to make a PC game and I am doing lighting with RenderTarget2D by drawing the world stuff in one and then drawing the lightmask stuff in another. Anyway I wasn't running into any problems at first using my 1920x1080 monitor, but I just upgraded to a 27" 2560x1440 S-IPS monitor and now I'm getting an error because my monitor resolution is set higher than 2048 and that's apparently the largest size a texture can be.
It's trying to draw a texture of size 2560 by 1440 so I need to find a way around that limitation. I suppose with large screens I could somehow split it into multiple RenderTarget2Ds. My issue with that is how I pass in the light mask:
drawMain();
drawLightMask();
ScreenManager.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
lightingEffect.Parameters["lightMask"].SetValue(lightMask);
lightingEffect.CurrentTechnique.Passes[0].Apply();
ScreenManager.SpriteBatch.Draw(mainScene, new Vector2(0, 0), Color.White);
ScreenManager.SpriteBatch.End();
I'm sure others have had to deal with this issue so maybe someone has some ideas on how I could approach this 2048 limitation?
Edit: Another thought.. perhaps when I detect that have a large resolution I just set it lower instead of default setting it to their current resolution. That way wouldn't really have to worry about it. The problem with this way is that in fullscreen mode it's changing their screen's resolution so when they exit the game it has to change resolutions again and is kind of messy. Then in borderless winowed mode the window is smaller but it doesn't seem to change your resolution.
I am having a major performance problem with a game I'm developing for Windows Phone 7 in C# XNA 4.0.
There's a lot of code going on, like collision, input, animations, physics and so on.
The frame rate has been set to 60fps, but is only running at 32fps. I have tried a lot of things, like disabling though stuff like collision detection, but nothing helped getting higher frame rate. Now randomly I discovered when disabling the drawing of the background, which is just a standard 480x800 sized image (Same as the Windows Phone Resolution), and uses the default method "spriteBatch.Draw(Textures.background, Vector2.Zero, Color.White)" the frame rate goes from 32 to 55 fps. I have also tried changing the texture to a plain white one, but that does not help either, and I have also tried moving the drawing of the background to another place in the code, but nothing changed either. I tried making a new project, and just having the background drawed, but the fps would be at 60 fps then as it should. I'm only having one SpriteBatch.Begin() and SpriteBatch.End(), where all the needed sprites are drawed inside. There's 256 Texture2Ds loaded into the game, which all is loaded at the beginning of the game. The game is a sidescroller, so the background needs to move to the left all the time, but even if I just set it to Vector2.Zero, it would still ruin the fps by -20fps. I hope anyone has a solution to this, or at least an idea of why this is happening.
If you have 256 individual Texture2Ds being used within the same SpriteBatch Begiin/End call it's not surprising that performance isn't optimal unless you are ordering the sprites by texture, which you likely are not for a platformer. All that texture switching within the same batch will cause a decrease in framerate - it's likely that the background image is just the straw that breaks the camels back for your particular game setup.
Have you tried combining those 256 separate images into a smaller number of Texture2Ds (i.e. using spritesheets or a texture atlas)? Here is an older link about how proper sprite sorting can affect performance