如何在Pygame中制作滚动相机?

时间:2014-04-19 20:49:19

标签: python python-3.x pygame

我问的问题是因为我需要一个滚动相机。我已经在相机上尝试了一些方法,但它们都没有用。或者他们说有一个全局名称错误。这是我使用的具有全局名称错误的代码

import pygame

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)


screen_width = 700
screen_height = 400

half_width = int(screen_width / 2)
half_height = int(screen_height / 2)


def main():
    screen = pygame.display.set_mode([screen_width, screen_height])

    pygame.display.set_caption("RPG")
    global cameraX, cameraY



    pygame.init()

    player = pygame.image.load("Textures(Final)\Whoo_For_Testing.bmp").convert()
    playerect = player.get_rect()
    player.set_colorkey(WHITE)


    grasstile = pygame.image.load("Textures(Final)\Grass_Tile.bmp").convert()
    watertile = pygame.image.load("Textures(Final)\Water_Tile.bmp").convert()
    waterbeach = pygame.image.load("Textures(Final)\Water_Beach.bmp").convert()
    grassrect = grasstile.get_rect()
    waterrect = watertile.get_rect()
    waterb = waterbeach.get_rect()

    TILE_WIDTH = 32
    TILE_HEIGHT = 32

    tilemap = [
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile]
            ]

    total_level_width = len(tilemap[0]) * 32
    total_level_height = len(tilemap)*32

    camera = Camera(simple_camera ,total_level_width, total_level_height)


    map_surface = pygame.Surface(( len(tilemap[0])*TILE_WIDTH, len(tilemap)*TILE_HEIGHT))

    for y,row in enumerate(tilemap):
        for x,tile_surface in enumerate(row):
            map_surface.blit(tile_surface,(x*TILE_WIDTH,y*TILE_HEIGHT))

    map_surface = pygame.transform.scale(map_surface, (1200, 800))
    player = pygame.transform.scale(player, (50, 100))


    done = False

    clock = pygame.time.Clock()

    move_speed = 5
    x, y = 100, 100

    entities = pygame.sprite.Group()

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP]:
            y -= move_speed
        elif keys[pygame.K_DOWN]:
            y += move_speed
        elif keys[pygame.K_LEFT]:
            x -= move_speed
        elif keys[pygame.K_RIGHT]:
            x += move_speed

        screen.fill(BLACK)

        screen.blit(map_surface, grassrect)
        screen.blit(player, (x,y))


        camera.update(player)

        clock.tick(20)

        pygame.display.flip()

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

    def apply(self, target):
        return target.rect.move(self.state.topleft)

    def update(self, target):
        self.state = self.camera_func(self.state, target.rect)


def simple_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    return Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)

def complex_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    l, t, _, _ = -l+HALF_WIDTH, -t+HALF_HEIGHT, w, h

    l = min(0, l)                           # stop scrolling at the left edge
    l = max(-(camera.width-WIN_WIDTH), l)   # stop scrolling at the right edge
    t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling at the bottom
    t = min(0, t)                           # stop scrolling at the top
    return Rect(l, t, w, h)

if __name__ == "__main__":
    main()



pygame.quit()

基本上我要问的是如何解决这个问题。对不起,不太擅长解释东西。谢谢!

1 个答案:

答案 0 :(得分:0)

这里有几件事需要解决。首先是关于NameErrors,因为Rect是来自导入的pygame包,你必须专门导入Rect:from pygame import Rect或写pygame.Rect。 (还要注意全局变量中的大写字母!)。现在,至于实际的相机问题,你遇到的主要问题是你传递给你的相机功能的玩家的矩形是一个移动的矩形,它只是使用了直接的pygame存储表面的大小(因此topleft将始终为(0,0))。当你真正画出它们时,你也没有将相机应用到表面的部分。这是我开始工作的代码:

import pygame

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)


SCREEN_WIDTH = 700
SCREEN_HEIGHT = 400

HALF_WIDTH = int(SCREEN_WIDTH / 2)
HALF_HEIGHT = int(SCREEN_HEIGHT / 2)


def main():
    screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])

    pygame.display.set_caption("RPG")
    global cameraX, cameraY



    pygame.init()

    #player = pygame.image.load("Textures(Final)\Whoo_For_Testing.bmp").convert()
    player = pygame.Surface((40,40))
    player.fill((255,0,0))

    playerrect = player.get_rect()
    player.set_colorkey(WHITE)


    #grasstile = pygame.image.load("Textures(Final)\Grass_Tile.bmp").convert()
    #watertile = pygame.image.load("Textures(Final)\Water_Tile.bmp").convert()
    #waterbeach = pygame.image.load("Textures(Final)\Water_Beach.bmp").convert()
    grasstile = pygame.Surface((40,40))
    watertile = pygame.Surface((40,40))
    waterbeach = pygame.Surface((40,40))
    grasstile.fill((0,200,0))
    watertile.fill((0,0,200))
    waterbeach.fill((200,200,250))

    grassrect = grasstile.get_rect()
    waterrect = watertile.get_rect()
    waterb = waterbeach.get_rect()

    TILE_WIDTH = 32
    TILE_HEIGHT = 32

    tilemap = [
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile],
                [grasstile, grasstile, grasstile, grasstile, waterbeach, watertile, watertile, watertile, watertile]
            ]

    total_level_width = len(tilemap[0]) * 32
    total_level_height = len(tilemap)*32

    camera = Camera(simple_camera ,total_level_width, total_level_height)


    map_surface = pygame.Surface(( len(tilemap[0])*TILE_WIDTH, len(tilemap)*TILE_HEIGHT))

    for y,row in enumerate(tilemap):
        for x,tile_surface in enumerate(row):
            map_surface.blit(tile_surface,(x*TILE_WIDTH,y*TILE_HEIGHT))

    map_surface = pygame.transform.scale(map_surface, (1200, 800))
    player = pygame.transform.scale(player, (50, 100))


    done = False

    clock = pygame.time.Clock()

    move_speed = 5
    x, y = 100, 100

    entities = pygame.sprite.Group()

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP]:
            y -= move_speed
        elif keys[pygame.K_DOWN]:
            y += move_speed
        elif keys[pygame.K_LEFT]:
            x -= move_speed
        elif keys[pygame.K_RIGHT]:
            x += move_speed

        screen.fill(BLACK)

        screen.blit(map_surface, camera.apply(grassrect))
        screen.blit(player, camera.apply(pygame.Rect(x,y,50,100)))

        camera.update(player.get_rect().move((x,y)))

        clock.tick(20)

        pygame.display.flip()

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

    def apply(self, rect):
        return rect.move(self.state.topleft)

    def update(self, target_rect):
        self.state = self.camera_func(self.state, target_rect)

def simple_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera

    return pygame.Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)

def complex_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    l, t, _, _ = -l+HALF_WIDTH, -t+HALF_HEIGHT, w, h

    l = min(0, l)                           # stop scrolling at the left edge
    l = max(-(camera.width-SCREEN_WIDTH), l)   # stop scrolling at the right edge
    t = max(-(camera.height-SCREEN_HEIGHT), t) # stop scrolling at the bottom
    t = min(0, t)                           # stop scrolling at the top
    return pygame.Rect(l, t, w, h)

if __name__ == "__main__":
    main()



pygame.quit()

这适用于您的simple_camera方法,但不适用于complex_camera方法,我将留给您尝试修复。