Не могу отрисовать несколько строк в Pygame на спрайте
У меня есть некоторые проблемы при рендеринге нескольких строк текста на спрайт в Pygame. Текст читается из текстового файла, а затем отображается на спрайте, который создается следующим классом Text. Однако, поскольку pygame неправильно отображает несколько строк, я сделал закомментированную часть для отображения каждого слова в тексте так, как оно должно быть показано, не осознавая, что в соответствии с тем, как я все настроил, мне нужно изображение в этом классе Text. (Да, действительно нужно.)ТАК МОЙ ВОПРОС: Есть ли способ получить конечный продукт, который создает моя закомментированная часть, в 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, делающей его таким, чтобы ему действительно требовалось изображение, возможно, есть способ как-то изолировать класс Text, все еще рисуя его?
Чтобы передать текст, я использую
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')
Надеюсь, это прояснит ситуацию?
1 ответ
Чтобы растереть несколько линий на поверхности, вам нужно сначала определить размер текста.
В приведенном ниже примере я передаю список строк Text
учебный класс.
Тогда я нахожу ширину самой длинной линии max(font.size(line)[0] for line in self.text)
и высота линии font.get_linesize()
и создать поверхность с этим размером (пройти pg.SRCALPHA
сделать его прозрачным).
Теперь вы можете использовать for
цикл для рендеринга и блики строк в self.text
список на поверхность. Перечислите список строк, чтобы получить позицию 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()