969 字
5 分钟
可爱猫咪认萝卜:C++ 字符画动画实现
最近网上有一只非常可爱的猫咪火遍全网,它的主人试着教它分辨萝卜和纸巾,但猫咪贼眉鼠眼瞎猜的样子实在是有点可爱。在网上看到了各种有趣的二创作品,我也心血来潮,尝试用 C++ 编写了一个简单的字符画动画来复刻这个场景。
效果演示视频:点这里跳转
这段代码实现了猫咪伸爪、收爪以及开心晃脑袋的动画效果。虽然逻辑比较简单,但作为字符画动画入门还是挺有意思的。有兴趣的小伙伴可以尝试运行一下,或者在此基础上拓展成一个小游戏!
#include <iostream>#include <string>#include <vector>#include <thread>#include <chrono>
using namespace std;
// 毫秒延迟函数,封装 thread 和 chrono 以简化调用void sleep_ms(int ms) { this_thread::sleep_for(chrono::milliseconds(ms));}
// 清除终端屏幕并重置光标位置void clear_screen() {// cout << "\033[2J\033[1;1H"; cout << "\033[1;1H\033[0J"; cout.flush();}
// 猫咪头部样式const string cat_base_normal = R"( /\_/\ ( o.o ) / \ /| | | |\)";
const string cat_base_wide_eyes = R"( /\_/\ ( O.O ) / ^ \ /| | | |\)";
// 开心状态下的头部帧(带偏移感)const vector<string> cat_happy_heads = { R"( /\_/\ ( ^.^ ) / \ /| | | |\)", R"( /\_/\ ( ^.^ ) / \ /| | | |\)", R"( /\_/\ ( ^.^ ) / \ /| | | |\)"};
// 坐着时的下半部分(带小尾巴摇晃感)const vector<string> sitting_paw_frames = { " (_| |_| |_)\n (_) (_)\n\n\n", " (_| |_| |_)\n (_) (_) ~\n\n\n", " (_| |_| |_)\n ~ (_) (_)\n\n\n"};
// 纸巾盒和萝卜的详细字符画变化的下半部分帧const vector<string> right_paw_frames = { " (_| |_| |_)\n (_) (_)\n\n\n", " (_| |_\\ \\_)\n (_) \\ \\\n (_)\n\n",};
const vector<string> left_paw_frames = { " (_| |_| |_)\n (_) (_)\n\n\n", " (_/ /_| |_)\n / / (_)\n (_)\n\n", " (_/ /_| |_)\n / / (_)\n / /\n (_)\n"};
const vector<string> left2right_paw_frames = { " (_| |_| |_)\n (_) (_)\n\n\n", " (__\\ \\|_|_)\n \\ \\_)\n (_)\n\n", " (__\\ \\|_|_)\n \\ \\_)\n \\ \\\n (_)\n",};
const vector<string> right2left_paw_frames = { " (_| |_| |_)\n (_) (_)\n\n\n", " (_| |/ /__)\n (_/ /\n (_)\n\n", " (_| |/ /__)\n (_/ /\n / /\n (_)\n"};
// 纸巾盒和萝卜的详细字符画const string items =" _____ \\ | /\n"" |_---_| ( )\n"" |_____| V\n";
void play_frame(int i, const vector<string>& paw_frames, bool wide_eyes = false) { clear_screen(); const string& head = wide_eyes ? cat_base_wide_eyes : cat_base_normal; cout << head << paw_frames[i]; cout << items << endl; sleep_ms(200);}
// 动画函数:猫咪开心地左右晃脑袋void animate_happy(int repeats = 3) { for (int r = 0; r < repeats; ++r) { // 序列:中 -> 右 -> 中 -> 左 int sequence[] = {0, 1, 0, 2}; for (int idx : sequence) { clear_screen(); cout << cat_happy_heads[idx]; // 晃脑袋时,脚部也配合摇摇尾巴 cout << sitting_paw_frames[idx == 0 ? 0 : (idx == 1 ? 1 : 2)]; cout << items << endl; sleep_ms(100); // 晃动快一点显得更兴奋 } } // 动画结束后,强制回到原位并恢复正常表情 clear_screen(); cout << cat_base_normal; cout << sitting_paw_frames[0]; cout << items << endl;}
// 动画函数:让猫咪伸出或收回左爪void animate_paw(bool extend, const vector<string>& paw_frames, bool wide_eyes_at_end = false) {
if (extend) { for (size_t i = 0; i < paw_frames.size(); ++i) { if (wide_eyes_at_end && i == paw_frames.size() - 1) { // 最后一帧:先保持正常眼睛样式 play_frame(i, paw_frames, false); // 稍微等待一小会(例如 300 毫秒),表现出“反应时间” sleep_ms(300); // 然后再睁大眼睛 play_frame(i, paw_frames, true); } else { play_frame(i, paw_frames, false); } } } else { for (int i = paw_frames.size() - 1; i >= 0; --i) { // 收回时如果从最后一帧开始,也要考虑眼睛是否处于睁大状态 bool current_eyes = (wide_eyes_at_end && i == (int)paw_frames.size() - 1); play_frame(i, paw_frames, current_eyes); } }}
int main() { // 等待 500 毫秒 sleep_ms(500);
// 向左伸出左爪(第一个参数改为 false 则为收爪) animate_paw(true, left_paw_frames, true); // 向右伸出左爪 animate_paw(true, left2right_paw_frames, true); // 向左伸出右爪 animate_paw(true, right_paw_frames, true); // 向右伸出右爪 animate_paw(true, right2left_paw_frames, true);
// 等待 500 毫秒 sleep_ms(500);
// 开心 animate_happy();
return 0;}希望这只“乱猜”的猫咪也能给你带来一点快乐!
可爱猫咪认萝卜:C++ 字符画动画实现
https://yezi.press/posts/nice_cat/
陕公网安备61010302001363号