Pygame精灵在某个Y坐标处随着分层更新而消失

2024-06-01 13:36:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用pygame制作这个游戏,并且用分层更新绘制了一个player精灵。玩家的_layer是1,出于某种原因,当他到达y坐标上的某个点时,他就消失了。ground精灵的_layer值为2,因此player精灵应始终位于顶部。奇怪的是,他只是在某个y坐标处消失了

main.py:

import pygame
from sprites import *
from settings import *
from os import path

class Game:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
        pygame.display.set_caption(TITLE)
        pygame.key.set_repeat(500, 100)
        self.clock = pygame.time.Clock()
        self.load_data()

    def load_data(self):
        main_folder = path.dirname(__file__)
        img_dir = path.join(main_folder, 'img')
        self.map_data = []
        with open(path.join(main_folder, 'map.txt'), 'rt') as f:
            for line in f:
                self.map_data.append(line)
        self.spritesheet = Spritesheet(path.join(img_dir, SPRITESHEET))

    def new(self):
        self.all_sprites = pygame.sprite.LayeredUpdates()
        self.blocks = pygame.sprite.Group()
        self.grounds = pygame.sprite.Group()
        for row, tiles in enumerate(self.map_data):
            for col, tile in enumerate(tiles):
                Ground(self, col, row)
                if tile == 'a':
                    Block(self, col, row)
                if tile == 'P':
                    self.player = Player(self, col, row)


    def run(self):
        self.playing = True
        while self.playing:
            self.events()
            self.update()
            self.draw()

    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    self.player.move(0,-1)
                if event.key == pygame.K_a:
                    self.player.move(-1,0)
                if event.key == pygame.K_s:
                    self.player.move(0,1)
                if event.key == pygame.K_d:
                    self.player.move(1,0)


    def update(self):
        self.screen.fill(BLACK)
        self.all_sprites.update()
        self.clock.tick(FPS)

    def draw(self):
        self.all_sprites.draw(self.screen)
        pygame.display.update()

g = Game()
while True:
    g.new()
    g.run()

雪碧

import pygame
from settings import *

class Spritesheet:
    def __init__(self, filename):
        self.spritesheet = pygame.image.load(filename).convert()

    def get_image(self, x, y, width, height):
        image = pygame.Surface((width, height))
        image.blit(self.spritesheet, (0,0), (x, y, width, height))
        return image

class Player(pygame.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = self.game.spritesheet.get_image(0,32,32,32)
        self.image.set_colorkey(BLACK)
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self.dir = 'UP'
        self._layer = PLAYER_LAYER

    def move(self, x_change, y_change):
        if x_change > 0:
            self.dir = 'RIGHT'
        if x_change < 0:
            self.dir = 'LEFT'
        if y_change > 0:
            self.dir = 'DOWN'
        if y_change < 0:
            self.dir = 'UP'

        if not self.collide(x_change, y_change):
            self.x += x_change
            self.y += y_change

    def collide(self, x_change, y_change):
        for block in self.game.blocks:
            if block.x == self.x + x_change and block.y == self.y + y_change and block.collidable:
                return True
        return False

    def update(self):
        self.rect.x = self.x * SCALE
        self.rect.y = self.y * SCALE

class Block(pygame.sprite.Sprite):
    def __init__(self, game, x, y, collidable=True, groups=None):
        pygame.sprite.Sprite.__init__(self, groups or (game.all_sprites, game.blocks))
        self.game = game
        self.image = pygame.Surface((SCALE, SCALE))
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self.collidable = collidable

    def update(self):
        self.rect.x = self.x * SCALE
        self.rect.y = self.y * SCALE

class Ground(Block):
    def __init__(self, game, x, y, collidable=False, groups=None):
        Block.__init__(self, game, x, y, collidable, groups or (game.all_sprites, game.grounds))
        self.image = self.game.spritesheet.get_image(0, 0, 32, 32)
        self._layer = GROUND_LAYER

settings.py:

WIN_WIDTH = 640
WIN_HEIGHT = 480

SPRITESHEET = 'sheet.png'

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

TITLE = 'Pykemon'
SCALE = 32
FPS = 60

PLAYER_LAYER = 1
TREE_LAYER = 2
GROUND_LAYER = 3

map.txt:

aaaaaaaaaaaaaaaaaaaa
a..................a
a..................a
a..................a
a..................a
a..................a
a..................a
a..................a
a..................a
a....P.............a
a..................a
a..................a
a..................a
a..................a
aaaaaaaaaaaaaaaaaaaa

谢谢


Tags: rectimageselfeventgameifinitdef
2条回答

你的地面层是3,玩家层是1。编号较低的层位于编号较高的层之下,因此玩家将被隐藏在地面上

根据文件“map.txt”中的数据定位地面分幅。我不知道那是什么,但我猜当玩家走到你想要的地砖上面时,它实际上就在地砖下面。或者它正在树下

尝试反转玩家、树和地面层的顺序

PLAYER_LAYER = 3
TREE_LAYER = 2
GROUND_LAYER = 1

@rabbi76在他的回答中关于层顺序的说法是正确的,尽管不是关于_layer属性或_layer的工作方式。这个@rabbi76无意冒犯,文档实际上是错的,我今天早些时候刚刚在文档中纠正了这一点。{a1}现在说“如果您添加的精灵有一个属性_层,那么将使用该层。”

此外,您还可以将_layer属性指定给任何数字,从而将精灵放置在您喜欢的任何级别。实际上,并没有创建一个层这样的事情。LayeredUpdates只是按照_layer属性指示的顺序遍历精灵。在我的代码中,我将精灵放置在一个层中,只需指定_layer属性即可上下移动精灵。如果您使用的属性名称不正确,则可能会出现这种情况,因为您必须使用各种方法来操作层,以便在不设置_layer的情况下工作

图层必须按升序排列:

PLAYER_LAYER = 3
TREE_LAYER = 2
GROUND_LAYER = 1

当精灵位于分层组(^{})中时,可通过^{}更改该层:

class Player(pygame.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites
        pygame.sprite.Sprite.__init__(self, self.groups)
        # [...]        

        game.all_sprites.change_layer(self, PLAYER_LAYER)
class Ground(Block):
    def __init__(self, game, x, y, collidable=False, groups=None):
        Block.__init__(self, game, x, y, collidable, groups or (game.all_sprites, game.grounds))
        self.image = self.game.spritesheet.get_image(0, 0, 32, 32)

        game.all_sprites.change_layer(self, GROUND_LAYER)

注意,更改_layer属性不会神奇地更改精灵的层。在将精灵添加到组之前,必须设置_layer属性。因此,您必须在super()调用之前设置层属性

class Player(pygame.sprite.Sprite):
    def __init__(self, game, x, y):

        self._layer = PLAYER_LAYER

        self.groups = game.all_sprites
        pygame.sprite.Sprite.__init__(self, self.groups)
class Ground(Block):
    def __init__(self, game, x, y, collidable=False, groups=None):

        self._layer = GROUND_LAYER

        Block.__init__(self, game, x, y, collidable, groups or (game.all_sprites, game.grounds))
        self.image = self.game.spritesheet.get_image(0, 0, 32, 32)

或者,如果将layer关键字参数传递给^{},则在组中创建一个层。而以下工作(如果self不在game.all_sprites之前):

game.all_sprites.add(self, layer=PLAYER_LAYER)

相关问题 更多 >