You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pygame逐字动画文本换行时重复显示而非正常换行如何解决

问题原因

现有代码存在两个核心逻辑错误,导致换行时内容重复错乱:

  1. 逐字生成器与自动换行的遍历逻辑完全不匹配:逐字生成器每次返回的是「从文本开头到当前输出字符的完整字符串」,但原自动换行逻辑是按单个单词为单位做遍历,每次调用next()拿到的不是当前要渲染的单个单词,而是累加的全量文本,直接绘制必然出现重复。
  2. 每帧更新文本时没有清空textsurface上的旧渲染内容,新绘制的内容会和上一帧的残留叠加,进一步加剧显示异常。
修复方案

把逐字生成、自动换行、渲染三个逻辑拆分:每次从生成器拿到当前已输出的完整文本后,先清空画布,再对完整文本做自动换行排版,最后统一绘制。

修复后完整代码

DynamicText类实现

class DynamicText:
    """
    显示支持自动换行的逐字弹出文本
    """
    def __init__(self, text, pos, font, color=WHITE, autoreset=False, text_surface=None):
        self.done = False
        self.font = font
        self.text = text
        self._gen = self.text_generator(self.text)
        self.pos = pos
        self.color = color
        self.autoreset = autoreset
        self.text_surface = text_surface
        self.full_rendered_text = ""
        self.update()
    
    def reset(self):
        self._gen = self.text_generator(self.text)
        self.done = False
        self.full_rendered_text = ""
        self.update()
        
    def update(self):
        if not self.done:
            try:
                self.full_rendered_text = next(self._gen)
                self.render_wrapped_text()
            except StopIteration: 
                self.done = True
                if self.autoreset: 
                    self.reset()
    
    def render_wrapped_text(self):
        # 清空上一帧的文本内容,透明背景用(0,0,0,0),不透明背景替换为你自己的文本框底色
        self.text_surface.fill((0,0,0,0))
        max_width, _ = self.text_surface.get_size()
        x, y = self.pos
        space_width = self.font.size(' ')[0]
        line_height = self.font.get_linesize()

        words = self.full_rendered_text.split(' ')
        current_line_width = 0
        for word in words:
            word_surface = self.font.render(word, True, self.color)
            word_width = word_surface.get_width()
            # 当前行宽度溢出则重置x坐标、y坐标累加行高换行
            if current_line_width + word_width > max_width:
                x = self.pos[0]
                y += line_height
                current_line_width = 0
            self.text_surface.blit(word_surface, (x, y))
            x += word_width + space_width
            current_line_width += word_width + space_width
    
    def text_generator(self,text):
        tmp = ""
        for letter in text:
            tmp += letter
            if letter != " ":
                yield tmp
        yield tmp

主程序适配修改

初始化DynamicText时传入目标渲染的textsurface,主循环每帧记得清屏避免叠影:

if __name__=='__main__':
    running=True
    ds=DoStuff() # 生成屏幕、文本框、图片矩形的原有逻辑保持不变
    # 初始化时传入textsurface作为文本渲染目标
    msg=DynamicText("Hey, does rendering this work? What about actual multiline text?", (10,10), textdata, WHITE, text_surface=textsurface)
    while running:
        screen.fill((0,0,0)) # 每帧先填充屏幕底色,避免画面残留
        screen.blit(textsurface,(20,10))
        screen.blit(imgsurface,(650,10))
        clock.tick(60)
        pg.display.update()
        for event in pg.event.get():
            if event.type==QUIT:
                running=False
            if event.type==pg.USEREVENT:
                msg.update()
    pg.quit()
    sys.exit()
效果对照
  • 单行文本运行正常:
    单行正常效果
  • 修复前长文本换行异常效果:
    换行异常效果

内容的提问来源于stack exchange,提问作者undonepotato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:33:19