pygame,停止背景滚动

时间:2013-01-27 22:53:53

标签: background python-2.7 scroll pygame

我想阻止屏幕背景图像与播放器一起移动,但我无法弄清楚如何做到这一点。下面是一个例子,当玩家移动时,背景图像随之移动。我只是希望相机随着播放器移动而背景静止不动。有人可以帮忙吗?

示例:

enter image description here

CODE:

import pygame
from pygame import *

WIN_WIDTH = 800
WIN_HEIGHT = 640
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 0
FLAGS = 0
CAMERA_SLACK = 30

def main():
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
    pygame.display.set_caption("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
    timer = pygame.time.Clock()

    up = left = right = False
    entities = pygame.sprite.Group()
    player = Player(32, 32)
    platforms = []

    x = 0
    y = 0
    level = [
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P              PPPPP        PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                     PPPPPPPPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P      PPPP                 PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "PPPPP                       PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P           PPPPP           PPPP     PPPPPPP",
        "P                                       PPPP",
        "P                                       PPPP",
        "P                                       PPPP",
        "P                         PPPPPPPPPPPPPPPPPP",
        "P                         PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]

    total_level_width = len(level[0]) * 32
    total_level_height = len(level) * 32
    #print(total_level_width, total_level_height)
    background = pygame.image.load("Untitled.png")

    # build the level
    for row in level:
        for col in row:
            if col == "P":
                p = Platform(x, y)
                platforms.append(p)
                entities.add(p)
            if col == "E":
                e = ExitBlock(x, y)
                platforms.append(e)
                entities.add(e)
            x += 32
        y += 32
        x = 0

    camera = Camera(complex_camera, total_level_width, total_level_height)
    entities.add(player)

    while 1:
        timer.tick(60)

        for e in pygame.event.get():
            if e.type == QUIT: raise SystemExit, "QUIT"
            if e.type == KEYDOWN and e.key == K_ESCAPE:
                raise SystemExit, "ESCAPE"

            if e.type == KEYDOWN and e.key == K_UP:
                up = True
            if e.type == KEYDOWN and e.key == K_LEFT:
                left = True
            if e.type == KEYDOWN and e.key == K_RIGHT:
                right = True

            if e.type == KEYUP and e.key == K_UP:
                up = False
            if e.type == KEYUP and e.key == K_LEFT:
                left = False
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False


        # draw background
        screen.blit(background, (0,0))

        #draw entities
        for e in entities:
            screen.blit(e.image, camera.apply(e))

        # update player, update camera, and refresh
        player.update(up, left, right, platforms)
        camera.update(player)
        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 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 left
    l = max(-(camera.width - WIN_WIDTH), l)   # stop scrolling right
    t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling bottom

    return Rect(l, t, w, h)

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class Player(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.xvel = 0
        self.yvel = 0
        self.onGround = False
        self.image = Surface((32,32))
        self.image.fill(Color("#0000FF"))
        self.image.convert()
        self.rect = Rect(200, 1200, 32, 32)

    def update(self, up, left, right, platforms):
        print(self.yvel)
        if up:
            if self.onGround:
                self.yvel = 0
                self.yvel -= 10 # only jump if on the ground
        if left:
            self.xvel = -8
        if right:
            self.xvel = 8
        if not self.onGround:
            self.yvel += 0.3 # only accelerate with gravity if in the air
            if self.yvel > 80: self.yvel = 80 # max falling speed
        if not(left or right):
            self.xvel = 0

        self.rect.left += self.xvel # increment in x direction
        self.collide(self.xvel, 0, platforms) # do x-axis collisions
        self.rect.top += self.yvel # increment in y direction
        self.onGround = False; # assuming we're in the air
        self.collide(0, self.yvel, platforms) # do y-axis collisions

    def collide(self, xvel, yvel, platforms):
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, ExitBlock):
                    pygame.event.post(pygame.event.Event(QUIT))
                if xvel > 0: self.rect.right = p.rect.left
                if xvel < 0: self.rect.left = p.rect.right
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                if yvel < 0:
                    self.rect.top = p.rect.bottom

class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = Surface((32, 32))
        self.image.convert()
        self.image.fill(Color("#FFFFFF"))
        self.rect = Rect(x, y, 32, 32)

    def update(self):
        pass

class ExitBlock(Platform):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image = pygame.image.load("bush.png")

if __name__ == "__main__":
    main()

2 个答案:

答案 0 :(得分:3)

  

我只是希望相机随着播放器移动而背景静止不动。

反过来说:背景已经静止不动了。你希望它随相机一起移动。

所以而不是

screen.blit(background, (0,0))

使用

screen.blit(background, camera.apply((0,0)))

并将您的相机类更改为此

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):
        try:
            return target.rect.move(self.state.topleft)
        except AttributeError:
            return map(sum, zip(target, self.state.topleft))

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

允许将其应用于仲裁坐标,而不仅仅是Sprite s。

答案 1 :(得分:0)

问题是背景不滚动。由于相机已经存在,您只需要存储当前偏移量,然后用blit存储,而不是(0,0)

请注意使用rect's properties (docs)。替换这些:

l, t, _, _ = target_rect
_, _, w, h = camera

l, t = target_rect.topleft
w, h = camera.size

像HALFWIDTH这样的东西可以使用这些属性来简化数学运算。 topleft, bottomleft, topright, bottomright midtop, midleft, midbottom, midright center, centerx, centery 等。