5.3    全屏显示

为了实现全屏显示,可以使用pygame.FULLSCREEN参数。由于全屏模式下的分辨率是未知的,我们需要在创建屏幕Surface后立即获取屏幕分辨率,并按比例计算显示尺寸。

我们设计成这样:初始窗口以两倍放大显示,当按下F12键时进入全屏模式,按下ESC键时退出全屏模式。修改后的完整代码如下所示:

05\03\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

 

        # 设置窗口标题

        pygame.display.set_caption('super mario bros')

 

        # 避免输入法影响按键

        pygame.key.stop_text_input()

 

        # 创建时钟对象

        self.clock = pygame.time.Clock()

 

        # 初始化图片缓存

        Globals.tilesImageCache = TilesImageCache()

 

        # 马里奥

        self.mario = Mario(10, 100, self.screen)

 

        # 地图数据

        self.mapArray = []

        self.mapViewFrom = 0

        self.mapViewTo = SCREEN_WIDTH

        self.mapViewFromMax = 0

 

        # 存储参与碰撞的物体信息

        self.objectArray = []

 

        # 初始化地图

        self.initMap()

 

    # 按比例计算画面尺寸

    def resizeWindow(self, newSize):

        ratio = min(newSize[0] / SCREEN_WIDTH, newSize[1] / SCREEN_HEIGHT)

        newWidth = int(SCREEN_WIDTH * ratio)

        newHeight = int(SCREEN_HEIGHT * ratio)

        self.windowSize = (newWidth, newHeight)

 

    # 初始化地图

    def initMap(self):

 

        # 地图数据

        self.mapArray = loadMapData("1-1.txt")

 

        # 滚动地图From的最大值

        self.mapViewFromMax = len(self.mapArray[0]) * MAP_BLOCK_SIZE - SCREEN_WIDTH

 

        # 存储参与碰撞的物体信息(地图坐标)

        for rowIndex in range(len(self.mapArray)):

            row = self.mapArray[rowIndex]

            for cellIndex in range(len(row)):

                cell = row[cellIndex]

                if cell == 1 or cell in Globals.tilesImageCache.bgImageList:

                    continue  # 背景图片,不碰撞

                else:

                    # 其他参与碰撞

                    posX = cellIndex * MAP_BLOCK_SIZE

                    posY = rowIndex * MAP_BLOCK_SIZE

                    self.objectArray.append(pygame.Rect(posX, posY, MAP_BLOCK_SIZE, MAP_BLOCK_SIZE))

 

    # 滚动地图

    def scrollMap(self, step):

        self.mapViewFrom += step

        if self.mapViewFrom < 0:

            self.mapViewFrom = 0

        if self.mapViewFrom > self.mapViewFromMax:

            self.mapViewFrom = self.mapViewFromMax

        self.mapViewTo = self.mapViewFrom + SCREEN_WIDTH

 

    def drawMap(self):

        # 画地图

        for rowIndex in range(len(self.mapArray)):

            row = self.mapArray[rowIndex]

            for cellIndex in range(len(row)):

                # 转换为屏幕坐标,在显示范围内才绘制,注意参数的顺序

                screenPos = mapArrayToScreen(cellIndex, rowIndex)

                if screenPos[0] + MAP_BLOCK_SIZE > 0 and screenPos[0] < SCREEN_WIDTH:

                    cell = row[cellIndex]

                    # 编号在图片缓存中,则显示图片

                    if cell in Globals.tilesImageCache.imageMap:

                        self.screen.blit(Globals.tilesImageCache.imageMap[cell], screenPos)

 

    def run(self):

 

        # 主循环

        isRunning = True

        while isRunning:

            for event in pygame.event.get():

                if event.type == pygame.QUIT:

                    isRunning = False

 

                # ESC退出全屏,变成窗口模式

                # F12进入全屏模式

                if event.type == pygame.KEYDOWN:

                    if event.key == pygame.K_ESCAPE:

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

                        self.resizeWindow(self.window.get_rect().size)

                    elif event.key == pygame.K_F12:

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

                        self.resizeWindow(self.window.get_rect().size)

 

                # 监测窗口大小变化事件

                if event.type == pygame.VIDEORESIZE:

                    self.resizeWindow((event.w, event.h))

 

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

            self.screen.fill(COLOR_SKY_BLUE)

 

            # 绘制地图

            self.drawMap()

 

            # 获取按键状态

            keys = pygame.key.get_pressed()

 

            # 更新马里奥

            self.mario.update(keys)

 

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

            print("size:" + str(self.windowSize))

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

运行程序,并尝试按下F12ESC键进行显示模式切换吧。