Pygame 根据位置重叠精灵(绘制顺序)

Ale*_*ter 3 python pygame collision-detection sprite draw

总的来说,我对 Pygame 和 Python 还比较陌生,所以希望这不是太陌生。

我正在制作一个自上而下的 RPG,并且我有两个 Sprite 对象,其图像看起来(例如)如下所示:
在此输入图像描述 在此输入图像描述

使用不代表整个图像的矩形:

class NPC(pygame.sprite.Sprite):
    def __init__(self, image, pos, *groups):
        super().__init__(*groups)
        self.image = pygame.load(image)
        self.rect = self.image.get_rect()
        self.collisionRect = pygame.Rect(self.rect.left, self.rect.top + 12, self.image.get_width(), self.image.get_width()) 
        #12 is the number of pixels that will overlap in the y-dimension
Run Code Online (Sandbox Code Playgroud)

我这样做是因为我希望 NPC 的顶部几个像素与其他精灵重叠。collisionRect每当我检测到碰撞时,都会使用每个对象中的,rect以便我可以创建这种效果。

但是,我需要一种方法在 update() 函数中重新绘制它们,以便一个根据彼此之间的相对位置绘制另一个。

因此,当一个 NPC 位于另一个 NPC 上方时,它看起来像这样:

在此输入图像描述

但是,当情况相反时,它应该看起来像这样:

在此输入图像描述

这意味着需要以不同的顺序绘制图像,具体取决于哪个精灵位于另一个精灵的“下方”。

我考虑过可能将精灵切割成单独的精灵,然后最后绘制“头部”精灵,但我想知道是否有一种更简单(或至少可靠)的方法来检测精灵是否应该最后绘制或否,取决于它是否与另一个精灵重叠并且在 y 维度中紧邻其下方。

如果这个问题太宽泛或需要更多背景信息,我深表歉意;如果需要的话可以提供。

slo*_*oth 8

正如金斯利在评论中所说,按坐标对精灵进行排序y是一种常见的方法。

这是一个完整的运行示例(我将您的图像命名为guy.pnggal.png)。由于您已经使用了精灵,因此我使用了一个简单的pygame.sprite.Group子类:

import pygame

class Actor(pygame.sprite.Sprite):
    def __init__(self, image, pos):
        super().__init__()
        self.image = image
        self.pos = pygame.Vector2(pos)
        self.rect = self.image.get_rect(center=self.pos)

    def update(self, events, dt):
        pass

class Player(Actor):
    def __init__(self, image, pos):
        super().__init__(image, pos)

    def update(self, events, dt):
        pressed = pygame.key.get_pressed()
        move = pygame.Vector2((0, 0))
        if pressed[pygame.K_w]: move += (0, -1)
        if pressed[pygame.K_a]: move += (-1, 0)
        if pressed[pygame.K_s]: move += (0, 1)
        if pressed[pygame.K_d]: move += (1, 0)
        if move.length() > 0: move.normalize_ip()
        self.pos += move*(dt/5)
        self.rect.center = self.pos

class YAwareGroup(pygame.sprite.Group):
    def by_y(self, spr):
        return spr.pos.y

    def draw(self, surface):
        sprites = self.sprites()
        surface_blit = surface.blit
        for spr in sorted(sprites, key=self.by_y):
            self.spritedict[spr] = surface_blit(spr.image, spr.rect)
        self.lostsprites = []

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    clock = pygame.time.Clock()
    dt = 0

    sprites = YAwareGroup(Player(pygame.image.load('guy.png').convert_alpha(), (100, 200)),
                          Actor(pygame.image.load('gal.png').convert_alpha(), (200, 200)))

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        sprites.update(events, dt)
        screen.fill((30, 30, 30))
        sprites.draw(screen)

        pygame.display.update()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您需要自定义绘图逻辑,子类化 pygame 类通常不是最糟糕的主意Group您可以在这里找到它们的来源,看看它们是如何工作的。