Displaying a 4:3 screen on a 16:9 monitor without stretching. [SOLVED]

Previous topic - Next topic

Millerszone

Since I am new to GLBasic I am going to make a pong game to get familiar with GLBasic.
The only other "Programming" experience I had was with "Game Maker".

Question: My pong background picture is 800x600. My computer HD monitor is set to 1360x768.
The problem I'm having is when in full-screen the background picture stretches, not 1:1 ratio.
I would like to keep the ratio 1:1 (800x600) when in "Full Screen" at any screen resolutions.
Windows mode keeps the 1:1 ratio.

I searched the forum but I could not find any fixes.

I would appreciate any help.
Registered GLBasic User,
Novak
Hardware: iMac 27", MacBook Air, PC 3.5Ghz Quad
Developing Tools: GLBasic SDK, Gideros Studio, PureBasic
Developing for: iOS, Android, Windows, OS X, webOS, HTML5

Wampus

Hmm, the background picture stretches.

I think you mean that your 1360x768 native resolution monitor (approx 16:9 aspect ratio) makes a full-screen 800x600 (4:3 aspect ratio) picture look stretched. If so, there is not much you can do about it. Using a 16:9 ratio monitor to display a fullscreen 4:3 ratio resolution always stretches things. Commands like GETSCREENSIZE, SETSCREEN and ISFULLSCREEN() won't help much either.

You could include options to manually set the game to display correctly on monitors with different aspect ratios. A lot of games include such options nowadays. (Unfortunately there is no command to determine possible fullscreen resolutions. That could come in handy).

If the above doesn't address the problem, could you explain it further or supply some sample code?

monono

I know 2 workarounds.
First you could draw everything on on a virtual screen (800x600), grab it as an image, change back to you real resolution screen and draw that image stretched in the middle of the screen. Look up CREATESCREEN in the help, or I write some code later (no time at the moment).
Secondly, you could construct you game from the center. Instead of using a position like 100,100 you use centerx-300,centery-200. If it works correct on your game resolution 800x600 you scale every gameobject and position with a factor generated from the native and the game resolutions heights. In your case 768/600. Use the height if you want to keep the wanted aspect ration. The position for example would be centerx-(300*1.28) and centery-(200*1.28), while centerx/y is surely the actual center.



Millerszone

Thanks for all the advice.

I'll do something with virtual screen as "monono" suggested.

I'll post back when I figure it out.

Novak 
Hardware: iMac 27", MacBook Air, PC 3.5Ghz Quad
Developing Tools: GLBasic SDK, Gideros Studio, PureBasic
Developing for: iOS, Android, Windows, OS X, webOS, HTML5

Millerszone

Hardware: iMac 27", MacBook Air, PC 3.5Ghz Quad
Developing Tools: GLBasic SDK, Gideros Studio, PureBasic
Developing for: iOS, Android, Windows, OS X, webOS, HTML5

ampos

You can easily show a 4:3 game on 16:9 monitor.

Open desireed 16:9 screen and add a XOFFSET to every x coordinate in your program (xoffset=(screen width - game width)/2 ). Same with YOFFSET.

The problem is that currently GLB dont know if the user screen is 16:9.
check my web and/or my blog :D
http://diniplay.blogspot.com (devblog)
http://www.ampostata.org
http://ampostata.blogspot.com
I own PC-Win, MacBook 13", iPhone 3G/3GS/4G and iPAC-WinCE

Moru

Quote from: Ocean on 2010-Sep-10
Quote from: ampos on 2010-Sep-10
The problem is that currently GLB dont know if the user screen is 16:9.

Again:  you are not limited to the preconfigured screen resolutions that are offered by the project settings dialog.  SETSCREEN to the rescue!

cheers
Ocean

Yes you can set the resolution to fit but how does he know what is fitting? There was some code to check the native resolution of the computer, and then you can use setscreen to get the right resolution.

Millerszone

Thanks again for all the help.
With the code below, my game can now be played on all monitors (4:3, 16:9, 16:10) "Full Screen" and the game will keep it's aspect ratio.

I still don't know where to put the "main loop" code (collisions, ball and paddle movement).
The problem I'm having now is that the "Background.png" shows twice. Once on the top left of the screen and the correct position, center of the screen" see pic below.

Code (glbasic) Select

// --------------------------------- //
// Project: Test
// Start: Thursday, September 09, 2010
// IDE Version: 8.085

GetDesktopResolution(sx, sy)  // My screen res is 1360x768

SETSCREEN sx,sy,1
LIMITFPS 60

GOSUB Init

//center the virtual screen
centerx = (sx-800)/2
centery = (sy-600)/2

CREATESCREEN 1, 15, 800,600  //this creates the virtual screen

main:     // main loop
USESCREEN 1
LOADBMP "Background.png"   //this is my pong play-field 800x600

GOSUB MoveAll
GOSUB ShowAll

USESCREEN -1
DRAWSPRITE 15,centerx,centery  //this displays and centers the virtual screen
SHOWSCREEN
GOTO main


FUNCTION end_main:
ENDFUNCTION

