0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ボカロオタクが聖夜に「Calc.」のプロンプト画面を再現して大満足するだけの話

Last updated at Posted at 2023-12-24

この記事は SLP-KBIT AdventCalendar2023 24日目の記事です。

はじめに

merry_christmas.png

merry_christmas_santa.png

merry_christmas_cake.jpg

こんばんわ。tttです。

メリークリスマス!!!!

今夜はクリスマスイブですね。
みなさん、いかがお過ごしでしょうか。

大切な家族や友人と過ごしたり、はたまた恋人と共に過ごす方もいらっしゃるでしょう。

中には「一人ぼっちのクリスマスイブでも問題ないし」と考えてる方もいると思います。

しかし、それは良くありません!

クリスマスイブは、「家族や友人、恋人との団らんの時間を大切にする時間である」(ネット検索)とされているように、決して一人で過ごす時間ではないのです!!

クリぼっちで問題ない!と考えている人も、心の底では寂しい思いを少なからずしているはずです。

さあ、今すぐ大切な人に会いに行きましょう!!

みなさんのクリスマスイブが、とても良い思い出になることを願っています。







え、僕?
ハハっ

序章

僕の大好きなボカロ曲です(唐突)。

何度聴いても素晴らしい!!

ココスキポイント
ベースが好き、コード進行が好き、シンプルな音楽構成が好き、歌詞が好き、間奏のギター好き、こんだけ爽やかな音楽のくせに「失恋ソング」なのが好き、こんだけ爽やかな音楽なのにMVが真っ黒な画面に緑コンソール文字だけっていうギャップが好き、タイトルが好き、以前の曲とつながってるのが好き、etc

考察も語りたいところですが、それだけで一つの記事になりそうなので割愛。
一応、他人の考察の中で納得したものもあるので、興味あればどぞ。

ほんへ

で。
情報学生の方なら以下の画像を見て思うことはないだろうか。

calc.jpg

そうです。

この画面をターミナル上で再現したい!!!!

ですよね。

やりましょう。

文字列の解読?
したけりゃ勝手にドウゾ
ちなみに平文に直すとミクがうp主を罵倒するメッセージが現れます
CTF経験者は自力で解けるかな?

Step1.まずは普通に出力

どう出力しようかなぁと考えたとき、Cプログラムとして実行するのが面白そうだなと思ったので、プログラミングします。

とは言っても、文字を出力するだけのプログラムですけどね。

大きい文字の「Calc.」はもちろん工夫します。

#include <stdio.h>

int main(void)
{
    putchar('\n');
    puts("Initializing...");
    putchar('\n');
    puts("837E834E81755982B382F182CC82B182C682CD");
    puts("82E082A4965982EA82BD82D982A482AA");
    puts("82A282A282C68E7682A282DC82B78176...");
    putchar('\n');
    puts("838B834A8175918A95CF82ED82E782B8");
    puts("96A297FB82AA82DC82B582A282C88176...");
    putchar('\n');
    puts("8357837E817592FA82DF82AA88AB82A282E68176...");
    putchar('\n');
    putchar('\n');
    puts(" ■■■       ■");
    puts("■   ■  ■■  ■  ■■■");
    puts("■        ■ ■ ■");
    puts("■      ■■■ ■ ■");
    puts("■   ■ ■  ■ ■ ■");
    puts(" ■■■   ■■■ ■  ■■■ ■");
    putchar('\n');
    putchar('\n');
    puts("8357837E815B817581638163");
    puts("28814C8145");
    puts("81CD8145814D29");
    puts("816381638176...");
    putchar('\n');

    return 0;
}

実行結果


Initializing...

837E834E81755982B382F182CC82B182C682CD
82E082A4965982EA82BD82D982A482AA
82A282A282C68E7682A282DC82B78176...

838B834A8175918A95CF82ED82E782B8
96A297FB82AA82DC82B582A282C88176...

8357837E817592FA82DF82AA88AB82A282E68176...


 ■■■       ■
■   ■  ■■  ■  ■■■
■        ■ ■ ■
■      ■■■ ■ ■
■   ■ ■  ■ ■ ■
 ■■■   ■■■ ■  ■■■ ■


