Python/Pygame 使 Pygame 中的文本在离开 window 时换行
Python/Pygame make text in Pygame wrap when in leaves the window
我有一个渲染的文本函数 text.The 函数如下
def textFunc(font,msg,color,x,y,center):
text_render = font.render(msg,True,color)
text_rect = text_render.get_rect()
#If center is true, then the X,Y will be used as the center
if center == True:
text_rect.center = (x,y)
else:
text_rect = (x,y)
game_display.blit(text_render,text_rect)
但是我的 msg 字符串太长,它会呈现在 window 之外。
有没有办法让我的文本注册为我的 window 太长,因此在文本开头以下继续?类似于计算机如何自动完成
有点像这样:
没有自动解决方案。你必须自己实现文本换行,逐行逐字绘制文本。
幸运的是 PyGame wiki 提供了一个功能来完成这个任务。请参见 PyGame 维基 Simple Text Wrapping for pygame。
我扩展了该函数并添加了一个额外的参数,它提供 left 或 right 对齐的文本,居中 文本甚至 块 模式:
textAlignLeft = 0
textAlignRight = 1
textAlignCenter = 2
textAlignBlock = 3
def drawText(surface, text, color, rect, font, align=textAlignLeft, aa=False, bkg=None):
lineSpacing = -2
spaceWidth, fontHeight = font.size(" ")[0], font.size("Tg")[1]
listOfWords = text.split(" ")
if bkg:
imageList = [font.render(word, 1, color, bkg) for word in listOfWords]
for image in imageList: image.set_colorkey(bkg)
else:
imageList = [font.render(word, aa, color) for word in listOfWords]
maxLen = rect[2]
lineLenList = [0]
lineList = [[]]
for image in imageList:
width = image.get_width()
lineLen = lineLenList[-1] + len(lineList[-1]) * spaceWidth + width
if len(lineList[-1]) == 0 or lineLen <= maxLen:
lineLenList[-1] += width
lineList[-1].append(image)
else:
lineLenList.append(width)
lineList.append([image])
lineBottom = rect[1]
lastLine = 0
for lineLen, lineImages in zip(lineLenList, lineList):
lineLeft = rect[0]
if align == textAlignRight:
lineLeft += + rect[2] - lineLen - spaceWidth * (len(lineImages)-1)
elif align == textAlignCenter:
lineLeft += (rect[2] - lineLen - spaceWidth * (len(lineImages)-1)) // 2
elif align == textAlignBlock and len(lineImages) > 1:
spaceWidth = (rect[2] - lineLen) // (len(lineImages)-1)
if lineBottom + fontHeight > rect[1] + rect[3]:
break
lastLine += 1
for i, image in enumerate(lineImages):
x, y = lineLeft + i*spaceWidth, lineBottom
surface.blit(image, (round(x), y))
lineLeft += image.get_width()
lineBottom += fontHeight + lineSpacing
if lastLine < len(lineList):
drawWords = sum([len(lineList[i]) for i in range(lastLine)])
remainingText = ""
for text in listOfWords[drawWords:]: remainingText += text + " "
return remainingText
return ""
最小示例: repl.it/@Rabbid76/PyGame-TextWrap
import pygame
pygame.init()
font = pygame.font.SysFont(None, 40)
msg = "Simple function that will draw text and wrap it to fit the rect passed. If there is any text that will not fit into the box, the remaining text will be returned."
textRect = pygame.Rect(100, 100, 300, 300)
window = pygame.display.set_mode((500, 500))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill((255, 255, 255))
pygame.draw.rect(window, (0, 0, 0), textRect, 1)
drawTextRect = textRect.inflate(-5, -5)
drawText(window, msg, (0, 0, 0), drawTextRect, font, textAlignBlock, True)
pygame.display.flip()
我有一个渲染的文本函数 text.The 函数如下
def textFunc(font,msg,color,x,y,center):
text_render = font.render(msg,True,color)
text_rect = text_render.get_rect()
#If center is true, then the X,Y will be used as the center
if center == True:
text_rect.center = (x,y)
else:
text_rect = (x,y)
game_display.blit(text_render,text_rect)
但是我的 msg 字符串太长,它会呈现在 window 之外。
有没有办法让我的文本注册为我的 window 太长,因此在文本开头以下继续?类似于计算机如何自动完成
有点像这样:
没有自动解决方案。你必须自己实现文本换行,逐行逐字绘制文本。
幸运的是 PyGame wiki 提供了一个功能来完成这个任务。请参见 PyGame 维基 Simple Text Wrapping for pygame。
我扩展了该函数并添加了一个额外的参数,它提供 left 或 right 对齐的文本,居中 文本甚至 块 模式:
textAlignLeft = 0
textAlignRight = 1
textAlignCenter = 2
textAlignBlock = 3
def drawText(surface, text, color, rect, font, align=textAlignLeft, aa=False, bkg=None):
lineSpacing = -2
spaceWidth, fontHeight = font.size(" ")[0], font.size("Tg")[1]
listOfWords = text.split(" ")
if bkg:
imageList = [font.render(word, 1, color, bkg) for word in listOfWords]
for image in imageList: image.set_colorkey(bkg)
else:
imageList = [font.render(word, aa, color) for word in listOfWords]
maxLen = rect[2]
lineLenList = [0]
lineList = [[]]
for image in imageList:
width = image.get_width()
lineLen = lineLenList[-1] + len(lineList[-1]) * spaceWidth + width
if len(lineList[-1]) == 0 or lineLen <= maxLen:
lineLenList[-1] += width
lineList[-1].append(image)
else:
lineLenList.append(width)
lineList.append([image])
lineBottom = rect[1]
lastLine = 0
for lineLen, lineImages in zip(lineLenList, lineList):
lineLeft = rect[0]
if align == textAlignRight:
lineLeft += + rect[2] - lineLen - spaceWidth * (len(lineImages)-1)
elif align == textAlignCenter:
lineLeft += (rect[2] - lineLen - spaceWidth * (len(lineImages)-1)) // 2
elif align == textAlignBlock and len(lineImages) > 1:
spaceWidth = (rect[2] - lineLen) // (len(lineImages)-1)
if lineBottom + fontHeight > rect[1] + rect[3]:
break
lastLine += 1
for i, image in enumerate(lineImages):
x, y = lineLeft + i*spaceWidth, lineBottom
surface.blit(image, (round(x), y))
lineLeft += image.get_width()
lineBottom += fontHeight + lineSpacing
if lastLine < len(lineList):
drawWords = sum([len(lineList[i]) for i in range(lastLine)])
remainingText = ""
for text in listOfWords[drawWords:]: remainingText += text + " "
return remainingText
return ""
最小示例:
import pygame
pygame.init()
font = pygame.font.SysFont(None, 40)
msg = "Simple function that will draw text and wrap it to fit the rect passed. If there is any text that will not fit into the box, the remaining text will be returned."
textRect = pygame.Rect(100, 100, 300, 300)
window = pygame.display.set_mode((500, 500))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill((255, 255, 255))
pygame.draw.rect(window, (0, 0, 0), textRect, 1)
drawTextRect = textRect.inflate(-5, -5)
drawText(window, msg, (0, 0, 0), drawTextRect, font, textAlignBlock, True)
pygame.display.flip()