INLINE   // thanks to "Ocean" for posting this code
}
#ifdef WIN32
   #define SM_CXSCREEN 0
   #define SM_CYSCREEN 1
   extern "C" __stdcall int GetSystemMetrics(int);
#endif
namespace __GLBASIC__{
ENDINLINE


FUNCTION GetDesktopResolution: BYREF sx, BYREF sy
INLINE
   #ifdef WIN32
      sx = ::GetSystemMetrics(SM_CXSCREEN);
      sy = ::GetSystemMetrics(SM_CYSCREEN);
   #endif
ENDINLINE
ENDFUNCTION




Hardware: iMac 27", MacBook Air, PC 3.5Ghz Quad
Developing Tools: GLBasic SDK, Gideros Studio, PureBasic
Developing for: iOS, Android, Windows, OS X, webOS, HTML5

monono

It seems to be a problem with LOADBMP. As I understood, it makes GLB use the pic it as the background for the next SHOWSCREEN. On the way from the secondscreen to the sprite (handle 15) happens something similar, so it is used for the background of that as well. That´s 2 times the picture, one for the "render screen to sprite" and on for the showscreen. Use LOADSPRITE for the background. That should fix it.

ampos

I have find (maybe) an easy solution: viewport.

If you create a viewport, any sprite placed will be offset from this viewport, not the screen. So:

Code (glbasic) Select
setscreen 800,600,0  //creates a 800x600 screen
viewport 100,100,600,400 //creates a viewport (virtual window) 600x400 in middle of screen
drawsprite any_sp,0,0 // places a sprite at 0,0 of VIEWPORT, not screen. So it will be same as 100,100 on screen.


Dont know if USEBMP is relative to viewport or screen, but it deserve a try.
check my web and/or my blog :D
http://diniplay.blogspot.com (devblog)
http://www.ampostata.org
http://ampostata.blogspot.com
I own PC-Win, MacBook 13", iPhone 3G/3GS/4G and iPAC-WinCE

Slydog

Since it's such a simple background, why don't you reconstruct it on the fly using 'DRAWRECT'?
One DRAWRECT for the top bar, one for the bottom, and a bunch for the dashed lines in the middle.

Then you can scale you game to fit your screen exactly with no stretching (and therefore no distortion).
You could even have the 16:9 screen wider, but that would affect the look and maybe feel of the game.
If not, figure out your aspect ratio, versus your desired aspect ratio and calculate an x-margin.
Just a thought.

But, some good ideas being passed around for your original problem!
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Millerszone

Thanks guys! Instead of using CREATESCREEN, I used VIEWPORT and DRAWSPRITE for the background pic. Thanks "ampos".
I tried the program on standard 4:3 and 16:9 monitors at different resolutions. It worked perfect!
I'm liking GLB more and more. Also this forum is a big help!

Code (glbasic) Select

// --------------------------------- //
// Project: Test
// Start: Thursday, September 09, 2010
// IDE Version: 8.085

GetDesktopResolution(sx, sy)  // My screen res is 1360x768

SETSCREEN sx,sy,1
LIMITFPS 60

//center virtual screen
centerx = (sx-800)/2
centery = (sy-600)/2

GOSUB Init
//these 3 lines will go in "Init", put here for ex.
VIEWPORT centerx,centery,800,600
DRAWSPRITE 4,0,0
USEASBMP

main:
VIEWPORT centerx,centery,800,600
GOSUB MoveAll
GOSUB ShowAll
GOTO main

...
...
...

FUNCTION end_main:
ENDFUNCTION

INLINE
}
#ifdef WIN32
   #define SM_CXSCREEN 0
   #define SM_CYSCREEN 1
   extern "C" __stdcall int GetSystemMetrics(int);
#endif
namespace __GLBASIC__{
ENDINLINE


FUNCTION GetDesktopResolution: BYREF sx, BYREF sy
INLINE
   #ifdef WIN32
      sx = ::GetSystemMetrics(SM_CXSCREEN);
      sy = ::GetSystemMetrics(SM_CYSCREEN);
   #endif
ENDINLINE
ENDFUNCTION




Hardware: iMac 27", MacBook Air, PC 3.5Ghz Quad
Developing Tools: GLBasic SDK, Gideros Studio, PureBasic
Developing for: iOS, Android, Windows, OS X, webOS, HTML5

ampos

Have you tried USEBMP after the viewport? If it works, it will be faster than spritedraw each call just to clean/paint the background.
check my web and/or my blog :D
http://diniplay.blogspot.com (devblog)
http://www.ampostata.org
http://ampostata.blogspot.com
I own PC-Win, MacBook 13", iPhone 3G/3GS/4G and iPAC-WinCE

Millerszone

O.K. I added. I probably won't need it for this game(Pong), but for future games "USEASBMP" will come in handy.
Updated code.

Thank you!
Hardware: iMac 27", MacBook Air, PC 3.5Ghz Quad
Developing Tools: GLBasic SDK, Gideros Studio, PureBasic
Developing for: iOS, Android, Windows, OS X, webOS, HTML5