0

So i am making a game in python and pygame and i have the indow setup like this

display = pygame.display.set_mode((0,0), pygame.FULLSCREEN)

which makes the size of the window about 1334 X 800 so i based all the sprites and backgrounds on that size of screen but as you know not everyone has the same sized screen as me so my question is how can i make images scale with how big the monitor screen is

(P.S The game is in fullscreen mode)

fafy622
  • 29
  • 4
  • It may actually be simpler to render to a giant surface and then scale the whole surface buffer, instead of scaling each sprite and background. It also looks better to do interpolation after compositing than before. (It may also be faster… but then it may also be slower, and more likely that won't matter.) – abarnert Apr 27 '15 at 20:23
  • Meanwhile, if someone's screen doesn't have the same aspect ratio as yours, do you want to stretch everything, letterbox the whole game, or what? For example, imagine someone has a crazy vertical screen that's 1334x1600. So you want all sprites to stay the same width but become twice as tall? Or stay the same size but the top and bottom of the screen are blank? Or something different? – abarnert Apr 27 '15 at 20:24

2 Answers2

1

First, how do you get the resolution and the scaling factor?

This is tricky, because someone's screen may not have the same aspect ratio as your 1334x800. You can letterbox (in various different ways) or stretch the sprites; you need to decide what you want, but I'll show one letterboxing possibility:

NOMINAL_WIDTH, NOMINAL_HEIGHT = 1334., 800.
surface = display.get_surface()
width, height = surface.get_width(), surface.get_height()
xscale = width / NOMINAL_WIDTH
yscale = height / NOMINAL_HEIGHT
if xscale < 1 and yscale < 1:
    scale = max(xscale, yscale)
elif xscale > 1 and yscale > 1:
    scale = min(xscale, yscale)
else:
    scale = 1.0

Now, how do you scale each sprite and background?

Well, first, are you sure you want to? It may be simpler to just transform the whole surface. Whether this is slower or faster is hard to predict without testing (and probably not relevant anyway), but it will definitely look better (because any interpolation, dithering, antialiasing, etc. happens after compositing, instead of before—unless you're going for that 8-bit look, of course, in which case it will destroy the look…). You can do this by compositing everything to an off-screen surface of 1334x800 (or, better, scaling everything up by a constant factor), then transforming that surface for display. (Note that the transform methods include an optional DestSurface argument. You can use this to directly transform from the offscreen surface to the display's surface.)


But let's assume you want to do it the way you asked.

You can do this when loading the sprites. For example:

def rescale(surf, scale):
    new_width, new_height = surf.get_width() * scale, surf.get_height() * scale
    return pygame.transform.smoothscale(surf, (new_width, new_height))

class ScaledSprite(pygame.sprite.Sprite):
    def __init__(self, path, scale):
        pygame.sprite.Sprite.__init__(self)
        self.image = rescale(pygame.image.load(path), scale)
        self.rect = self.image.get_rect()

And the same for the backgrounds.

abarnert
  • 354,177
  • 51
  • 601
  • 671
-1

from this SO question, you can get the size of the monitor with

infoObject = pygame.display.Info()

which gets the height and width of the screen as infoObject.current_w and infoObject.current_h

You can then use these values to scale everything appropriately.

Community
  • 1
  • 1
Matthew
  • 672
  • 4
  • 11
  • He doesn't need this; he's set the display to fullscreen, so its surface's size is usually the monitor's size—and in the rare cases where it isn't, it's the surface size he wants. – abarnert Apr 27 '15 at 20:40
  • You can get the display size using that from a full screen display according to the other SO question – Matthew Apr 27 '15 at 22:22
  • Yes, you can--but again, you don't need to if you've already created a surface of that size, as the OP has. – abarnert Apr 28 '15 at 10:55
  • You can create the surface with `display = pygame.display.set_mode((0,0), pygame.FULLSCREEN)`, which you don't pass a size of the screen, you default to full screen. In order to scale things such that small screens manage to capture everything and large screens don't have empty spaces, you need to get the size of the screen. So yes, you do need to get the size of the fullscreen... – Matthew Apr 29 '15 at 08:23
  • Of course you can; the OP _is_ creating the surface that way. But you can just get the height and width of that surface. Which means your code continues to work with no changes if you add windowed mode, you get the right answer in the rare edge cases where a fullscreen surface is smaller than the display, etc. – abarnert Apr 29 '15 at 08:27