美文网首页
sl小火车开源项目分析

sl小火车开源项目分析

作者: 知止乎尔 | 来源:发表于2018-08-06 21:43 被阅读0次

今天心情不错分析下这个玩具! sl比较有趣,当手快按错文件查看命令顺序时,我经常会被突然跑出来的小火车给逗乐。给我个sl我可以玩一天。我们接下来就看看这个开源小玩意是怎么做的。

项目地址: https://github.com/mtoyoda/sl
作者:Toyoda Masashi (mtoyoda@acm.org)

SL (Steam Locomotive)是一个基于终端运行的小工具。当你想输入ls时,却误输入成sl,就会运行。只是一个玩笑,然并没什么卵用 --Toyoda Masashi(作者)。

安装(以Ubuntu为例):

  apt install sl

让我们看看运行效果:


sltrain.gif

这是一个C语言开发的小工程,那么我们从哪里开始呢?
按照正常的分析流程,我们应该做的是:

  • 找到文件的依赖关系
  • 从程序入口(main)开始分析

1.明确文件依赖关系

为了找到明确的依赖关系,让我们先看看这个工程的makefile:

CC=gcc
CFLAGS=-O -Wall

all: sl

sl: sl.c sl.h
    $(CC) $(CFLAGS) -o sl sl.c -lncurses

clean:
    rm -f sl

distclean: clean

这个makefile非常简单(不熟悉makefile语法的同学自行补脑推荐陈浩老师的教程下载-【跟我一起写Makefile-陈皓】
只有两个文件sl.c 和 sl.h,并且依赖于ncurses库,这个库中提供了字符终端处理的一些方法。

内容如此简单,我们继续看,在看程序入口之前,我们先看看这个sl.h文件里面是什么东西❓
竟然是满脸的小火车零件...
∩_∩哈!原来这个神奇了小火车就是,这些定义的宏(火车零件),组装出来的!

贴出来看看:

/* 火车神兽头 */
#define LOGO1  "     ++      +------ "
#define LOGO2  "     ||      |+-+ |  "
#define LOGO3  "   /---------|| | |  "
#define LOGO4  "  + ========  +-+ |  "
#define LWHL11 " _|--O========O~\\-+ "
#define LWHL12 "//// \\_/      \\_/  "

2.分析主程序入口

nt main(int argc, char *argv[])
{
    int x, i;

    for (i = 1; i < argc; ++i) {
        if (*argv[i] == '-') {
            option(argv[i] + 1);
        }
    }
    initscr(); /*curses模式初始化方法*/
    signal(SIGINT, SIG_IGN); /*忽略键盘中断*/
    noecho(); /*关闭字符回显*/
    curs_set(0); /*设置光标不可见  0 不可见;1 普通模式;2 可见*/
    nodelay(stdscr, TRUE); /*终端设置为非阻塞式*/
    leaveok(stdscr, TRUE); /*不使用光标,节省移动光标的时间*/
    scrollok(stdscr, FALSE); /*不允许窗口滚屏*/

    for (x = COLS - 1; ; --x) {
        if (LOGO == 1) {
            if (add_sl(x) == ERR) break;
        }
        else if (C51 == 1) {
            if (add_C51(x) == ERR) break;
        }
        else {
            if (add_D51(x) == ERR) break;
        }
        getch();
        refresh();
        usleep(40000);
    }
    mvcur(0, COLS - 1, LINES - 1, 0);
    endwin();

    return 0;
}

我们一行行的看,5 - 9行是个for循环,从这个option方法中可以看出,是为了接收不同的参数时,进行不同的响应。有4种小火车图案,分别对应-a-F-l-c四种参数。10 - 16行设置初始化状态,包括了光标滚动和中断状态等。那18行的COLS是个什么👻?不用找了这个是终端中的一个常量,表示行宽,字符数。那行高是什么❓是的,没错就是32行的LINES。 18 - 33行就是将字符串显示到终端中。并且40ms刷新一次。

作者写了这几个方法来分别写不同样式,和不同的组件,这里不展开,方法类似,逻辑相同。

    void add_smoke(int y, int x);  /*火车上的烟*/
    void add_man(int y, int x); /*这是火车中呼救的小人*/
    int add_C51(int x);
    int add_D51(int x);  /*不同样式*/
    int add_sl(int x);

最终调用的写字符的方法是这样的,是经过组装过的mvaddch(int, int, char *)方法。


int my_mvaddstr(int y, int x, char *str)
{
    for ( ; x < 0; ++x, ++str)
        if (*str == '\0')  return ERR;
    for ( ; *str != '\0'; ++str, ++x)
        if (mvaddch(y, x, *str) == ERR)  return ERR;
    return OK;
}

这位作者的语法不是很规范(不推荐的哈),不过思路还是很清晰,先校验,然后逐个遍历对应位置显示。

是不是很简单,逻辑确实很简单,复杂的是字符位置计算。当然作者没有在字符中加任何特效,感兴趣的同学可以看看ncurses这个类的用法,可以增加颜色、闪烁等一些特效。还记得当初看见一个在终端中显示初音舞蹈的视频,大概也是这种实现思路吧。笔者抽空在终端中写了汉诺塔和贪吃蛇小游戏。欢迎大家交流探讨。

相关文章

网友评论

      本文标题:sl小火车开源项目分析

      本文链接:https://www.haomeiwen.com/subject/oxknvftx.html