5.2    画面比例缩放

现在游戏窗口的放大按钮是灰色的,是不能点击的。如果想允许玩家调整窗口尺寸的话,在创建窗口时使用pygame.RESIZABLE参数即可,代码如下所示:

self.window = pygame.display.set_mode((SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2), pygame.RESIZABLE)

修改程序并调整窗口大小,对比画面如5‑2所示。

52任意缩放的窗口

         在进行任意缩放时,经常会出现画面严重变形的问题,这会影响游戏体验。现在大多数显示器都是宽屏显示器,全屏窗口后画面会显得非常扁长。

为了解决这个问题,我们希望实现画面按比例缩放,避免形变,放大后画面的两侧可以保持空白。现在放大画面的方法如下:

            newSurface = pygame.transform.scale(self.screen, self.window.get_rect().size)

         scale()方法的第二个参数是放大后的宽高,这里使用的是窗口的尺寸,所以画面会填满整个窗口。为了按比例缩放,我们可以根据原始画面的尺寸(256x224像素)来计算新的画面尺寸。如果新窗口的宽度较大,那么左右两侧留白,按高度来计算新尺寸。如果新窗口的高度较大,那么上下两侧留白,按宽度来计算新尺寸。

         那么,我们应该在何时计算新尺寸呢?当玩家调整窗口大小时,Pygame会生成pygame.VIDEORESIZE事件,通过监听这个事件,我们可以获取窗口的新尺寸,修改后的代码如下所示:

 

05\02\Game.py

import pygame

from constants import *

from utils import *

from Globals import *

from Mario import Mario

from TilesImageCache import TilesImageCache

 

 

class Game:

    def __init__(self):

        # 初始化 Pygame

        pygame.init()

 

        # 先画到一个画布上

        self.screen = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))

 

        # 真正的屏幕

        self.window = pygame.display.set_mode((SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2), pygame.RESIZABLE)

        self.windowSize = self.window.get_rect().size

 

……省略……

 

    def run(self):

 

        # 主循环

        isRunning = True

        while isRunning:

            for event in pygame.event.get():

                if event.type == pygame.QUIT:

                    isRunning = False

 

                # 监测窗口大小变化事件

                if event.type == pygame.VIDEORESIZE:

                    # 计算比例(event.wevent.h是调整后的宽度和高度)

                    ratio = min(event.w / SCREEN_WIDTH, event.h / SCREEN_HEIGHT)

                    newWidth = int(SCREEN_WIDTH * ratio)

                    newHeight = int(SCREEN_HEIGHT * ratio)

                    self.windowSize = (newWidth, newHeight)

            # 全屏擦除(注意背景色改成了天蓝色)

            self.screen.fill(COLOR_SKY_BLUE)

 

            # 绘制地图

            self.drawMap()

 

            # 获取按键状态

            keys = pygame.key.get_pressed()

 

            # 更新马里奥

            self.mario.update(keys)

 

            # 放大画面,显示在屏幕中间

            newSurface = pygame.transform.scale(self.screen, self.windowSize)

            showPosX = (self.window.get_rect().size[0]-self.windowSize[0])/2

            showPosY = (self.window.get_rect().size[1] - self.windowSize[1]) / 2

            self.window.blit(newSurface, (showPosX, showPosY))

 

            # 刷新显示

            pygame.display.flip()

 

            # 每秒60

            self.clock.tick(60)

        # 退出 Pygame

        pygame.quit()

 

 

if __name__ == '__main__':

    game = Game()

    Globals.game = game  # 保存起来,便于使用

    game.run()

运行程序并调整窗口,画面如5‑3所示,可以看到画面始终保持比例,并显示在窗口中间,效果非常好。

53窗口比例缩放