Skip to main content
 首页 » 编程设计

python之在pygame中像这样分层的好方法是什么

2025年05月04日16zhenyulu

我一直在用 pygame 做一个小项目。这是一款高架 2D 游戏,但如果玩家在物体后面,我需要玩家在物体后面一层。如果玩家在物体前面,则它需要在物体前面一层。

    for image, imagerect, imageypos in zip(blitimages, blitrects, blitypositions): 
 
    if realy < imageypos: 
        screen.blit(playerimage, playerimagerect) 
        screen.blit(image, imagerect) 
    if realy > imageypos: 
        screen.blit(image, imagerect) 
        screen.blit(playerimage, playerimagerect) 
 
    if realy == imageypos: 
        screen.blit(playerimage, playerimagerect) 
        screen.blit(image, imagerect) 

这是我尝试过的方法,但它不起作用。它始终显示播放器在前面。

供引用:

blitrects = [house1imagerect, house2imagerect, rock1imagerect] 
blitimages = [house1image, house2image, rock1image] 
blitypositions = [house1y, house2y, rock1y] 

我最需要的是一种正确执行此操作的方法(这也很快),以及为什么这种方法不起作用。如果需要答案,我愿意发布更多代码部分,只需发表评论即可!提前致谢!

编辑:

完整代码:

import sys, pygame, math, random 
pygame.init() 
 
size = width, height = 1000,720 
x = 0 
y = 0 
 
 
 
 
house1x = 500 
house1y = 360 
 
house2x = 1470 
house2y = 360 
 
 
rock1x = -100 
rock1y = 300 
 
 
scrollx = 0 
scrolly = 0 
screen = pygame.display.set_mode(size, pygame.DOUBLEBUF) 
counter = 0 
 
 
playercollideRect =  pygame.rect.Rect((0, 0), (75, 25)) 
 
house1collideRect = pygame.rect.Rect((0, 0), (870, 605)) 
house2collideRect = pygame.rect.Rect((0, 0), (870, 605)) 
 
rock1collideRect = pygame.rect.Rect((0, 0), (140, 100)) 
 
 
 
collision = False 
 
 
lastkey = 'down' 
animationdirection = 'down' 
 
 
 
playerimage = pygame.image.load("img/player/player0.png").convert_alpha() 
playerimagerect = playerimage.get_rect() 
 
 
house1image = pygame.image.load("img/structures/house1.png").convert_alpha() 
house1imagerect = house1image.get_rect() 
 
house2image = pygame.image.load("img/structures/house2.png").convert_alpha() 
house2imagerect = house2image.get_rect() 
 
 
rock1image = pygame.image.load("img/objects/rock1.png").convert_alpha() 
rock1imagerect = rock1image.get_rect() 
 
 
 
clock = pygame.time.Clock() 
 
screencolor = 0, 155, 20 
gamefont = pygame.font.SysFont("arial", 30) 
 
playeranimationdown = ['img/player/player1.png','img/player/player0.png','img/player/player2.png','img/player/player0.png'] 
playeranimationup = ['img/player/playerback1.png','img/player/playerback0.png','img/player/playerback2.png','img/player/playerback0.png'] 
playeranimationleft = ['img/player/playerleft1.png','img/player/playerleft0.png','img/player/playerleft2.png','img/player/playerleft0.png'] 
playeranimationright = ['img/player/playerright1.png','img/player/playerright0.png','img/player/playerright2.png','img/player/playerright0.png'] 
 
 
pygame.mixer.music.load('audio/music/ambient.mp3') 
pygame.mixer.music.set_endevent(pygame.constants.USEREVENT) 
pygame.mixer.music.play() 
pygame.display.set_caption('Game') 
pygame.event.set_allowed([pygame.QUIT, pygame.KEYDOWN, pygame.KEYUP]) 
 
colliders = [house1collideRect, house2collideRect, rock1collideRect] 
blitrects = [house1imagerect, house2imagerect, rock1imagerect] 
blitimages = [house1image, house2image, rock1image] 
blitypositions = [house1y, house2y, rock1y] 
 
