python-3.x 在pygame中使文本适合现有曲面

zy1mlcev  于 2023-02-10  发布在  Python
关注(0)|答案(3)|浏览(153)

我尝试创建大小相同的文本表面,无论文本是什么。换句话说:我希望较长的文本具有较小的字体大小,较短的文本具有较大的字体大小,以便使文本适合现有的Surface。
要在pygame中创建文本,我需要:
1.创建字体对象。例如:font = pygame.font.SysFont('Arial', 32)
1.从字体对象创建文本表面。例如:text = font.render('My text', True, (255, 255, 255))

  1. Blitting文本表面。
    问题是,在创建文本表面之前,我首先需要创建一个特定大小的字体对象,我创建了一个函数来完成我想要做的事情:
import pygame

def get_text(surface, text, color=(255, 255, 255), max_size=128, font_name='Arial'):
    """
    Returns a text surface that fits inside given surface. The text
    will have a font size of 'max_size' or less.
    """
    surface_width, surface_height = surface.get_size()
    lower, upper = 0, max_size
    while True:
        font = pygame.font.SysFont(font_name, max_size)
        font_width, font_height = font.size(text)

        if upper - lower <= 1:
            return font.render(text, True, color)
        elif max_size < 1:
            raise ValueError("Text can't fit in the given surface.")
        elif font_width > surface_width or font_height > surface_height:
            upper = max_size
            max_size = (lower + upper) // 2
        elif font_width < surface_width or font_height < surface_height:
            lower = max_size
            max_size = (lower + upper) // 2
        else:
            return font.render(text, True, color)

有没有其他更清洁和/或更有效的方法来解决这个问题?

a1o7rhls

a1o7rhls1#

不幸的是,这似乎是最合适的解决方案。字体大小更多的是一种近似值,不同字体之间也会有所不同,因此没有统一的方法来计算特定字体所占的面积。另一个问题是,某些字体的某些字符大小不同。
理论上,等宽字体可以使计算更高效,只需将表面的宽度除以字符串的长度,然后检查等宽字体的大小是否覆盖了该区域。

lnlaulya

lnlaulya2#

您可以重新缩放文本图像以适合:

def fit_text_to_width(text, color, pixels, font_face = None):
    font = pygame.font.SysFont(font_face, pixels *3 // len(text) ) 
    text_surface = font.render(text, True, color)
    size = text_surface.get_size()
    size = ( pixels, int(size[1] * pixels / size[0]) )
    return pygame.transform.scale(text_surface, size)
qjp7pelc

qjp7pelc3#

Font对象似乎有size() -> (width, height)metrics() -> list[(minx, maxx, miny, maxy)]方法,这两个方法对于检查每个结果字符的大小和文本的宽度很有用。
最简单的方法是使用size,并简单地根据某个比率(例如screen_width / font.size()[0])将文本缩小到所需的宽度和高度。
为了将文本分成几行,需要使用metrics方法,应该可以循环遍历度量列表,并根据每行的总宽度拆分文本。

相关问题