続、コンソールでリズムゲーム
先日書いたプログラムについて、あるお方から「termiosを使えば出来そうですね」と助言がありました。へぇ、ターミナルの調整とかこんな機能があったんですか。簡単そうだし早速コレ(termios)を使って実装してみましょう。
以下、改良版ソースコード
// コンソールだけでリズムゲーみたいなの作れるか // ncursesで組む前に検証 #include#include #include #include // 1コマ辺りのミリ秒 #define TIME_BAR_ONE 50 // バー全体のマス数 #define TIME_BAR 20 // 当たり判定を許すミリ秒 #define TIME_DIV1 40 //#define TIME_DIV2 30 //#define TIME_DIV3 20 //#define TIME_DIV4 10 // コードデータ構造体 typedef struct{ unsigned long time; int key; }code_t; // コードデータ実体とその長さ code_t code_line = {{5000, 0},{7000, 0},{8000, 0},{9000, 0},{10000, 0},{11000, 0}}; int code_line_len; // 現在のコード位置 int now_code; // プログラム開始時間と現在時間 unsigned long start_time, now_time; int score;// 現在の得点 unsigned int hit_f;// ヒット状態(0で何もない、1で失敗、2で) // ターミナルの状態 struct termios save_term; struct termios temp_term; unsigned long getmilisec(void) { struct timeb sec; ftime(&sec); return ((unsigned long)sec.time*1000) + sec.millitm;// バグ過ぎる } int init(void) { // ターミナルのセーブ tcgetattr(fileno(stdin), &save_term); // 端末設定、非カノニカルモード、readでブロックしないように、エコーも無し temp_term = save_term; temp_term.c_lflag &= ~ICANON; temp_term.c_lflag &= ~ISIG; temp_term.c_lflag &= ~ECHO; temp_term.c_cc[VMIN] = 0; temp_term.c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSANOW, &temp_term); // コードデータ読み込み code_line_len=6; now_code = 0; start_time = now_time = getmilisec();// 開始時刻の読み込み score = 1000;// スコアを初期化する return 0; } int display(void) { int disp_code; int i; putc('\r', stdout); printf("[score:%8d] ", score); if (hit_f & 0x00000001){ putc('-', stdout); } else { putc(' ', stdout); } if (hit_f & 0x00000002){ putc('x', stdout); } else { putc('#', stdout); } // 50ミリ秒単位で' 'を入れてみよう disp_code = now_code; for(i=0; i = code_line_len){ putc(' ', stdout); }else{ if ((((now_time-start_time)+i*TIME_BAR_ONE)-code_line[disp_code].time) < TIME_BAR_ONE){ putc('o', stdout); disp_code++; }else{ putc(' ', stdout); } } } putc('|', stdout); return 0; } int destroy(void) { // なにもすることがねえ、得点記録とか? putc('\n', stdout); // ターミナルの復元 tcsetattr(fileno(stdin), TCSANOW, &save_term); return 0; } int main(int argc, char *argv ) { char ch; init(); while(1){ hit_f = 0; // 時間を取得 now_time = getmilisec(); // 制限時間を越えてしまったコードは読み飛ばす for(; now_code=code_line_len) break; // 全コード読んだ // コンソールだとsleepしてられない // usleep(100); // 少しスリープする } destroy(); return 0; }
おお出来ました。確かにread(fgetc)のブロッキングがしない。コレは面白い関数を教えてもらいました^−^
〜〜〜
感動して数回実行してみる
〜〜〜
・・・どうでもいいけどEnter押しっぱなしが高得点出せるってどんなチートなのよ(こんなコードじゃ仕方ないけど)