while 1: 
 
    clock.tick(500) 
 
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: sys.exit() 
 
    if y > 720-75-100: 
        y = 720-75-100 
        scrolly -= 1 
    if y < 0+75+100: 
        y = 0+75+100 
        scrolly += 1 
    if x > 1000-37-100: 
        x=1000-37-100 
        scrollx -=1 
    if x < 0+37+100: 
        x = 0+37+100 
        scrollx +=1 
 
 
    for collider in colliders: 
        if playercollideRect.colliderect(collider): 
            if lastkey == 'left': 
                x += 1 
            if lastkey == 'right': 
                x -= 1 
            if lastkey == 'up': 
                y += 1 
            if lastkey == 'down': 
                y -= 1 
            collision = True 
        else: 
            collision = False 
 
 
    keys = pygame.key.get_pressed() 
    if keys[pygame.K_UP] or keys[pygame.K_DOWN] or keys[pygame.K_LEFT] or keys[pygame.K_RIGHT]: 
        if keys[pygame.K_UP]: 
            y -= 1 
 
            if not collision == True: 
                playerimage = pygame.image.load(playeranimationup[int(math.floor(counter/50))]).convert_alpha() 
                counter = (counter + 1) % 200 
            lastkey = 'up' 
 
 
        elif keys[pygame.K_DOWN]: 
            y += 1 
            if not collision == True: 
                playerimage = pygame.image.load(playeranimationdown[int(math.floor(counter/50))]).convert_alpha() 
                counter = (counter + 1) % 200 
            lastkey = 'down' 
 
 
        elif keys[pygame.K_RIGHT]: 
            x += 1 
            if not collision == True: 
                playerimage = pygame.image.load(playeranimationright[int(math.floor(counter/50))]).convert_alpha() 
 
                counter = (counter + 1) % 200 
            lastkey = 'right' 
 
        elif keys[pygame.K_LEFT]: 
            x -= 1 
 
            if not collision == True: 
                playerimage = pygame.image.load(playeranimationleft[int(math.floor(counter/50))]).convert_alpha() 
 
                counter = (counter + 1) % 200 
            lastkey = 'left' 
 
 
 
 
    playerimagerect.centerx = x 
    playerimagerect.centery = y 
 
 
    house1imagerect.centerx = house1x+scrollx 
    house1imagerect.centery = house1y+scrolly 
 
    house2imagerect.centerx = house2x+scrollx 
    house2imagerect.centery = house2y+scrolly 
 
    rock1imagerect.centerx = rock1x+scrollx 
    rock1imagerect.centery = rock1y+scrolly 
 
 
 
    playercollideRect.midbottom = playerimagerect.midbottom 
 
    house1collideRect.midbottom = house1imagerect.midbottom 
    house2collideRect.midbottom = house2imagerect.midbottom 
 
    rock1collideRect.midbottom = rock1imagerect.midbottom 
 
 
    realx = x-scrollx 
    realy = y-scrolly 
 
 
 
    for image, imagerect, imageypos in zip(blitimages, blitrects, blitypositions): 
 
        if realy < imageypos: 
            screen.blit(playerimage, playerimagerect) 
            screen.blit(image, imagerect) 
        if realy > imageypos: 
            screen.blit(image, imagerect) 
            screen.blit(playerimage, playerimagerect) 
 
        if realy == imageypos: 
            screen.blit(playerimage, playerimagerect) 
            screen.blit(image, imagerect) 
 
 
 
 
 
    label = gamefont.render(str('FPS: '+str(clock.get_fps())), 1, (255,255,0)) 
    screen.blit(label, (50, 50)) 
 
    pygame.display.flip() 
    screen.fill(screencolor) 

请您参考如下方法:

停止直接使用 Surfaces。使用 pygame 的 Sprite 类。

然后你可以简单地给你的 Sprites 一个 _layer 属性并使用 LayeredUpdates管理它们的组,该组将负责 blitting 的顺序。

这是一个例子:

import pygame 
pygame.init() 
screen = pygame.display.set_mode((300, 300)) 
 
class Actor(pygame.sprite.Sprite): 
    def __init__(self, group, color, layer, pos): 
        self.image = pygame.Surface((30, 30)) 
        self.image.fill(color) 
        self.rect = self.image.get_rect(center=pos) 
        self._layer = layer 
        pygame.sprite.Sprite.__init__(self, group) 
 
group = pygame.sprite.LayeredUpdates() 
Actor(group, (255, 255, 255), 0, (100, 100)) 
Actor(group, (255, 0, 255),   1, (110, 110)) 
Actor(group, (0, 255, 255),   0, (120, 120)) 
Actor(group, (255, 255, 0),   3, (130, 130)) 
Actor(group, (0, 0, 255),     2, (140, 140)) 
 
run = True 
while run: 
    for e in pygame.event.get(): 
        if e.type ==pygame.QUIT: 
            run = False 
    screen.fill((0,0,0)) 
    group.update() 
    group.draw(screen) 
    pygame.display.flip() 

请注意 Sprite 的顺序如何由 _layer 属性的值决定。