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

如何在终端尺寸变化时用Curses实现Perl动画重绘

解决Perl Term::Animation终端尺寸变化后无法重绘动画的问题

问题分析

你的代码存在几个关键问题导致终端 resize 后实体无法重绘:

  1. 错误的变量声明:my $entity->{position} 中的 my 会创建新的词法变量,而非修改原有实体的位置属性,导致原实体位置未更新。
  2. 未处理Curses的resize事件:getch() 默认是阻塞模式,会错过终端尺寸变化时触发的 KEY_RESIZE 事件,且单纯轮询屏幕尺寸不够可靠。
  3. 缺少必要的画面重置步骤:更新终端尺寸后,需要清除旧画面并确保动画环境正确重置,否则旧的渲染内容会干扰新画面。

修正后的代码

#!/usr/bin/env perl

use Term::Animation;
use Term::Animation::Entity;
use Curses;

# 初始化动画对象(补充你原本的实体声明代码)
my $anim1 = Term::Animation->new();
my $entity = Term::Animation::Entity->new(
    # 这里填入你原本的实体参数,比如shape、color等
);
$anim1->add_entity($entity);

# 获取初始屏幕尺寸
my ($width, $height) = $anim1->screen_size();
# 设置窗口非阻塞,避免getch()阻塞导致错过resize事件
nodelay($anim1->window(), 1);
# 启用keypad捕获特殊键(比如KEY_RESIZE)
keypad($anim1->window(), 1);

# 初始化实体到屏幕中间
$entity->{position} = [$height / 2 - 7, $width / 2 - 25, 0];

while (1) {
    # 渲染当前帧
    $anim1->animate();

    # 处理用户输入和resize事件
    my $input = getch();
    if (defined $input) {
        if ($input eq 'c') {
            last; # 按'c'退出
        } elsif ($input == KEY_RESIZE) {
            # 捕获终端resize事件
            my ($new_width, $new_height) = $anim1->screen_size();
            $width = $new_width;
            $height = $new_height;

            # 更新实体到新屏幕的中间位置(去掉my,直接修改原有实体)
            $entity->{position} = [$height / 2 - 7, $width / 2 - 25, 0];
            
            # 更新终端尺寸并清除旧画面
            $anim1->update_term_size();
            # 强制清除屏幕,避免残留旧内容
            clear();
        }
    }

    # 控制动画帧率,避免过度占用CPU
    napms(50);
}

# 退出时恢复终端设置
endwin();

关键修正点说明

  • 去掉my直接修改$entity->{position},确保原有实体的位置被更新。
  • 使用nodelay()设置非阻塞输入,keypad()启用特殊键捕获,确保能及时响应KEY_RESIZE事件。
  • 触发resize时调用clear()清除旧画面,配合update_term_size()重置动画的终端环境。
  • 添加napms()控制帧率,减少CPU占用。
  • 最后调用endwin()恢复终端正常状态,避免退出后终端显示异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:28:18