[C言語]初学者がタイミングゲームを作成してみた

初めての方は初めまして、増田デラックスと申します。
C言語で初めてプログラミングを開始し、二か月が経ちました。
ある程度慣れて来たのでゲーム作成をこそこそと続けておりましたが、youtube等の動画サイトでよく見かける「タイミングゲーム」の様なものがC言語でも作成できないか?と思い、今回作成してみました。

初学者故にコードにおいて最適化が出来ていない場合や書き方に誤りがあるかもしれませんが、宜しくお願い致します。


1.概要説明

タイミングゲームとは一体なんなのか?という点から軽くご紹介させて頂きます。
動画を見て頂けると話が早いので以下の動画の1:30秒地点までをご覧下さい。


…といったように画面に表示された指標を基にユーザに入力をさせ、そのタイミングによって成功の可否を判断する。
といった内容になってます。

こちらのゲームをc言語上を用いてVisualStudioCord上で動作する様に作成してみました。

以下にゲーム画面の動画を張っておきますのでまずはこちらをご覧ください。


2.コード

お次に実際のコードをご覧ください。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <conio.h>


//ディレイ処理関数
void delay(int milliseconds) {

    clock_t start_time = clock();
    while (clock() < start_time + milliseconds);

}

//入力ストップ用関数
void stop (void){

    char c = 0;//キーボード管理用

    for(;;){

        if(kbhit()){
            c = getch();
            break;
        }
    }
}


//タイミングゲーム処理関数
int timing (int round){

     ((unsigned)time(NULL));

    int i , k;      //for文内で使用 座標用
    int dec;            //decide タイミング保存用
    int point = 0;      //保存したdecを点数に変換する用
    int end = 0;       //終了管理用
    char charkey = 0;   //キーボード管理用
    int delaytime = rand()%80 + 10; //1コマあたりの時間(ミリ秒)
                                    //今回は乱数を使用していますが、固定時間を指定することももちろん可能です
    

    printf("===========止めるにはsキーを入力してね!============\n"); //UI表示
    printf("\n\n");
    printf("xxxxxxxxxxxxxx| GOOD | JUST | GOOD |xxxxxxxxxxxxxx\n");

    while (end == 0) {         //タイミングバー表示用
    for( i = 1 ; i <= 25 ; i ++){
        
        printf("|");
        delay(delaytime);

        if(kbhit()){        //何かしらのキーが押されたら終了
            charkey = getch();
            end += 1; 
            dec = i;
            break;
        }

        printf("\033[2K");
        printf(" ");
        
    }
    
    for( k = 25 ; k >= 1 ; k --){

        if(end != 0){ // 左から右に行くときにストップが押された場合、右から左に行く処理をスキップします
            break;
        }
        
        printf("\033[3D");
        printf("|");
        delay(delaytime);

        if(kbhit()){        //何かしらのキーが押されたら終了
            charkey = getch();
            end += 1; 
            dec = k;
            break;

        }
        
        printf("\033[2K");

    }
    }

    //printf("\ni または k は %d\n", dec );
    // ここはテスト用です 値を見るときに使用してください

    delay(10);

    if( dec <= 7 || dec > 17){
        printf("\n                     MISS!\n\n");
        point = 0;
        

    }else if( 7 < dec && dec <= 10 || 14 < dec &&  dec <= 17  ){
        printf("\n               %d連続!    GOOD!  +5点\n\n",round);
        point += 5;

    }else if(10 < dec && dec <= 14 ){
        printf("\n               %d連続!    JUST!  +10点\n\n",round);
        point+= 10;

    }

    return point;

}

int main(void){
 
    int result = 0;    //タイミングゲーム関数内で処理した点数保管用
    int beforeresult = 0;//前回のスコアを保存
    int times = 0;     //ゲームのラウンド数管理用
    int T_times = 0;   //合計ラウンド表示用
    
    int endB = 0;      //ゲーム終了管理用
    char charkey = 0;  //キーボード管理用

    //以下ゲーム本編
    printf("============================\n");
    printf("=     タイミングゲーム      =\n");
    printf("= Press any key to start!  =\n");
    printf("============================\n");

    printf("・タイミング良くSキーを押してね!\n");
    printf("・xで止めるとゲーム終了!\n");
    printf("・最高スコアを目指して自分の限界に挑め!\n");
    printf("\n");

    stop();//キーボード入力受付&その間処理を止める関数

    for(times  = 1 ;; times ++){  //タイミングゲームを回し続ける箇所

        beforeresult = result;
        result = result + timing(times);

        if(result == beforeresult  ){
            break;
        }

        T_times = times;
    }
    
    delay(100); //以下リザルト表示用
    printf("\n\n");
    printf("==================\n");
    printf("======RESULT======\n");
    printf("\n連続ゲーム数:%d回!\n",T_times);
    printf("\n合計点      :%d点!\n",result);
    printf("\n\n==================\n");
   
    printf("\n\n--終了--\n\n");
    
    return 0;
}

といったものが、コードになります。
ゲーム画面としては以下の画像のようになります。

実際のゲーム画面

3.コードの説明

月並みなコードではありますが、特筆すべき点としてゲームの大部分を処理するtiming関数をご紹介します。

1.動き回る棒について


タイミングの指標となる左右に動く棒について、左から右に行く際においては
1.| を書く
2.| を消す
3.[スペース]を書く
と繰り返すだけになっており、パラパラ漫画などと同じ様にアニメーションを作成しています。

逆に右から左に動く際については
1.[スペース]を消す
2.| を書く
3.| を消す
といった前項の動作を逆再生する形で描画しています。

ターミナル画面に描画したモノを消す、およびカーソル位置を変更する為にエスケープシーケンスを用いています。

2.タイミングの判定管理について

判定管理についてはfor文を用いて仮座標を定義し、[左から右に行く際] と [右から左に行く際] において差異が出ないように作成する事で、両者の判定に相違がない環境を作成する事が出来ました。
下記の画像がイメージとして分かりやすいかと思われます。
・左から右に棒が進む時には i 軸を使用
・右から左に棒が進む時には k 軸を使用 

座標のイメージ画像

4.あとがき

拙い文章ではありましたが、ご高覧頂きありがとうございました。
非常に当たり前な話ですが、ゲームを作成するのであればC言語以外の言語で作成をする事が推奨されます。

ですが、C言語からプログラミングを始めた初学者が自身の学習理解を深めつつ、目に見える成果物としてモノを作るには「ゲーム」というものは良い題材にも思えます。

ぜひ皆様も日々のプログラミング学習の成果物としてゲームを作成してみてはいかがでしょうか?


この記事が気に入ったらサポートをしてみませんか?