ANSI Escape Sequence 下落的方块

2024-02-10 05:44

本文主要是介绍ANSI Escape Sequence 下落的方块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ANSI Escape Sequence 下落的方块

1. ANSI Escape 的用途

无意中发现 B站有人讲解, 完全基于终端实现俄罗斯方块。 基本想法是借助于 ANSI Escape Sequence 实现方方块的绘制、 下落动态效果等。对于只了解 ansi escape sequence 用于 log 的颜色打印的人来说, 这无疑是拓宽了认识。

在这里插入图片描述

这一篇简单的列一下 ansi escape sequence 中的稀奇古怪的数字的含义, 并最终给出一个绿色方块下落的动态效果和对应的代码。 基于本篇给出的表格和代码, 可以把它拓展为自由落体的游戏效果, 也可以跟着 B 站视频更容易的写出终端里的俄罗斯方块。

同时也注意到, ansi escape sequence 有它的局限性, 无法绘制比较大的圆形, 使用 ansi escape sequence 会限制界面显示、 游戏开发的上限。

2. ANSI Escape Sequence 有什么用?

终端会把 ANSI Escape 序列的字符解释为命令,而不是原本的内容。这些命令在终端上控制如下内容:

  • 鼠标位置
  • 颜色
  • 字体样式
  • 其他选项

使用 ANSI Escape Sequence 做 log 打印的例子比较多, 但其实还可以那它用作绘图显示: 把终端当成是 256 色的图像, 在终端显示图像内容。

3. 形式

