Pygame - 使用转义字符或换行符对文本进行 blitting

Sha*_*awk 5 pygame python-3.x

嗨,我希望将一些文本 blit 到 pygame 屏幕。我的文字是在推荐词之后有/包括一个换行符。

posX = (self.scrWidth * 1/8)
posY = (self.scrHeight * 1/8)
position = posX, posY
font = pygame.font.SysFont(self.font, self.fontSize)
if text == "INFO":
   text = """If you are learning to play, it is recommended
               you chose your own starting area."""
   label = font.render(text, True, self.fontColour)
   return label, position
Run Code Online (Sandbox Code Playgroud)

return给的表面和位置对位块。

我已经尝试使用三引号方法来包含空格,使用 \n。我不知道我做错了什么。

小智 10

pygame.font.Font/SysFont().render() 不支持多行文本。

这在此处的文档中有所说明。

文本只能是一行:不呈现换行符。

解决此问题的一种方法是呈现单行字符串列表。每行一个,并将它们一个在另一个下方。

例子:

posX = (self.scrWidth * 1/8)
posY = (self.scrHeight * 1/8)
position = posX, posY
font = pygame.font.SysFont(self.font, self.fontSize)
if text == "INFO":
    text = ["If you are learning to play, it is recommended",
            "you chose your own starting area."]
    label = []
    for line in text: 
        label.append(font.render(text, True, self.fontColour))
    return label, position
Run Code Online (Sandbox Code Playgroud)

然后要对图像进行 blit,您可以使用另一个 for 循环,如下所示:

for line in range(len(label)):
    surface.blit(label(line),(position[0],position[1]+(line*fontsize)+(15*line)))
Run Code Online (Sandbox Code Playgroud)

在 blit 的 Y 值中,该值为:

position[1]+(line*fontsize)+(15*line)
Run Code Online (Sandbox Code Playgroud)

这样做的确切方法是获取位置 [0],这是之前的 posY 变量,并将其用作 blit 的最左上角位置。

然后将 (line*fontsize) 添加到其中。因为 for 循环使用范围而不是列表项本身,所以行将是 1、2、3 等...,因此可以添加以将每个连续的行直接放在另一个之下。

最后,将 (15*line) 添加到其中。这就是我们如何获得空间之间的余量。在这种情况下,常量 15 表示边距应该是多少像素。数字越大,差距越大,数字越小,差距越小。添加“线”的原因是为了补偿将上述线向下移动所述数量。如果您愿意,您可以去掉“*line”以查看这将如何导致线条开始重叠。


Sha*_*awk 5

这是我在代码中找到并使用的答案。这样就生成了可以正常使用的文本表面。

class TextRectException:
    def __init__(self, message=None):
            self.message = message

    def __str__(self):
        return self.message


def multiLineSurface(string: str, font: pygame.font.Font, rect: pygame.rect.Rect, fontColour: tuple, BGColour: tuple, justification=0):
    """Returns a surface containing the passed text string, reformatted
    to fit within the given rect, word-wrapping as necessary. The text
    will be anti-aliased.

    Parameters
    ----------
    string - the text you wish to render. \n begins a new line.
    font - a Font object
    rect - a rect style giving the size of the surface requested.
    fontColour - a three-byte tuple of the rgb value of the
             text color. ex (0, 0, 0) = BLACK
    BGColour - a three-byte tuple of the rgb value of the surface.
    justification - 0 (default) left-justified
                1 horizontally centered
                2 right-justified

    Returns
    -------
    Success - a surface object with the text rendered onto it.
    Failure - raises a TextRectException if the text won't fit onto the surface.
    """

    finalLines = []
    requestedLines = string.splitlines()
    # Create a series of lines that will fit on the provided
    # rectangle.
    for requestedLine in requestedLines:
        if font.size(requestedLine)[0] > rect.width:
            words = requestedLine.split(' ')
            # if any of our words are too long to fit, return.
            for word in words:
                if font.size(word)[0] >= rect.width:
                    raise TextRectException("The word " + word + " is too long to fit in the rect passed.")
            # Start a new line
            accumulatedLine = ""
            for word in words:
                testLine = accumulatedLine + word + " "
                # Build the line while the words fit.
                if font.size(testLine)[0] < rect.width:
                    accumulatedLine = testLine
                else:
                    finalLines.append(accumulatedLine)
                    accumulatedLine = word + " "
            finalLines.append(accumulatedLine)
        else:
            finalLines.append(requestedLine)

    # Let's try to write the text out on the surface.
    surface = pygame.Surface(rect.size)
    surface.fill(BGColour)
    accumulatedHeight = 0
    for line in finalLines:
        if accumulatedHeight + font.size(line)[1] >= rect.height:
             raise TextRectException("Once word-wrapped, the text string was too tall to fit in the rect.")
        if line != "":
            tempSurface = font.render(line, 1, fontColour)
        if justification == 0:
            surface.blit(tempSurface, (0, accumulatedHeight))
        elif justification == 1:
            surface.blit(tempSurface, ((rect.width - tempSurface.get_width()) / 2, accumulatedHeight))
        elif justification == 2:
            surface.blit(tempSurface, (rect.width - tempSurface.get_width(), accumulatedHeight))
        else:
            raise TextRectException("Invalid justification argument: " + str(justification))
        accumulatedHeight += font.size(line)[1]
    return surface
Run Code Online (Sandbox Code Playgroud)