Talk:Auto-Scaling WVGA XNA Games to WXGA & 720P with MonoGame for WP8

From Nokia Developer Wiki
Jump to: navigation, search


Hamishwillee - Clear and concise

Hi Dan

I have given this a brief scan and minor subedit and it looks clear, concise and useful. Thanks very much! The categories were changed because we're moving to a category model rather than "tagged" model for organising articles.

You will note I removed "Code Examples" - we tend to use that only for articles that have a buildable zip attached for the project (this "supersedes" code snippet category). If reasonable and possible I highly recommend you attach such a test project. What we've found is this helps in future if there are any questions about the article (ie often people say it doesn't work due to copy-paste errors of snippets etc). In essence makes article easier to maintain.



hamishwillee (talk) 03:59, 15 July 2013 (EEST)

This is ridiculous - Auto-Scaling WVGA XNA Games to WXGA & 720P with MonoGame for WP8

Nice Artcile!

However there are some caveats in this approach.

  1. DrawingSurface is slower than DrawingSurfaceBackgroundGrid
  2. From my experiance on scaling the App.Current.Host.Content.GetType().GetProperty("ScaleFactor") method returns a single float value. However this is not always suitable for maintaining correct aspect ratio of your graphics. Consider the situation when you draw a circle bound to WVGA resolution. For WXGA the scaling coef. is 1.6 for both axis. However for 720p its 1.6 horizontal and 1.5 verticla. So if you strech the WVGA to 720p by using only the single scale coeficient you will get cirlces stretched to ovals. And sometimes this is not really acceptable. So from my experience it's better to keep both values for scaling (horizontal and vertical even when using DrawingSurface instead of DrawingSurfaceBackgroundGrid)
  3. This is more of a question. Are the touch points automatically scaled with DrawingSurface? The thing I've faced recently is that they are not when using DrawingSurfaceBackgroundGrid.

I will briefly add my approach to draw for multiple resolutions.

NOTE: We use DrawingSurfaceBackgroundGrid. So rotation and touch are done the custom way.

  1. get the scaling factors (for 720p and WXGA horizontal is 1.6, however for 720p 1.5 is the vertical scale)
  2. get current resolution and invert the values for landscape (for example Vector2 resolution = new Vector2(720, 1280) for portrait, inverted will be Vector2 ScreenSize = new Vector2(resolution.Y, resolution.X)).
  3. then we need a center point of screen in portrait for later drawing (Vector2 halfRes = resolution / 2f ); this will be the point we will rotate render target around
  4. draw everything in WVGA resolution, so we also need virtual screen size (800x480) and a half of it (400, 240). The scale is maintained as Vector2 as well.
  5. draw the game off-screen to Render Targets using virtual screen size (we use 7 of these while drawing gameplay. Most of them are for post effects and lights. One is final image that is presented to the user)
  6. at the very end of Draw function we switch Render Target to null (screen) and draw final rendertaget using the rotation of 90 degrees, with position of half of real resolution, the scaling we got from GetProperty("ScaleFactor") and the origin of half of virtual screen size. At this point everything was good except the controls. The virtual thumb stick and buttons are round, on 720p devices we got those controls horizontally streched.
  7. to compensate the wrong aspect of OSC controls we involved one more variable - the inverted scale (with components swapped by their places)
  8. then we draw our round controls using a spriteBatch overload with Vector2 used for scaling. But we use the inverted scale devided by the X component of real scale.

This might need some of explanation. So: Scales WVGA - (1, 1). 720p - (1.6, 1.5), WXGA - (1.6, 1.6); Inverted Scale is visible only in 720p (1.5, 1.6)

we draw round objects of controller with scaling like InvertedScale / Scale.X. This gives the values like (0.9375, 1), so we get vertically streched image of controls of the OSC by default in 720p that later is compensated horizontally when scaling WVGA renderTarget to 720p. Other resolutions do not need any scaling compensations due to they are not distorted.

this_is_ridiculous (talk) 15:14, 15 July 2013 (EEST)

Hamishwillee - Dan, Artem

Artem, thanks for taking the time to provide detailed expert feedback!

Dan, can this be integrated or does it need another article?

hamishwillee (talk) 04:16, 16 July 2013 (EEST)

Dan Colasanti - Response to comments

Hamish & Artem,

Thanks for your comments and questions. My responses to Artem's three caveats/questions, similarly numbered, are below:

(1) Because DrawingSurface provided sufficient performance for my 2D shooter game (it runs at the desired 30-fps in Debug & Release in the Emulator and on Device for all tested screen resolutions), I didn't bother trying to benchmark/compare its performance with DrawingSurfaceBackgroundGrid. If DrawingSurface does not provide sufficient performance for another game, another method would be needed (such as possibly using DrawingSurfaceBackgroundGrid as you have suggested).

(2) I don't agree that using a single scaling value for both X and Y dimensions is a problem - in fact, it is exactly what is needed to avoid image warping. Scaling a WVGA screen to the full dimensions of a 720P screen (1280x720) would cause warping, but this method only scales the graphics to 1200x720 on 720P screens, and therefore doesn't. Of course, because the entire 720P screen is not used here, letterboxing is needed. Using simple scaling with letterboxing is what makes this method easy. If filling the full 720P screen with graphics is desired, this method can't be used (and neither can scaling each dimension separately, because it will cause image warping). But for quickly scaling to a best-fit within the 720P rectangle, this method seems to work just fine (without image warping) and has been tested with all WP8 screen resolutions.

(3) While this article only discusses scaling WVGA graphics output to WXGA and 720P, your question about resulting touch-points is a good one and something that I should have mentioned in the article. Fortunately, TouchPanel.GetState() still returns WVGA coordinates when the DrawingSurface is scaled using this method. For example, in my game I have the following code:

           TouchState = TouchPanel.GetState();
           touchPt = (TouchState.Count > 0)? TouchState[0] : (TouchLocation?)null;
When my landscape-oriented game is touched on a 720P screen near the bottom right corner, touchPt is assigned values close to { 800, 480 } - exactly what I wanted. I was surprised about this myself, because the scaled viewport bounds on 720P becomes 1200x720, but the touch-points still were within 800x480.

Dan Colasanti (talk) 07:38, 16 July 2013 (EEST)

This is ridiculous - My responses to Artem's three caveats/questions

Thanks for the response. Let's continue the talk in similar fashion :). 1) I respect your choice of DrawingSurface. I do not have anything against it 2) I never said single scalar for scaling is a problem. Instead it was that it's not suitable in all situations. And you accepted the fact of letterboxing for yourself :). However I disagree on warping. As long as you use correct states for the Sampler you will never have any kind of warping no matter how you scale the image to fill the entire screen. A bit later today I will take a photo of our game in it's very early state running on all devices with different resolutions and there's neither letterboxing nor warping happening. 3) Thanks for you response. I suspected that DrawingSurface scales the points by it-self and does rotation for the coder out of the box.

NOTE: please do not consider my comments as offensive. This is the stuff I've been working recently for scaling our game and discussing this seemed interesting to me. :)

Again: nice article and comments/feedback from you!

this_is_ridiculous (talk) 10:01, 16 July 2013 (EEST)

Dan Colasanti - The warping issue

Don't worry - I didn't take any offense.

What I meant regarding warping by using { 1.5, 1.6 } 2-dimensional scaling for 720P is that if we remove the Margin adjustment for letterboxing and change this line of code (from my article)

     scaleTransform.ScaleX = scaleTransform.ScaleY = scale;


     scaleTransform.ScaleX = 1.6f;
     scaleTransform.ScaleY = 1.5f;

in order to completely fill the 720P screen, the graphics would be stretched wider than they should be, although with some graphics it might not be that noticeable.

The game that I ported to MonoGame/WP8 and used this scaling method for is rather simple and currently doesn't do any post-processing (my XNA WP7 port of the Invasion game on CodeProject.com) - so it really wouldn't benefit from render targets at this point. But I have another XNA/WP7 game that uses render-targets and is much more resource-intensive that I wanted to port to MonoGame. If & when I ever get around to that, I'll probably use the method that you are recommending. For Invasion though, scaling with the DrawingSurface was more than adequate and very easy to implement. It only took a few minutes to write the scaling code - much longer to write the article!

Thanks again!


Dan Colasanti (talk) 10:42, 16 July 2013 (EEST)

This is ridiculous - the graphics would be stretched wider than they should be

I've written about scaling compensation in my first comment :) Some graphics object are not that much sensitive to non-uniform scaling, however with the On-Screen Controller this was very noticeable. When time comes I will update my article here about On-Screen Controller and will mention all this stuff with scaling for different resolution.

this_is_ridiculous (talk) 10:54, 16 July 2013 (EEST)

Hamishwillee - If you get agreement

Hi Guys

All a bit abstract to me since I've not written an XNA game - but you seem to be having fun and talking constructively :-)

Dan, as a reader I find it useful to know what assumptions/design decision are made and why - saying that DrawingSurfaceBackgroundGrid is an alternative to DrawingSurface that might be worth trying if there are performance issues is useful information, as is stating that DrawingSurface worked fine in your app. Ditto explaining that using letterboxing and avoiding issues of scaling is a very simple approach is useful - people can see then the compromise that is made. Anyway, suggestion is that if possible you add brief Template:Notes at reasonable places explaining this.

This is your article, and your call. And of course I'm making the assumption that you guys reach agreement on this before anything is added.

Artem, you wrote "When time comes I will update my article here about On-Screen Controller and will mention all this stuff with scaling for different resolution." Sounds great. Might be better to have a stand alone article or integrated in this article and linked from your article. The reason is that people searching for scaling information are IMO more likely to click on a topic name like this one.



hamishwillee (talk) 03:21, 17 July 2013 (EEST)

Dan Colasanti - Thanks for the comments & suggestions

Hamish & Artem,

Thanks for the comments and suggestions. My schedule is quite full right now and I'm not yet familiar enough with DrawingSurfaceBackgroundGrid to update the article with it, but I will when I get a chance to check it out. I'll also try to explain letterboxing better and maybe add some screenshots/diagrams. Will try to get back to it in August.



Dan Colasanti (talk) 20:09, 17 July 2013 (EEST)

Hamishwillee - Thankyou

Thanks Dan. In the meantime readers have all the discussion in the comments to work with if needed.

hamishwillee (talk) 06:38, 18 July 2013 (EEST)

This is ridiculous - Might be better to have a stand alone article or integrated in this article and linked from your article.

Hello, Hamish!

My approach is a way more comlicated than Dan took. Developer will have to deal with rotation, centering, and scaling of visual part as well as touch points on his own. And tihs would be a bit complicated article to write.The scaling aproach would also work with DrawingSurface. However we write a pretty heavy in terms of graphics game, and if to belive benchmarks that MonoGame guys did and posted on codeplex WP8 dicussion thread DrawingSurfaceBackgroundGrid (unlike DrawingSurface) uses swapchain for DX drawing and gives performance close to native DirectX on phone when DrawingSurface performs pretty much like MS XNA. It (DrawingSurfaceBackgroundGrid) just cannot give us the landscape rendertarget and landscape touch orientation due to limitations in the SDK. I'm a bit busy with our game right now, but I'm gathering ideas and laying it all flat in my head to write the article and get it posted.

this_is_ridiculous (talk) 14:04, 18 July 2013 (EEST)