简体   繁体   English

如何在Pygame中将段落渲染到表面上

[英]How to render a paragraph onto a surface in pygame

I've made a fully functioning main menu with buttons where one button take you to the game and another button that takes you to the instruction page. 我已经制作了一个功能齐全的主菜单,其中的按钮带您进入游戏,一个按钮带您进入说明页面。

However, in my instructions page I can only write a one line sentence. 但是,在我的说明页中,我只能写一个单行句子。 If I add multiple lines it shows squares in the middle. 如果添加多条线,则中间会显示正方形。

What I want achieve is to write a multi-line paragraph onto the screen for displaying some instruction, game information, etc. 我想要实现的是在屏幕上写一个多行段落,以显示一些指令,游戏信息等。

Here es a screen shot of my current game GUI: 这是我当前游戏GUI的屏幕截图: 游戏GUI

And this is the relevant code I have so far: 这是我到目前为止拥有的相关代码:

def text_objects(text, font):
   textSurface = font.render(text, True, (0,0,0))
   return textSurface, textSurface.get_rect()


def ParagraphText(text, font):
   ParagraphSize = (600,500)
   FontSize = font.get_height()

   ParagraphSurf = pygame.Surface(ParagraphSize)

   ParagraphSurf.fill(WHITE)
   ParagraphSurf.set_colorkey(WHITE)

   SplitLines = text.splitlines()

   CentreText = (ParagraphSize[1] - len(SplitLines)*(FontSize + 1)//2)

   for idx, line in enumerate(SplitLines):
       currentTextline = font.render(text, False, (0, 0, 0))
       currentPostion = (0, idx * FontSize + CentreText)
       ParagraphSurf.blit(currentTextline, currentPostion)

   return ParagraphSurf, ParagraphSize



def Instructions():
   paragraph = """Your are the last surviving rhino. Your horn
   is worth millions! Right now you are trapped in a zoo and
   waiting to be slaughtered for your horn. But you can't give
   up! Escape from the tribesmen and zoo security so you can
   enjoy your life as a free being once again"""

   screen.blit(pygame.image.load("background0.jpg").convert(), (0,0))
   InstructionsFont = pygame.font.SysFont("elephant",15)
   TextSurf, TextRect = text_objects("Instructions", InstructionsFont)
   TextRect.center = ((screen_width/2),(screen_height/6))
   screen.blit(TextSurf, TextRect)

   ParagraphText(paragraph,InstructionsFont)

   intro = True

   while intro:
       for event in pygame.event.get():
           if event.type == pygame.QUIT:
               pygame.quit()
               quit()

       Buttons("BACK",100,500,120,50,TURQUOISE,DARK_TURQUOISE,"back")

       pygame.display.update()
       clock.tick(15)

The render() method of a pygame.font.Font object can only blit single line text, as stated in the documentation . pygame.font.Font对象的render()方法只能对单行文本进行对齐,如文档所述

To work around this you have to adapt your text_objects() function to draw each line of the passed in text string separately onto the appropriate position: 要解决此问题,您必须调整text_objects()函数,以将传入的文本字符串的每一行分别绘制到适当的位置:

  1. Create a new surface onto which the whole paragraph will be drawn. 创建一个将在其上绘制整个段落的新曲面。 To fake a transparent surface use Pygame's set_colorkey() method. 要伪造透明表面,请使用Pygame的set_colorkey()方法。 1) 1)
  2. Split the text into several lines of characters using Python's built-in splitlines() method. 使用Python的内置splitlines()方法将文本分成几行字符。
  3. Compute an optional offset value if you want to align (eg center) the text vertically inside the paragraph surface. 如果要在段落表面内垂直对齐(例如居中)文本,请计算一个可选的偏移值。
  4. Loop (ie enumerate) over the split lines: 在分割线上循环(即枚举):
    • Render the current line of characters onto a dummy surface. 将当前字符行渲染到虚拟表面上。 1) 1)
    • Calculate the position of this line to fit into a paragraph style. 计算该行的位置以适合段落样式。
    • Blit the dummy surface onto the main paragraph surface. 将虚拟曲面蒙到主段落曲面上。
  5. Draw the paragraph surface onto the main screen or return it with other parameters. 将段落表面绘制到主屏幕上,或将其与其他参数一起返回。

Now it´s time implement this: 现在是时候实现这一点了:

def text_objects(text, font):
    paragraphSize = (xsize, ysize)
    fontSize = font.get_height()

    # Step 1
    paragraphSurface = pygame.Surface(paragraphSize ) 

    #Set colorkey to fake transparent paragraph surface
    paragraphSurface.fill((255, 255, 255))
    paragraphSurface.set_colorkey((255, 255, 255))

    # Step 2
    splitLines = text.splitlines() 

    # Step 3: center the text vertically 
    offSet = (paragraphSize[1] - len(splitLines) * (fontSize + 1)) // 2 

    #Step 4
    for idx, line in enumerate(splitLines):
        currentTextline = font.render(line, False, (0, 0, 0))
        currentPostion = (0, idx * fontSize + offSet)
        paragraphSurface.blit(currentTextline, currentPostion)

    #Step 5
    return paragraphSurface, paragraphSize

If you want to center each line in the text, don't set the x -coordinate of the currentPostion to 0 but use the following calculation: 如果要使文本中的每一行居中,请不要将currentPostionx坐标设置为0而是使用以下计算:

#center paragraph
currentPostion = ((paragraphSize[0] - currentTextline.get_width()) // 2, #x-coordinate
                  idx * fontSize + offSet) #y-coordinate

sample: center text

or right align: 或右对齐:

#right align paragraph
currentPostion = (paragraphSize[0] - currentTextline.get_width(), #x-coordinate
                  idx * fontSize + offSet) #y-coordinate

sample: right align

1) Please note that setting the antialias parameter to true when rendering a line, can have bad effects because of the set color-key of the paragraph surface! 1) 请注意,渲染直线时将antialias参数设置为true ,由于设置了段落表面的颜色键,可能会产生不良影响!

I hope this helps you :) 我希望这可以帮助你 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM