10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

こそぷろ(子育てプロトタイピング) #protooutAdvent Calendar 2023

Day 23

2歳むすめちゃんお気に入りのslコマンド!これのアンパンマンバージョン、その名も"anp"コマンドを作ればむすめちゃん大喜びなのでは...?!!

Posted at

はい、タイトルの通りですね!
というわけでslコマンドのアンパンマンバージョン、その名もanpコマンドを作っていきます~~!

SLコマンドって?

言わずと知れたlinuxジョークコマンド。

slと入力すると汽車ぽっぽ(国鉄D51形蒸気機関車)が走ります。エンジニアの子供が叩かされがちなコマンドです。
https://ja.wikipedia.org/wiki/Sl_(UNIX)

sl.gif

Macでしたらbrewで入りますので、ぜひbrew install slして試してみてください!

ちなみにこんなオプションが指定できたりします。

オプション 内容
a 乗客?がHELP
l 汽車が細くなる
F 汽車が飛んでいく
c C51系機関車になる

どんな感じの実装か

コードを読んでみる。

こんな感じっぽいです。

  1. 画面をクリアする
  2. 出力する空白を増やして移動してるように見せる
  3. アニメーションは行ごとに文字列化
  4. アニメーションつけるなら複数のアスキーアートを組み合わせて交互に表示
  5. 表示切り替え時にsleepさせてアニメーション感を出す
  6. キーボード入力無視の設定

とりあえずやってみましょう。

手始めに文字をちょっと移動させる

C言語はもう忘れてしまったので、うろ覚えのC++で書いてみましょう。

#include <iostream>
#include <thread>
#include <chrono>
#include <sys/ioctl.h>
#include <unistd.h>
using namespace std;

int getScreenWidth() {
    struct winsize w;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);

    return w.ws_col;
}

int main() {
    const int width = getScreenWidth();
    const string anpan = "anpanman"; 

    for (int i = width; i >= 0; i--) {
        system("clear");
        for (int j = 0; j < i; j++) {
            cout << " ";
        }
        if (i < anpan.length()) {
            cout << anpan.substr(anpan.length() - i, i) << endl;
        } else if (i > width - anpan.length()) {
            cout << anpan.substr(0, width - i) << endl;
        } else {
            cout << anpan << endl;
        }
        this_thread::sleep_for(chrono::milliseconds(100));
    }
    return 0;
}

これでこんな感じになる。

firstanp.gif

ふむふむ、なんかいけそうな気がしてきた!

アンパンマンのアスキーアートを動かそう!

空を飛んでるアンパンマンが右から左に飛んでいくような感じにしたいな〜と思っていい感じの画像やAAがないか探してたら、AAHUBでドンピシャなやつを見つけました!

早速このAAを文字列化しようとしたのですが...

あわわ...なんか大変なことに...これめんどくさいやつ...。

ということで難易度を急激に下げてこちらのAAを右から左に移動させてみましょう。

こんな感じになりました。
多少のアニメーションとしてちょっと上下させたり表示を変えたりしてみました...

anp.gif

ビルドプロセスの整理

むすめちゃんが叩きやすいように、バイナリを./anpと実行するのではなく、バイナリをパスの通ったディレクトリに置いてanpコマンドとして実行する感じにしようと思います。

Linucサイトによると自作プログラムは/usr/local/binに置くのがいいらしいので、バイナリを/usr/local/binにコピーするMakefileを書いておきましょう。

「/usr/local/bin」には、「シングルユーザモードで利用しない」かつ「RPMやdebなどのパッケージ管理システムによってシステムに管理されないコマンドやプログラム」が置かれることになります。自作のスクリプトなどはこのディレクトリに置くことが一般的です。

Makefile

# Makefile
CC=g++
CFLAGS=-Wall
TARGET=amp
DESTDIR=/usr/local/bin

all: $(TARGET)

$(TARGET): $(TARGET).cpp
	$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).cpp

install:
	cp $(TARGET) $(DESTDIR)/$(TARGET)

clean:
	rm -f $(TARGET)

むすめちゃん、大喜びなるか...?!!

original_477267ed-c731-4e7b-9f64-3c87dec6f896_PXL_20231223_071123810.MP~2.jpg

アンパンマンとか何も言わずにコマンドを初披露したところ、「アンパンマンだー!」と認識してくれました...!!

やったね!

感想など

時間不足(言い訳)でアンパンマンのクオリティがイマイチになってしまいましたが、むすめちゃんがそこそこ喜んでくれてよかったです。
アスキーアート難しい、アニメーションも難しい...

ゆるい内容でしたが最後まで読んでくださりありがとうございました!

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?