3.1 格式概况

  • 绝大多数有用的序列: ESC[ 开头
  • 序列的重置: ESC[0m, 意思是各种设置的属性都撤销掉,恢复为没有设置时的状态

一些“黑话”:

  • CSI (Control Sequence Introducer): ESC[ 的别名, ASCII escape 数值是27, 实际使用时 ESC 换成 \x1b(16进制), \033(8进制) 或 \e
  • SGR (Select Graphic Rendition): CSI n m 的别名,用于设定字符的颜色和风格。其中:
    • CSI 要换成 \x1b[, \033[\e[
    • n 要换成具体的数字,在 0~107 之间

根据 wikipedia 得到的解释:

  • 起始: ESC[ (这个组合又叫做 CSI, Control Sequence Introducer)
  • parameter bytes: 任意数量的 0x30-0x3F 范围的字符, 也就是 0-9:;<=>?
  • intermediate bytes: 任意数量的 0x20-0x2F 范围的字符,也就是 !"#$%&'()*+,-./
  • final bytes: 任意数量的 0x40-0x7E 范围的字符,也就是 “@A–Z[]^_`a–z{|}~”
  • private bytes: 包含 <=>? 或 0x70-0x7E 范围(p-z{|}~) 的字符, 各厂商自行定义和使用的
  • 设定多个属性: ; 分隔的单个属性
  • 重置: ESC[0m

而网上其他资料, 以及实际验证, 发现维基百科有遗漏内容, ESC[ (CSI) 之后可以紧跟着 0~0x2F 范围的数字, 例如 n=1 对应到 “字体加粗” 的属性。

3.2 格式的具体情况

n名字含义、作用
0Reset or normal重置所有属性
1Bold or increased intensity字体加粗
2Faint, decresed intensity, or dim字体变暗
3Italic斜体。据说没有被广泛使用
4Underline下划线. 算是扩展, 在 Kitty, VTE, mintty, iTERM2, Konsole 里有效
5Slow blink设定光标闪烁时间在每分钟内小于150次(暂时不会用)
6Rapid blink光标闪烁加速,每分钟内超过150次; 没有被广泛支持
7Reverse video or invert对调背景和前景的颜色
8Conceal or hide没有被广泛的支持,iTerm2 上没有效果
9Crossed-out, or strike让字符带有删除线
10Primary(default) font默认字体
11~19Alternative font选择编号为 n-10 的字体
20Fraktur(Gothic)很少使用。iTerm2 上没有效果
21Doubly underlined; or: not bold双下划线、或者不要加粗
22Normal intensity既不加粗、也不变暗
23Neither italic, nor blackletter既不斜体, 也不黑色字母
24Not underlined不要有单个下划线, 也不要有双下划线
25Not blinking不要闪烁光标
26Proportional spacing终端上没有在使用
27Not reservediTerm2 上没有效果
28Reveal不要"隐瞒"
29Not crossed out去掉“删除线"
30-37Set foreground color设置前景颜色
30Black 黑色前景
31Red 红色前景
32Green 绿色前景
33Yellow 黄色前景
34Blue 蓝色前景
35Magenta 紫色前景
36Cyan 靛蓝色前景
37White 白色前景
38Set foreground color设置前景颜色, 接下来的参数是 5;n2;r;g;b
39Default foreground color默认前景颜色
40-47设置背景颜色
40Black 黑色背景
41Red 红色背景
42Green 绿色背景
43Yellow 黄色背景
44Blue 蓝色背景
45Magenta 紫色背景
46Cyan 靛蓝色背景
47White 白色背景
48Set background color设置前景颜色, 接下来的参数是 5;n2;r;g;b
49默认背景颜色
50Disable proportional spacing禁用等比例空格
51Framedmintty 中被实现为 emoji 选择器(?)
52Encircled同上
53Overlinked没效果
54Neither framed nor encircled
55Not overlined
58Set underline color设置下划线颜色。不是标准规定的。Kitty, VTE, iTerm2里有实现;下一个参数需要是 5;n2;r;g;b 形式
59Default underline color默认下划线颜色. 非标准。在 Kitty, VTE, iTerm2里有实现
60~65通常没有实现
73-74Superscript, Subscript上标和下标。只在 mintty 里有实现
75-76Neither superscript nor subscript取消上标和下标
90-97Set bright foreground color设置前景颜色亮度。非标准. iTerm2里有效
90Bright Black亮黑色前景色
91Bright Red亮红色前景色
92Bright Green亮绿色前景色
93Bright Yellow亮黄色前景色
94Bright Blue亮蓝色前景色
95Bright Magenta亮紫色前景色
96Bright Cyan亮靛蓝色前景色
97Bright White亮白色前景色
100-107Set bright background color背景颜色亮度. iTerm2里有效
100Bright Black亮黑色背景色
101Bright Red亮红色背景色
102Bright Green亮绿色背景色
103Bright Yellow亮黄色背景色
104Bright Blue亮蓝色背景色
105Bright Magenta亮紫色背景色
106Bright Cyan亮靛蓝色背景色
107Bright White亮白色背景色

其中 n 为 38 是设置前景颜色 ESC[38;5;{ID}m, n 为 48 是设置背景颜色 ESC[48;5;{ID}m, ID 是具体的颜色, 见下图:

在这里插入图片描述

3.3 常见私有模式 (Common Private Modes)

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797

ESC 代码序列描述
ESC[?25l]隐藏光标
ESC[?25h]显示光标
ESC[?47l]恢复屏幕
ESC[?47h]保存屏幕
ESC[?1049h]启用可选buffer
ESC[?1049l]禁用可选bufer

3.4 控制光标

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#cursor-controls

ESC 代码序列描述
ESC[H光标移动到 (0, 0) 位置
ESC[#A光标向上移动 #
ESC[#B光标向下移动 #

3.5 擦除功能 (Erase Functions)

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#erase-functions

ESC CodeDescription
ESC[J清除光标位置到屏幕结束位置
ESC[0JESC[J
ESC[1J清除光标位置到屏幕开始
ESC[2J清除整个屏幕
ESC[3J清除保存的行
ESC[K清除当前光标位置到当前行末尾
ESC[0KESC[K
ESC[1K删除当前光标位置到当前行首
ESC[2K删除整行

4. 简单例子

在这里插入图片描述

#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <numeric>int main()
{std::vector<int> codes = {1, 2, 3, 4, 7, 8, 9};std::generate_n(std::back_inserter(codes), 8, [n = 30]() mutable { return n++; });std::generate_n(std::back_inserter(codes), 8, [n = 40]() mutable { return n++; });std::generate_n(std::back_inserter(codes), 8, [n = 90]() mutable { return n++; });std::generate_n(std::back_inserter(codes), 8, [n = 100]() mutable { return n++; });for (const auto code : codes){printf("\e[%dmHello\e[mworld  (n=%d)\n", code, code);}printf("\e[1;34mHello\e[0mworld  (n=1;34)\n");printf("\e[38;5;2mHello\e[0mworld  (n=38;5;2)\n");printf("\e[48;5;2mHello\e[0mworld  (n=48;5;2)\n");return 0;
}

5. 复杂例子 - 方块下落

绘制最小的绿色矩形: 打印“空格” 字符, 并且让空格字符的前景颜色红色的:

printf("\e[42m \e[0m\n"); 

绘制较大的红色矩形: 每一行打印多个空格, 连续打印多行; 每一行打印时使用转义字符。

printf("\e[42m    \e[0m\n"); 

绘制会下落的红色矩形框: 先绘制一个,长度持续增加的。

void draw_box()
{for (int i = 0; i < 10; i++){printf("\e[42m    \e[0m\n");std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}

通过 ANSI Escape Sequence, 修改光标位置, 然后再绘制矩形:

void draw_box2()
{printf("\e[H");     // 光标移动到 (0,0) 位置printf("\e[42m    \e[0m"); // 绘制绿色背景的空格printf("\e[1B");  // 光标往下一行。 注意此时 column 方向上, 光标不是在0位置printf("\e[43m    \e[0m"); // 绘制黄色背景的空格
}

让每一行的绘制, 都从第 6 列开始绘制, 并且每次绘制后, 等待 100 毫秒:

void draw_box6()
{printf("\e[?25l"); // 隐藏光标, 避免光标导致的白色小方框for (int i = 0; i < 10; i++){printf("\e[2J");    // 清空整个屏幕printf("\x1b[%d;%dH\e[0m", i, 6); // 光标一定到第i 行,第 6 列printf("\e[42m    \e[0m"); // 绘制绿色矩形: 也就是绘制绿色背景的空格fflush(stdout); // 确保绘制到控制台std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 暂停 500 毫秒,营造下落的视觉效果}printf("\e[?25h"); // 恢复光标的可见性
}

在这里插入图片描述

6. ANSI Escape 的局限

无法绘制圆形。 因为终端绘制的最小单位, 是单个字符,每个字符通常是竖条而不是正方形, 并且竖条比较大, 大于通常看到的图像像素。 这就导致, 稍微复杂的图形无法绘制, 需要选择其他的方案:

  • 使用 opencv 的 Mat 绘制, 用 imshow 显示
  • 使用 SFML / SDL / Dear imgui / Qt 绘制和显示

7. References

  • 手把手教你写俄罗斯方块:2-如何在终端上绘图
  • ANSI Escape Codes
  • C语言实现 log 库

这篇关于ANSI Escape Sequence 下落的方块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/696261

相关文章

C++实现俄罗斯方块(Windows控制台版)

C++实现俄罗斯方块(Windows控制台版) 在油管上看到一个使用C++控制台编写的俄罗斯方块小游戏,源代码200多行,B站上也有相关的讲解视频,非常不错,值得学习。 B站讲解视频地址为:【百万好评】国外技术大神C++游戏编程实战教程,油管580W收藏,新手10小时入门,并快速达到游戏开发能力(中英字幕) B站 CSDN博主千帐灯无此声还为此写了一篇博客:C++实现俄罗斯方块(源码+详解),讲

浙大数据结构:02-线性结构4 Pop Sequence

这道题我们采用数组来模拟堆栈和队列。 简单说一下大致思路,我们用栈来存1234.....,队列来存输入的一组数据,栈与队列进行匹配,相同就pop 机翻 1、条件准备 stk是栈,que是队列。 tt指向的是栈中下标,front指向队头,rear指向队尾。 初始化栈顶为0,队头为0,队尾为-1 #include<iostream>using namespace std;#defi

【UVA】1626-Brackets sequence(动态规划)

一道算是比较难理解的动规。 状态转移分2个: (用d[i][j]表示在i~j内最少需要添加几个括号,保持平衡) 1.如果s[i]和s[j]是一对括号,那么d[i][j] = d[i + 1][j - 1] 2.否则的话 d[i][j] = min(d[i][k],[k + 1][j]); 边界是d[i + 1][i] = 0; d[i][i] = 1; 13993644 162

【UVA】10534 - Wavio Sequence(LIS最长上升子序列)

这题一看10000的数据量就知道必须用nlog(n)的时间复杂度。 所以特意去看了最长上升子序列的nlog(n)的算法。 如果有2个位置,该位置上的元素为A[i]和A[j],并且他们满足以下条件: 1.dp[i] = dp[j]    (dp[x]代表以x结尾的最长上升子序列长度) 2.A[i] < A[j] 3.i < j 那么毫无疑问,选择dp[i] 一定优于选择dp[j] 那么

2015年多校联合训练第一场OO’s Sequence(hdu5288)

题意:给定一个长度为n的序列,规定f(l,r)是对于l,r范围内的某个数字a[i],都不能找到一个对应的j使得a[i]%a[j]=0,那么l,r内有多少个i,f(l,r)就是几。问所有f(l,r)的总和是多少。 公式中给出的区间,也就是所有存在的区间。 思路:直接枚举每一个数字,对于这个数字,如果这个数字是合法的i,那么向左能扩展的最大长度是多少,向右能扩展的最大长度是多少,那么i为合法的情况

【自用14】C++俄罗斯方块-思路复盘

1.编写主函数 int main(void){welcome();//欢迎函数system("pause");//窗口停留colsegraph();//关闭图画return 0;//返回值} 其中包含有最开始的欢迎,以及基础的窗口停留、图画关闭和返回值语句 2.编写欢迎函数 需求: 欢迎函数中需要包含的功能 设置游戏窗口的大小 设置游戏窗口的颜色 设置游戏窗口需要显示的文字的字

NYOJ 763 Vawio Sequence

OJ题目 : 戳这里~ 描述 Vawio Sequence is very funny,it is a sequence of integers. It has some interesting properties. ·   Vawio is of odd length i.e. L = 2*n + 1. ·  The first (n+1) integers of  Vawio s

python中使用FormatDataLibsvm转为txt文件后报错illegal multibyte sequence

‘gbk’ codec can’t decode byte 0xff in position 0: illegal multibyte sequence 这个报错是因为编码不对,正确的编码是ANSI编码,txt文件打开后另存为可以看到当前的文本文档编码 但是excel不能直接保存ANSI编码的txt文件 所以不能直接保存为ANSI编码 有两种解决办法 1.新建一个txt文件(新建的txt文件

【14.1运行版】C++俄罗斯方块-实现欢迎界面

实现欢迎界面 #include <stdio.h>//C语言形式的输入输出#include <graphics.h>//图形库的头文件//实现欢迎界面void welcome(void);int main(void) {welcome();//colsegraph();return 0;}void welcome(void) {//初始化画布initgraph(550, 660);//设置

[LeetCode] 128. Longest Consecutive Sequence

题:https://leetcode.com/problems/longest-consecutive-sequence/description/ 题目 Given an unsorted array of integers, find the length of the longest consecutive elements sequence. Your algorithm should