Python >> Tutoriel Python >  >> Python GUI >> Pygame GUI

Comment adapter une résolution de conception à d'autres résolutions avec Pygame ?

J'ai passé du temps à bricoler et à créer une démo montrant comment vous pourriez vous attaquer à ce problème. Trouvez-vous une image à tester et placez le chemin de chaîne vers cette image dans le script pour la valeur de imagePath.

La fonctionnalité de ce script est simple. Lorsque vous appuyez sur les touches fléchées vers la gauche ou vers la droite, la résolution de l'écran passe par un tuple de résolutions acceptables et l'écran se redimensionne en conséquence tout en adaptant votre image de test à la nouvelle résolution.

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()

La meilleure façon d'y parvenir est de réduire l'échelle des images, afin de préserver la qualité de l'image. Voici deux options :

Option 1

Cette méthode est probablement la plus rapide.

  1. Créez des images compatibles avec la plus grande résolution que vous avez l'intention de prendre en charge.
  2. Créez un écran avec la taille souhaitée par l'utilisateur.

    screen = pygame.display.set_mode((user_x, user_y))
    
  3. Réduire l'échelle des images au moment du chargement

    image = pygame.image.load("a.png").convert_alpha()
    pygame.transform.scale(image, (screen.width() / your_max_width, screen.height() / your_max_height), DestSurface=image)
    
  4. Maintenant, il suffit de les blit normalement. Il devrait fonctionner à des vitesses normales.

Option 2

  1. Créez un écran avec la taille souhaitée par l'utilisateur.

    screen = pygame.display.set_mode((user_x, user_y))
    
  2. Ensuite, créez un pygame.Surface avec la plus haute résolution vous entendent soutenir.

    surface = pygame.Surface((1920, 1080))
    
  3. Ensuite, effacez tout sur cette surface.

    surface.blit(image, rect)
    # Etc...
    
  4. Une fois tous les blits terminés, réduisez la surface (si nécessaire) à la résolution souhaitée par l'utilisateur. De préférence, vous n'autoriseriez que des résolutions avec le même rapport hauteur/largeur.

    pygame.transform.scale(surface, ((screen.width() / your_max_width, screen.height() / your_max_height), DestSurface=surface)
    
  5. Enfin, mettez la surface sur l'écran et affichez-la.

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

Ce processus (downscaling) permet de préserver la qualité de l'image tout en permettant à l'utilisateur de choisir sa résolution d'écran. Ce sera plus lent car vous manipulez constamment des images.