详解Pygame 使用相机模块

  • Post category:Python

Pygame(Python游戏开发框架)提供了相机模块,可以为2D游戏创建一个虚拟摄像机,以便于控制游戏的视角。该模块可以实现镜头跟随游戏对象、地图滚动背景等效果。以下是Pygame相机模块的使用方法:

安装Pygame

在使用Pygame相机模块之前,需要先安装Pygame。可以通过以下命令安装:

pip install pygame

相机模块使用方法

首先从pygame库中导入相机模块,然后定义一个Camera对象:

import pygame

class Camera(object):
    def __init__(self, width, height):
        self.camera = pygame.Rect(0, 0, width, height)
        self.width = width
        self.height = height

初始化函数 __init__() 接收屏幕的宽和高作为参数,并构造一个pygame.Rect对象来表示相机的位置和大小。该对象包含四个参数,分别是相机矩形左上角点的x坐标、y坐标、宽度和高度。相机的初始位置和大小为 (0, 0, width, height)

apply 方法

定义 Camera 类的 apply() 方法,用来将游戏对象的位置转化成相对于相机的位置。这个方法需要接受图像和位置作为参数,并返回一个新的位置,表示相机应该如何在屏幕上渲染这个图像。

def apply(self, target_rect):
    return target_rect.move(self.camera.topleft)

这段代码中,target_rect 是一个pygame.Rect对象,代表对象在游戏窗口中的位置和大小。move() 方法用于返回一个新的对象,该对象的位置被移动到相机左上角。self.camera.topleft 表示相机的左上角坐标。

update 方法

定义 update() 方法,该方法接受一个目标Surface对象作为参数,并用 pygame.Surface.set_clip() 方法来更新相机的位置和大小。

def update(self, target):
    x = -target.rect.x + (self.width / 2)
    y = -target.rect.y + (self.height / 2)

    x = min(0, x)
    y = min(0, y)
    x = max(-(self.camera.width - self.width), x)
    y = max(-(self.camera.height - self.height), y)

    self.camera = pygame.Rect(x, y, self.camera.width, self.camera.height)
    return self.camera

在上面的代码中,我们首先计算出相机的位置,使目标对象位置在窗口的中心。然后,我们将相机的位置限制在地图范围内,并将新的相机矩形返回。

两条示例说明:

示例1:相机随目标物体移动

以下示例假设有个小球从左到右移动。需要相机跟随小球并保持其在屏幕范围内可见。实现代码如下:

import pygame

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((20, 20))
        self.image.fill(pygame.color.Color("blue"))
        self.rect = self.image.get_rect()
        self.rect.center = (0, 200)
        self.speed = 5

    def update(self, *args):
        self.rect.centerx += self.speed
        if self.rect.right > 800:
            self.speed = -5
        elif self.rect.left < 0:
            self.speed = 5

class Game(object):
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((800, 400))
        self.clock = pygame.time.Clock()

        self.ball = Ball()
        self.sprites = pygame.sprite.LayeredUpdates()
        self.sprites.add(self.ball)

        self.camera = Camera(self.screen.get_width(), self.screen.get_height())

    def run(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            self.sprites.update()
            self.screen.fill(pygame.color.Color("white"))

            for sprite in self.sprites:
                pygame.draw.rect(self.screen, pygame.color.Color("blue"), self.camera.apply(sprite))

            self.camera.update(self.ball)
            pygame.display.flip()

            self.clock.tick(60)

if __name__ == "__main__":
    game = Game()
    game.run()
    pygame.quit()

在代码中,Ball 类定义了小球的行为。Game 类初始化了游戏屏幕、时钟、小球对象和相机对象。游戏主循环中先更新小球运动状态,然后将小球和所有其他精灵对象渲染到屏幕上。每个球的坐标都是相对于相机的,因此,在将这些对象添加到屏幕上之前,需要将它们的位置转换成相机坐标。

示例2:相机滚动背景

以下示例演示如何使用相机模块实现一个平台游戏的背景滚动效果。

import pygame
import random

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((32, 32))
        self.image.fill(pygame.color.Color("red"))
        self.rect = self.image.get_rect(center=(400, 132))

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 2
        if keys[pygame.K_RIGHT]:
            self.rect.x += 2

class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.image = pygame.Surface((width, height))
        self.image.fill(pygame.color.Color("green"))
        self.rect = self.image.get_rect(topleft=(x, y))

class Game(object):
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((800, 400))
        self.clock = pygame.time.Clock()

        self.all_sprites = pygame.sprite.LayeredUpdates()
        self.platform_sprites = pygame.sprite.LayeredUpdates()

        self.player = Player()
        self.all_sprites.add(self.player)

        for i in range(0, 40, 2):
            p = Platform(i * 60, random.randint(200, 300), 60, 10)
            self.all_sprites.add(p)
            self.platform_sprites.add(p)

        self.camera = Camera(self.screen.get_width(), self.screen.get_height())

    def run(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            self.all_sprites.update()

            self.camera.update(self.player)

            self.screen.fill(pygame.color.Color("blue"))

            for platform in self.platform_sprites:
                pygame.draw.rect(self.screen, pygame.color.Color("green"), self.camera.apply(platform))

            pygame.draw.rect(self.screen, pygame.color.Color("red"), self.camera.apply(self.player))
            pygame.display.flip()

            self.clock.tick(60)

if __name__ == "__main__":
    game = Game()
    game.run()
    pygame.quit()

以上示例中,Player 类和 Platform 类是游戏对象,Game 类是游戏主循环。玩家控制 Player 对象左右移动,同时相机沿着 x 轴自动滚动,以使玩家对象始终位于屏幕中心。地面由许多 Platform 精灵对象构成。

在主循环中,首先更新所有精灵对象的位置。然后相机位置根据玩家的位置移动,以使玩家对象在屏幕中心。然后绘制所有平台和玩家。注意,绘制时要使用相机坐标,以便在屏幕上正确显示相对位置。

在这两个示例中,相机模块将每个精灵对象的位置从绝对位置转换为相对于相机位置的相对位置。这些相对位置的组合产生了可以随着玩家对象移动的背景效果。 此外,相机模块还实现了可滚动的背景。这两个示例说明了相机模块的作用和使用方法。