如何在 terminal 上做一个喜迎新春的动画

今天来玩点特别点的东西,就是在命令行中端 terminal 上,用 ascii 字符,来显示一个类似动画的效果。我用了一个开源库 ncurses。先展示一个 gif 动态图片给大家看下实际的效果。

动图展示太快,可能看不清楚。图片展示的效果,是从右下角放出了一枚烟花,烟花绽放后变身成了一条神龙,庆祝 2024。神龙吐出一枚龙珠炮弹,将 2023 年的一切不快全部击碎,然后给大家展示了一个祝福界面

sql 复制代码
HAPPY NEW YEAR!!!GUYS

实现起来也比较简单,就是调用 ncurses 的接口 mvprintw,在屏幕上显示相应的字符。而字符移动的过程,就是根据屏幕的 row 和 col 坐标,不停的移动的过程,每移动一步,还需要 clean 上一步在屏幕上显示的字符。具体来看下实现过程。

实现细节

烟花展示

从右下角开始,往屏幕中间放烟花。

c 复制代码
start = 140;
direction = -1;
for (row = 1; row < 30; row++) {
  MvPrintw(LINES - row, start + (row * direction),
           (direction < 0) ? "\\" : "/");
  showit();
}

MvPrintw 就是 ncurses mvprintw 函数的一个封装,具体函数模型为

arduino 复制代码
int mvprintw(int y, int x, const char* fmt, ...)

在屏幕的 row 为 y,col 为 x 处显示字符串。上面的代码,就是从右下角开始往屏幕中间移动,通过 '' 这个字符进行移动模拟发射烟花的效果。而比较有意思的就是烟花绽放的过程。其实就是几组 ascii 字符一次展示的过程。

c 复制代码
  init_pair(1, get_colour(&bold), my_bg);
  (void)attrset(AttrArg(COLOR_PAIR(1), bold));
  MvPrintw(row - 1, col - 1, " - ");
  MvPrintw(row + 0, col - 1, "-+-");
  MvPrintw(row + 1, col - 1, " - ");
  showit();

  init_pair(1, get_colour(&bold), my_bg);
  (void)attrset(AttrArg(COLOR_PAIR(1), bold));
  MvPrintw(row - 2, col - 2, " --- ");
  MvPrintw(row - 1, col - 2, "-+++-");
  MvPrintw(row + 0, col - 2, "-+#+-");
  MvPrintw(row + 1, col - 2, "-+++-");
  MvPrintw(row + 2, col - 2, " --- ");
  showit();

  init_pair(1, get_colour(&bold), my_bg);
  (void)attrset(AttrArg(COLOR_PAIR(1), bold));
  MvPrintw(row - 2, col - 2, " +++ ");
  MvPrintw(row - 1, col - 2, "++#++");
  MvPrintw(row + 0, col - 2, "+# #+");
  MvPrintw(row + 1, col - 2, "++#++");
  MvPrintw(row + 2, col - 2, " +++ ");
  showit();

  init_pair(1, get_colour(&bold), my_bg);
  (void)attrset(AttrArg(COLOR_PAIR(1), bold));
  MvPrintw(row - 2, col - 2, "  #  ");
  MvPrintw(row - 1, col - 2, "## ##");
  MvPrintw(row + 0, col - 2, "#   #");
  MvPrintw(row + 1, col - 2, "## ##");
  MvPrintw(row + 2, col - 2, "  #  ");
  showit();

  init_pair(1, get_colour(&bold), my_bg);
  (void)attrset(AttrArg(COLOR_PAIR(1), bold));
  MvPrintw(row - 2, col - 2, " # # ");
  MvPrintw(row - 1, col - 2, "#   #");
  MvPrintw(row + 0, col - 2, "     ");
  MvPrintw(row + 1, col - 2, "#   #");
  MvPrintw(row + 2, col - 2, " # # ");
  showit();

  init_pair(1, get_colour(&bold), my_bg);
  (void)attrset(AttrArg(COLOR_PAIR(1), bold));
  MvPrintw(row - 2, col - 2, "  * * ");
  MvPrintw(row - 1, col - 2, "*     *");
  MvPrintw(row + 0, col - 2, "       ");
  MvPrintw(row + 1, col - 2, "*     *");
  MvPrintw(row + 2, col - 2, "  * * ");
  showit();

直接放动图会更加直观

就是上面几个图形一次展示的过程。而烟花绽放结束后,就出现了今天的主角神龙。

绘制神龙

神龙的绘制,也是通过 ascii 字符拼接起来的。这个 ascii 字符画神龙的过程,我是让 gpt 来实现的,然后把翅膀去掉了。大家都知道,国外的 dragon 都是有翅膀的,而且大部分都是贪婪的象征。那不是我心目中的神龙,我心目中的神龙,那可是经过九九八十一难,历经千辛万苦,集齐12颗龙珠才出现的,是可以帮人实现愿望的(狗头)。

看下代码

吐龙珠炮弹的过程也比较简单,就是绘制一个圆形,然后 row 不变,col 不断变小,从屏幕右边移动到左边的一个过程。

代码里面有些 magic number,是我计算的当前屏幕中对话框的长度,这里懒得改成变量的方式了。

击碎 2023 的不快

龙珠炮弹向左移动的目标,是为了击碎 2023 年的所有不快。这些不快的事情,显示在了一个钻石形状的框框里面。

即使在2023年经历了无尽的坎坷与艰辛,但终究已成为了历史。彼时所承受的所有磨砺与困苦,如同雕琢璞玉的刻刀,精心塑造了此刻熠熠生辉的你。岁月的沉淀将困厄转化为智慧的光芒,映照出你坚韧不屈的身影,而这一切过往,皆是为了铸就今日卓越的你。

结语

好了,今天的故事到这就结束了。2024 的故事,这才刚刚开始。

新的一年,愿你们心如明镜台,映照出生活的美好,滤去烦忧的尘埃,让心灵沐浴在宁静与和谐之中。 将每一个平凡的日子都装点成一首首动人的诗篇,以最美的姿态迎接 2024 的每天。

相关推荐
一路往蓝-Anbo1 小时前
STM32单线串口通讯实战(二):链路层核心 —— DMA环形缓冲与收发切换时序
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网
散峰而望1 小时前
【算法竞赛】C++入门(三)、C++输入输出初级 -- 习题篇
c语言·开发语言·数据结构·c++·算法·github
一路往蓝-Anbo3 小时前
STM32单线串口通讯实战(三):协议层设计 —— 帧结构、多机寻址与硬件唤醒
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网
爱吃生蚝的于勒3 小时前
【Linux】零基础深入学习动静态库+深入学习地址
linux·运维·服务器·c语言·数据结构·c++·学习
♛识尔如昼♛4 小时前
C 基础(4) - 字符串和格式化输入输出
c语言·开发语言
散峰而望13 小时前
【算法竞赛】C++函数详解:从定义、调用到高级用法
c语言·开发语言·数据结构·c++·算法·github
冷凝雨13 小时前
复数乘法(C & Simulink)
c语言·开发语言·信号处理·simulink·dsp
智者知已应修善业14 小时前
【求等差数列个数/无序获取最大最小次大次小】2024-3-8
c语言·c++·经验分享·笔记·算法
量子炒饭大师15 小时前
Cyber骇客的逻辑节点美学 ——【初阶数据结构与算法】二叉树
c语言·数据结构·c++·链表·排序算法
量子炒饭大师16 小时前
Cyber骇客神经塔尖协议 ——【初阶数据结构与算法】堆
c语言·数据结构·c++·二叉树·github·