8357837E815B817581638163
28814C8145
81CD8145814D29
816381638176...

まあ普通ですね。

Step2.色をつける

MVの文字は、緑色なのでそれに合わせます。

C言語には特殊文字と呼ばれるものが存在します。

ピンと来ない方もいると思いますが、簡単にいうと\n\0などです。

で、文字を緑色にする特殊文字は以下の通りです。

\x1b[32m

長いので説明は省きます。
ファ!?なんだこれ!!と思う方はこちらをどうぞ。

コード

#include <stdio.h>

int main(void)
{
    printf("\x1b[32m");
    putchar('\n');
    puts("Initializing...");
    putchar('\n');
    puts("837E834E81755982B382F182CC82B182C682CD");
    puts("82E082A4965982EA82BD82D982A482AA");
    puts("82A282A282C68E7682A282DC82B78176...");
    putchar('\n');
    puts("838B834A8175918A95CF82ED82E782B8");
    puts("96A297FB82AA82DC82B582A282C88176...");
    putchar('\n');
    puts("8357837E817592FA82DF82AA88AB82A282E68176...");
    putchar('\n');
    putchar('\n');
    puts(" ■■■       ■");
    puts("■   ■  ■■  ■  ■■■");
    puts("■        ■ ■ ■");
    puts("■      ■■■ ■ ■");
    puts("■   ■ ■  ■ ■ ■");
    puts(" ■■■   ■■■ ■  ■■■ ■");
    putchar('\n');
    putchar('\n');
    puts("8357837E815B817581638163");
    puts("28814C8145");
    puts("81CD8145814D29");
    puts("816381638176...");
    putchar('\n');
    printf("\x1b[0m");

    return 0;
}

実行結果

image.png

なんかこれじゃない感。

というのも、大文字の「Calc.」が本家と少し形が異なるんですよねぇ...

ということで工夫します。

Step3.「Calc.」の表記方法を一新

ここ賢いポイント。

「■」という文字を使って「Calc.」を表現しようとしていますが、これが半角判定になり、うまくできません。

ここで、C言語の文字を緑色にする特殊文字に注目します。

「文字を緑色にする」ということは、つまり「空白文字も緑色にする」ということです。

なので、空白文字に緑色が当たるよう調整すれば、いい感じになるはずです。

コード

#include <stdio.h>
int main(void)
{
    printf("\x1b[32m");
    putchar('\n');
    puts("Initializing...");
    putchar('\n');
    puts("837E834E81755982B382F182CC82B182C682CD");
    puts("82E082A4965982EA82BD82D982A482AA");
    puts("82A282A282C68E7682A282DC82B78176...");
    putchar('\n');
    puts("838B834A8175918A95CF82ED82E782B8");
    puts("96A297FB82AA82DC82B582A282C88176...");
    putchar('\n');
    puts("8357837E817592FA82DF82AA88AB82A282E68176...");
    putchar('\n');
    putchar('\n');
    puts("  \x1b[42m      \x1b[49m              \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m      \x1b[42m  \x1b[49m    \x1b[42m    \x1b[49m    \x1b[42m  \x1b[49m    \x1b[42m      \x1b[49m");
    puts("\x1b[42m  \x1b[49m                \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m            \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m      \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m    \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("  \x1b[42m      \x1b[49m      \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m    \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m");
    putchar('\n');
    putchar('\n');
    puts("8357837E815B817581638163");
    puts("28814C8145");
    puts("81CD8145814D29");
    puts("816381638176...");
    putchar('\n');
    printf("\x1b[0m");
    return 0;
}

実行結果

image.png

:)

Step4.アニメーションをつける

当初の目的は達成しましたが、あまり面白みがないので、この画面に動きを付けます。

MVに登場するClacプログラムが実際にどのように動くのか、想像しながら作成していきます。

文字が流れるように表示されていく様子を想像したので、それをプログラムで表現することにしました。

それを実現するために

  • usleep()関数
  • fflush()関数

を使用します。

また、任意の時間によって文字を出力したいので、それを実現する自作関数も用意します。

参考サイト:

ついでに実行時に画面が更新されるようにもします。

コード

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void slowMsg(char* msg, int wait_time)
{
    int i = 0;
    while(msg[i] != '\0')
    {
        printf("%c", msg[i]);
        usleep(wait_time);
        fflush(stdout);
        i++;
    }
}

int main(void)
{
    system("clear");
    printf("\x1b[32m");

    putchar('\n');
    slowMsg("Initializing", 100000);
    slowMsg("... ", 1000000);
    putchar('\n');
    putchar('\n');
    slowMsg("837E834E81755982B382F182CC82B182C682CD\n", 30000);
    slowMsg("82E082A4965982EA82BD82D982A482AA\n", 30000);
    slowMsg("82A282A282C68E7682A282DC82B78176... ", 30000);
    putchar('\n');
    putchar('\n');
    slowMsg("838B834A8175918A95CF82ED82E782B8\n", 30000);
    slowMsg("96A297FB82AA82DC82B582A282C88176... ", 30000);
    putchar('\n');
    putchar('\n');
    slowMsg("8357837E817592FA82DF82AA88AB82A282E68176", 30000);
    slowMsg("... ", 800000);
    putchar('\n');
    putchar('\n');
    putchar('\n');
    puts("  \x1b[42m      \x1b[49m              \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m      \x1b[42m  \x1b[49m    \x1b[42m    \x1b[49m    \x1b[42m  \x1b[49m    \x1b[42m      \x1b[49m");
    puts("\x1b[42m  \x1b[49m                \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m            \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m      \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m    \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("  \x1b[42m      \x1b[49m      \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m    \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m");
    putchar('\n');
    putchar('\n');
    usleep(1000000);
    slowMsg("8357837E815B817581638163\n", 30000);
    slowMsg("28814C8145\n", 30000);
    slowMsg("81CD8145814D29\n", 30000);
    slowMsg("816381638176... ", 30000);
    putchar('\n');
    putchar('\n');
    printf("\x1b[0m");

    return 0;
}

実行結果

[calc_step5.gifhttps://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384147/852b8c34-2460-0917-2c2c-d68de4bb9674.gif

動画をgifに直すと劣化が凄かったのでカット
:(

Step5.音楽と同時に実行する

仕上げです。

音楽も流して盛大にしましょう。

コード

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void slowMsg(char* msg, int wait_time)
{
    int i = 0;
    while(msg[i] != '\0')
    {
        printf("%c", msg[i]);
        usleep(wait_time);
        fflush(stdout);
        i++;
    }
}

void* startMusic(void *arg)
{
    system("mpg123 -q ./music/Calc.mp3");
    return NULL;
}

int main(void)
{
    system("clear");
    printf("\x1b[32m");

    putchar('\n');
    slowMsg("Initializing", 100000);
    slowMsg("...", 800000);
    pthread_t music_thread;
    pthread_create(&music_thread, NULL, startMusic, NULL);
    slowMsg(" ", 500000);
    putchar('\n');
    putchar('\n');

    slowMsg("837E834E81755982B382F182CC82B182C682CD\n", 40000);
    slowMsg("82E082A4965982EA82BD82D982A482AA\n", 40000);
    slowMsg("82A282A282C68E7682A282DC82B78176... ", 40000);
    putchar('\n');
    putchar('\n');
    slowMsg("838B834A8175918A95CF82ED82E782B8\n", 40000);
    slowMsg("96A297FB82AA82DC82B582A282C88176... ", 40000);
    putchar('\n');
    putchar('\n');
    slowMsg("8357837E817592FA82DF82AA88AB82A282E68176", 40000);
    slowMsg("... ", 500000);
    usleep(408000);
    putchar('\n');
    putchar('\n');
    putchar('\n');

    puts("  \x1b[42m      \x1b[49m              \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m      \x1b[42m  \x1b[49m    \x1b[42m    \x1b[49m    \x1b[42m  \x1b[49m    \x1b[42m      \x1b[49m");
    puts("\x1b[42m  \x1b[49m                \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m            \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("\x1b[42m  \x1b[49m      \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m    \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m  \x1b[42m  \x1b[49m");
    puts("  \x1b[42m      \x1b[49m      \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m    \x1b[42m      \x1b[49m  \x1b[42m  \x1b[49m");
    putchar('\n');
    putchar('\n');
    usleep(5000000);
    slowMsg("8357837E815B817581638163\n", 30000);
    slowMsg("28814C8145\n", 30000);
    slowMsg("81CD8145814D29\n", 30000);
    slowMsg("816381638176... ", 30000);
    usleep(3000000);
    putchar('\n');
    putchar('\n');
    putchar('\n');
    slowMsg("すれ違いは結局運命で", 30000);
    usleep(1900000);
    slowMsg("  全ては筋書き通りだって", 30000);
    usleep(1900000);
    putchar('\n');
    slowMsg("悲しみを紛らわせるほど", 30000);
    usleep(1905000);
    slowMsg("  僕は強くないから", 30000);
    usleep(1900000);
    putchar('\n');
    putchar('\n');
    slowMsg("弾き出した答えの全てが", 30000);
    usleep(1850000);
    slowMsg("  一つ二つ犠牲を伴って", 30000);
    usleep(1840000);
    putchar('\n');
    slowMsg("また一歩踏み出す勇気を", 30000);
    usleep(1800000);
    slowMsg("  奪い取ってゆく", 30000);
    usleep(1500000);
    putchar('\n');
    putchar('\n');
    putchar('\n');
    slowMsg("いつか", 95000);
    usleep(470000);
    slowMsg("君に捧げた歌", 30000);
    slowMsg("  ", 1830000);
    slowMsg("今じゃ哀しいだけの愛の歌", 30000);
    usleep(5000000);
    putchar('\n');
    slowMsg("風に吹かれ飛んでゆけ", 30000);
    usleep(4000000);
    slowMsg("  僕らが出会えたあの夏の日まで", 30000);

    usleep(12000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');

    slowMsg("巡り会いも結局運命で", 30000);
    usleep(1900000);
    slowMsg("  全ては筋書き通りだって", 30000);
    usleep(1900000);
    putchar('\n');
    slowMsg("都合良く考えられたら", 30000);
    usleep(1905000);
    slowMsg("  寂しくはないのかな", 30000);
    usleep(1900000);
    putchar('\n');
    putchar('\n');
    slowMsg("弾き出した答えの全てが", 30000);
    usleep(1850000);
    slowMsg("  一つ二つ矛盾を伴って", 30000);
    usleep(1840000);
    putchar('\n');
    slowMsg("向こう側へと続く道を", 30000);
    usleep(1800000);
    slowMsg("  消し去ってゆく", 30000);
    usleep(1400000);
    putchar('\n');
    putchar('\n');
    putchar('\n');
    slowMsg("いつか", 95000);
    usleep(470000);
    slowMsg("君に捧げた歌", 30000);
    slowMsg("  ", 1830000);
    slowMsg("今じゃ哀しいだけの愛の歌", 30000);
    usleep(5000000);
    putchar('\n');
    slowMsg("風に吹かれ飛んでゆけ", 30000);
    usleep(4000000);
    slowMsg("  僕らが出会えたあの夏の日まで", 30000);

    usleep(12000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');

    slowMsg("過去も未来も無くなれば", 30000);
    slowMsg("  ", 1900000);
    slowMsg("僕も自由に飛び立てるかな", 30000);
    usleep(5000000);
    putchar('\n');
    slowMsg("感情一つ消せるのなら", 30000);
    usleep(4000000);
    slowMsg("  「好き」を消せば楽になれるかな", 30000);
    usleep(4900000);
    putchar('\n');
    putchar('\n');

    slowMsg("君の耳を、目を、心を", 30000);
    slowMsg("  ", 2000000);
    slowMsg("通り抜けたモノ全てを", 30000);
    usleep(5000000);
    putchar('\n');
    slowMsg("いつか知ることが出来たら", 30000);
    usleep(4500000);
    slowMsg("  次はちゃんと君を愛せるかな", 30000);

    usleep(12000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');
    usleep(3000000);
    putchar('\n');

    puts("Music : OneRoom");
    puts("Created by ttt");
    puts("2023/12/24");

    putchar('\n');
    putchar('\n');

    printf("\x1b[0m");
    pthread_join(music_thread, NULL);
    return 0;
}

実行結果

おわりに

余は大変満足である。

あとカラオケ行きたくなった。

では良いお年を~~~ノシ

0
0
4

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?