[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Fixed aspect ratio scaling



On May 31, 2007, at 1:03 AM, John Eriksson wrote:

Hi,

Does anyone know about a good solution on the stretching problem when
running in fullscreen mode on a widescreen monitor?

For windows users having an nvidia driver it's possible to set "Fixed
aspect ratio scaling" as an option for the display causing the
widescreen to have black borders at the sides.

But are there any platform independent solutions to this?

I guess it might be possible to solve this using code, creating a
correct sized display and then blitt the game screen to it's centered.

But this (I guess) can cause some performance loss. And I don't know if
it's even possible to detect the best screen resolution to use.
As far as I know there are no way to determine the current screen
resolution (to calculate the monitors aspect ratio) of the system?

Is the problem that your game expects a fixed-resolution and therefore a fixed aspect ratio? Regardless if your game demands a fixed aspect ratio then on some monitors you must either letter-box the screen or stretch everything to fit. You seem to be hinting at doing the latter, but that causes undesireable distortion (i.e., circles become ovals, etc).

Here is my suggested solution to this problem:

- Make your game resolution independent. That is, distances in the game are independent of pixel size.

- Make either the horizontal or vertical screen distance fixed, perhaps matching it to the "ideal" screen size (e.g., 1280 or 1600)

- At game startup let pygame pick the resolution by default or allow it to be overridden by user preference. Figure out the scale by dividing the fixed screen distance by the actual screen resolution. Then scale all of your graphics accordingly. If you are using sprite images, rotozoom works excellent (just zoom everything at load-time) and is very fast.

You get several benefits from this:

- You can pretty easily implement a zoom in/out feature by varying the fixed screen distance.

- Users can select lower resolutions to trade quality for performance or vice versa. Some resolutions may be letterboxed, but the user can decide if this is objectionable, many times it isn't.

To get at the screen resolution use the surface object returned from pygame.display.set_mode(), call get_rect() on it to figure out the screen res.

Here is some code I wrote to select the screen res from four user resolution settings: max, high, med and low. It is intended to pick sizes that fit the aspect ratio of the screen in fullscreen mode, where possible. It also favors portrait orientation (for those of us with pivoting monitors).

screen_sizes = {
	'max': ((0, 100000), (1280, 1024)),
	'high': ((650, 800), (1024, 768)),
	'med': ((500, 649), (800, 600)),
	'low': ((400, 499), (640, 480))
}
(min_height, max_height), window_size = screen_sizes[resolution]
if fullscreen:
	modes = pygame.display.list_modes()
	# Choose the first mode with a height in the desired range
	for mode in modes:
		if min_height <= mode[1] <= max_height and mode[0] > mode[1]:
			break
	else:
		mode = modes[0]
		print "Could not find ideal display mode, using", mode
	screen = pygame.display.set_mode(mode, FULLSCREEN)
else:
	screen = pygame.display.set_mode(window_size)
screen_rect = screen.get_rect()

hth,

-Casey