How do you scale the screen resolution for other resolutions with Pygame?

So, every Pygame example I've seen seems to have a resolution in which the game is meant to be played and what it is. There are no options for setting higher or lower resolutions. If you change the resolution using display.set_mode then the texture / graphics scale of the game will be out of order and the game will become unplayable.

In all the examples I've seen, it looks like you will need to create different sets of textures for each target resolution ... Which seems ridiculous. This brings me to my question.

If I'm building a game based on a standard resolution of 480x270, can I just scale the output of this surface to 1080p (or 1440p, 4k, etc.) while still using game assets built for 480x270? If so, can anyone post an example of how this can be done? Any advice or pointers would be appreciated as well.

+3


source to share


2 answers


The best way to do this is to downscale the images to maintain image quality. Here are two options:

Option 1

This method is probably the fastest.

  • Create images for compatibility at the highest resolution you intend to support.
  • Create a screen with the desired user size.

    screen = pygame.display.set_mode((user_x, user_y))
    
          

  • Thumbnails while loading

    image = pygame.image.load("a.png").convert_alpha()
    pygame.transform.scale(image, (screen.width() / your_max_width, screen.height() / your_max_height), DestSurface=image)
    
          

  • Now just spray them normally. It should run at normal speed.



Option 2

  • Create a screen with the desired user size.

    screen = pygame.display.set_mode((user_x, user_y))
    
          

  • Then create a pygame.Surface with the highest resolution you are going to support.

    surface = pygame.Surface((1920, 1080))
    
          

  • Then, everything to this surface.

    surface.blit(image, rect)
    # Etc...
    
          

  • After all the blits are complete, reduce the surface (if necessary) to whatever resolution the user desires. Preferably, you allow resolutions with the same aspect ratio.

    pygame.transform.scale(surface, ((screen.width() / your_max_width, screen.height() / your_max_height), DestSurface=surface)
    
          

  • Finally, blit the surface on the screen and display it.

    screen.blit(surface, (0, 0))
    pygame.display.update()
    
          

This process (downscaling) preserves the image quality while retaining the choice of screen resolution. It will be slower because you are constantly manipulating images.

+2


source


Spent some time messing around and putting together a demo showing how you could solve this problem. Find an image to test and put the line path to that image in your script for the imagePath value.

The functionality of this script is simple. As you press the left or right arrow keys, the screen resolution cycles through the tuple of acceptable resolutions and the screen resizes accordingly as the test image is scaled to the new resolution.



import pygame,sys
from pygame import *
from pygame.locals import *


displayIndex = 0
pygame.init()

##standard 16:9 display ratios
DISPLAYS = [(1024,576),(1152,648),(1280,720),(1600,900),(1920,1080),(2560,1440)] 
screen = pygame.display.set_mode(DISPLAYS[displayIndex])
screen.fill((0,0,0))
### change image path to a string that names an image you'd like to load for testing. I just used a smiley face from google image search.
### Put it in the same place as this file or set up your paths appropriately
imagePath = "Smiley-icon.png"


class Icon(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.smileyImage = pygame.image.load(imagePath)
        self.image = self.smileyImage.convert_alpha()
        ### need to assume a default scale, DISPLAYS[0] will be default for us
        self.rect = self.image.get_rect()
        self.posX = x
        self.posY = y
        self.rect.x = x
        self.rect.y = y
        self.defaultx = (float(self.rect[2])/DISPLAYS[0][0])*100
        self.defaulty = (float(self.rect[3])/DISPLAYS[0][1])*100
        ## this is the percent of the screen that the image should take up in the x and y planes



    def updateSize(self,):
        self.image = ImageRescaler(self.smileyImage,(self.defaultx,self.defaulty))
        self.rect = self.image.get_rect()
        self.rect.x = self.posX
        self.rect.y = self.posY


def ImageRescaler(image,originalScaleTuple): #be sure to restrict to only proper ratios
    newImage = pygame.transform.scale(image,(int(DISPLAYS[displayIndex][0]*(originalScaleTuple[0]/100)),
                                         int(DISPLAYS[displayIndex][1]*(originalScaleTuple[1]/100))))
    return newImage


def resizeDisplay():
    screen = pygame.display.set_mode(DISPLAYS[displayIndex])
    ## this is where you'd have'd probably want your sprite groups set to resize themselves
    ## Just gonna call it on icon here
    icon.updateSize()


icon = Icon(100,100)
while True:
    screen.fill((0,0,0))
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                displayIndex -=1
                if displayIndex < 0:
                    displayIndex = 5
                resizeDisplay()
            elif event.key == K_RIGHT:
                displayIndex+=1
                if displayIndex > 5:
                    displayIndex = 0
                resizeDisplay()




    screen.blit(icon.image,(icon.rect.x,icon.rect.y))  
    pygame.display.update()

      

+1


source







All Articles