似乎无法在精灵上呈现 pygame 中的多行

Cant seem to render multiple lines in pygame on a sprite

我在 pygame 中将多行文本渲染到 sprite 上时遇到一些问题。文本是从 txt 文件中读取的,然后显示在由以下文本 class 制作的精灵上。但是,由于 pygame 没有正确呈现多行,我将注释部分按照应有的方式显示文本中的每个单词,没有意识到根据我设置所有内容的方式,我需要一个图像此文本 class。 (是的,实际上需要。) 所以我的问题是 有没有办法让我注释掉的部分创建的最终产品进入 self.image,就好像它是一个像我以前的文本表面一样的表面?

class Text(pg.sprite.Sprite):
    def __init__(self, game, x, y, text):
        self.groups = game.all_sprites, game.text
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        myfont = pg.font.SysFont('lucidaconsole', 20, bold = True)

        '''words = [word.split(' ') for word in text.splitlines()]
        space = myfont.size(' ')[0]
        max_width = 575
        max_height = 920
        pos = (0, 0)
        text_x, text_y = pos
        for line in words:
            for word in line:
                text_surface = myfont.render(word, False, (0, 255, 0))
                text_width, text_height = text_surface.get_size()
                if (text_x + text_width >= max_width):
                    text_x = pos[0]
                    text_y += text_height
                game.screen.blit(text_surface, (text_x, text_y))
                text_x += text_width + space
            text_x = pos[0]
            text_y += text_height'''

        textsurface = myfont.render(text, False, (0, 255, 0))
        self.image = textsurface
        game.screen.blit(textsurface, (0, 0))
        self.rect = game.text_img.get_rect()
        self.x = x
        self.y = y
        self._layer = 2
        self.rect.x = (x * TILESIZE) - 49
        self.rect.y = (y * TILESIZE) - 45

为什么必须这样做可能有点含糊,因为游戏的很大一部分是这样绘制的:

def draw(self):
    for sprite in sorted(self.all_sprites, key=lambda s: s._layer):
        self.screen.blit(sprite.image, self.camera.apply(sprite))
    pg.display.flip()

为了能够绘制它,它必须是 all_sprites 组的一部分,所以它确实需要图像,也许有办法以某种方式隐藏文本 class还在画呢?

为了传递文本,我使用

if event.type == pg.USEREVENT + 1:
            for row, tiles in enumerate(self.map.data):
                for col, tile in enumerate(tiles):
                    if tile == 'T':
                        with open('text_code.txt') as f:
                            for line in f:
                                Text(self, col, row, line)

因此文本来自 .txt 文件,其中找到了如下文本:

Player has moved left!
Player has moved down!
Player has moved down!
Player has moved right!
Player has moved right!

任何玩家动作都写在这里:

def move(self, dx=0, dy=0):
    if (dx == -1):
        with open('text_code.txt', 'a') as f:
            f.write('Player has moved left!\n')
    if (dx == 1):
        with open('text_code.txt', 'a') as f:
            f.write('Player has moved right!\n')
    if (dy == -1):
        with open('text_code.txt', 'a') as f:
            f.write('Player has moved up!\n')
    if (dy == 1):
        with open('text_code.txt', 'a') as f:
            f.write('Player has moved down!\n')

我希望这能解决问题吗?

要将多行位块传输到表面上,您需要先计算出文本的大小。

在下面的示例中,我将字符串列表传递给 Text class。

然后我找到最长线的宽度 max(font.size(line)[0] for line in self.text) 和线高 font.get_linesize() 并创建一个具有此尺寸的表面(通过 pg.SRCALPHA 使其透明)。

现在您可以使用 for 循环将 self.text 列表中的行渲染并 blit 到表面上。枚举行列表以获取 y 位置并将其乘以行高。

import pygame as pg


pg.init()

MYFONT = pg.font.SysFont('lucidaconsole', 20, bold=True)

s = """Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum."""


class Text(pg.sprite.Sprite):

    def __init__(self, pos, text, font):
        super().__init__()
        self.text = text
        width = max(font.size(line)[0] for line in self.text)
        height = font.get_linesize()
        self.image = pg.Surface((width+3, height*len(self.text)), pg.SRCALPHA)
        # self.image.fill(pg.Color('gray30'))  # Fill to see the image size.
        # Render and blit line after line.
        for y, line in enumerate(self.text):
            text_surf = font.render(line, True, (50, 150, 250))
            self.image.blit(text_surf, (0, y*height))
        self.rect = self.image.get_rect(topleft=pos)


class Game:

    def __init__(self):
        self.done = False
        self.clock = pg.time.Clock()
        self.screen = pg.display.set_mode((1024, 768))
        text = Text((20, 10), s.splitlines(), MYFONT)
        self.all_sprites = pg.sprite.Group(text)

    def run(self):
        while not self.done:
            self.clock.tick(30)
            self.handle_events()
            self.draw()

    def handle_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.done = True

    def draw(self):
        self.screen.fill((50, 50, 50))
        self.all_sprites.draw(self.screen)
        pg.display.flip()


if __name__ == '__main__':
    Game().run()
    pg.quit()