素人プログラマーの日常

効率の良いコード、美しいコードなんて書けません。

Phase of Evolution 完成!

落ち物系パズル完成しました。タイトルはどんどん進化していくということで「Phase of Evolution」に決定!なんか言葉の響きがカッコイイのでこれにしました(笑

 

f:id:dgen:20150722023556p:plain


一応今回はまともなゲームなので多少凝りたかったわけですが、最終的には画像もサウンドも手抜きで落ち着きました(汗。本当は神秘的で洗練されたイメージに仕上げる予定でしたが、早々に自分の実力を痛感し(いや、最初からわかっていたけど)素人っぽさの残る作品となりました。

まあそれで好いんです。実際素人ですし。カッコイイ画像やサウンドが作れるわけでもないので…。そういったことが得意な人は、自作の画像やサウンドに書き換えてプレイしてください。全部 imgフォルダに入っているので、ファイル名が同じなら読み込まれます。で、神秘的で洗練されたイメージになったら、そのファイルを私にください!(爆。改めて新バージョンとして紹介しようと思います。

こんな感じで、演出部分はプログラミングで多少補う程度で本腰を入れずやっていこうと開き直りました。逆にシンプルにすることが味になることもありますからね、なんて言い訳も追加しておきます。

あと内容としては、参考にしたゲームよりもテンポの良さを追求(っていうほどのものではないが)しました。操作はちょっと慣れないとブロックが回転し過ぎたりするかもしれませんが、テンポを良くするとちょうど好いくらいだと思います。他にも落下速度を早くしたり、進化のエフェクトも短時間にしてあります。原作よりも広いエリアなので、プレイ時間も長くなります。そこでテンポが悪いとプレイしていて鬱陶しいですからね。唯一の拘りです。

個人的にはそこそこ楽しめるゲームだと思っています。ぷよぷよとか好きならプレイ感覚は近いのでハマるかもしれません。連鎖も割りと簡単です。


こちらのページからダウンロード出来ます。プレイ動画もあります。

http://tenkomorituuhan2.com/products/phaseofevolution/top.html



ってことで Phase of Evolution のソースコードを掲載します。前回書いた再帰関数はだいぶ煩雑な感じに仕上がってます。というか私の書いたコードはプロの目にはどう映っているんですかね~。BASICっぽいコーディングは逆にわかり辛いんでしょうね。そもそもBASICだって極めたわけではないので、いい加減なコードに代わりはありませんが…。


素人が書いたものです。コードをてきとーに使用すると、巨神兵が眠りから醒め火の七日間を再現することになるかもしれません。そんな人類が絶滅の危機に瀕するようなことには関わりたくないので、わかる人が確認した上で使用してください。

#include "DxLib.h"

#define WX 640            //ウインドウサイズ
#define WY 480

#define WIDTH 10        //ブロック行
#define HEIGHT 10        //ブロック列

#define blockmax 20

int score;                            //スコア
int scoret;                        //スコア計算用
int scored;                        //スコア表示用
int highscore[ 10 ] = { 0 };                //ハイスコア
int level;                            //レベル
int maxevo;                        //最大進化
int combo;                        //連鎖
int maxcombo;                    //最大連鎖
int relative[ blockmax ];        //出現率相関

int block[ 6 ];                    //[0,1]操作ブロック [2,3],[4,5]ネクストブロック
int blockx[ 2 ];                    //操作ブロック位置
int blocky[ 2 ];

int totalflag;                        //制御フラグ
int maxmode;                    //モードフラグ

int area[ HEIGHT ][ WIDTH ];        //ブロックエリア
int areaE[ HEIGHT ][ WIDTH ];        //進化ブロックエリア
int totalbl;                                //隣接ブロック合計

int xp[ HEIGHT ][ WIDTH ];            //ゲームオーバー時ブロック描画用
int yp[ HEIGHT ][ WIDTH ];
int xv[ HEIGHT ][ WIDTH ];
int yv[ HEIGHT ][ WIDTH ];
int bl[ HEIGHT ][ WIDTH ];

//ハンドル

int GHtitle;                        //タイトル
int GHbg[ 2 ];                    //背景
int GHblock[ blockmax ];        //ブロック
int GHnext;                        //ネクストブロック
int GHscore;                        //スコア
int GHnum[ 10 ];                //数字
int GHfade;                        //フェドインアウト

int SHbgm;            //BGM

int SHrotate;        //回転
int SHmove;            //移動
int SHfall;            //落下
int SHevo1;            //進化
int SHevo2;

//プロトタイプ宣言

void Title();
void DrawTitle();
void Play();
void Draw();
void Extraction();        //出現ブロック抽出
void Control();            //操作
void Fall();                //ブロック落下
int Evolution();                //進化
void EvolutionSearch( int absx , int absy );    //進化可能ブロック探索(再帰
void DrawEvolution( int effect );        //進化エフェクト
void FadeIn();            //フェードイン
void FadeOut();            //フェードアウト
int GameOverFlag();        //ゲームオーバー判定
void GameOver();            //ゲームオーバー
int DrawGameOver();    //描画
void Init();                    //スタート時初期化

void Save();
void Load();

//WinMain
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    SetOutApplicationLogValidFlag( FALSE );    //ログ出力しない
    SetMainWindowText( "PHASE OF EVOLUTION" );        //ウインドウタイトル指定
    SetGraphMode( WX , WY , 32 );            //ウインドウの大きさとカラービット数指定
    ChangeWindowMode( TRUE );                //ウインドウで表示
    SetDrawScreen( DX_SCREEN_BACK );    //ちらつき防止設定
    SetWaitVSyncFlag( TRUE );                    //フレーム同期
    SetMouseDispFlag( TRUE );                    //マウスカーソル表示
    SetWindowUserCloseEnableFlag( FALSE );    //×ボタンで終了しない

    if( DxLib_Init() == -1 ) return -1;

    Load();        //読込み

    //画像読込
    GHtitle = LoadGraph( "img/title.png" );
    GHbg[ 0 ] = LoadGraph( "img/bg.png" );
    GHbg[ 1 ] = LoadGraph( "img/bg2.png" );
    GHnext = LoadGraph( "img/next.png" );
    GHscore = LoadGraph( "img/score.png" );
    LoadDivGraph( "img/block.png" , blockmax , blockmax , 1 , 48 , 48 , GHblock );
    LoadDivGraph( "img/num.png" , 10 , 10 , 1 , 16 , 32 , GHnum );

    //音声読込み
    SHbgm = LoadSoundMem( "img/bgm_base.wav" );
    ChangeVolumeSoundMem( 250 , SHbgm );

    SHrotate = LoadSoundMem( "img/rotate.wav" );
    SHmove = LoadSoundMem( "img/move.wav" );
    SHfall = LoadSoundMem( "img/fall.wav" );
    SHevo1 = LoadSoundMem( "img/evo1.wav" );
    SHevo2 = LoadSoundMem( "img/evo2.wav" );

    ChangeFont( "Impact" );

    //メインループ/////////////////////////////////
    while( totalflag != -1 ){

        switch( totalflag ){
        case 0:
            Title();
            break;
        case 1:
            Play();
            break;
        }

    }

    Save();

    DxLib_End();
    return 0;
}


void Title(){            //タイトル画面///////////////////

    DrawTitle();
    FadeIn();
    DrawTitle();
    ScreenFlip();
    WaitKey();

    if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ){
        totalflag = -1;
    }else{
        totalflag = 1;
    }
    if( CheckHitKey( KEY_INPUT_M ) == 1 ){
        maxmode = 1;
    }else{
        maxmode = 0;
    }

    FadeOut();

}


void DrawTitle(){    //タイトル描画///////////////////

    DrawBox( 0 , 0 , WX , WY , 0x005dc2 , TRUE );
    DrawGraph( 70 , 20 , GHtitle , TRUE );

    //ハイスコア描画
    for( int i = 0 ; i<10 ; i++ ){
        int sc = highscore[ i ];
        for( int j = 1 ; sc > 0 ; j++ ){
            DrawGraph( i / 5 * 160 - ( j * 16 ) + 440 , i % 5 * 40 + 270 , GHnum[ sc % 10 ] , TRUE );
            sc /= 10;
        }
    }

    //最大進化描画
    int me = maxevo;
    for( int j = 1 ; me > 0 ; j++ ){
        DrawGraph( 250 - j * 16 , 322 , GHnum[ me % 10 ] , TRUE );
        me /= 10;
    }

    //最大連鎖描画
    int mc = maxcombo;
    for( int j = 1 ; mc > 0 ; j++ ){
        DrawGraph( 250 - j * 16 , 382 , GHnum[ mc % 10 ] , TRUE );
        mc /= 10;
    }

    DrawString( 80 , 240 , "any key to start!" , 0xffff00 );
    DrawString( 80 , 260 , "「M」 key to Maxmode!!" , 0xffff00 );
    DrawString( 80 , 280 , "「ESC」 key to close" , 0xffff00 );

    DrawString( 340 , 240 , "HIGH SCORE" , 0xffffff );
    DrawString( 80 , 330 , "MAX EVOLUTION" , 0xffffff );
    DrawString( 80 , 390 , "MAX COMBO" , 0xffffff );

}


void Play(){            //プレイ////////////////////////////

    Init();

    Extraction();            //出現ブロック抽出
    Extraction();            //ネクストブロックを含め3回

    Draw();
    FadeIn();
    Draw();
    ScreenFlip();

    PlaySoundMem( SHbgm , DX_PLAYTYPE_LOOP );

    while( totalflag != 9 ){            //プレイループ

        Extraction();            //出現ブロック抽出
        Control();                //ブロック操作
        if( totalflag == -1 ) break;

        while( 1 ){
            Fall();                            //ブロック落下
            if( Evolution() == 0 ) break;        //進化
        }
        
        totalflag = GameOverFlag();        //ゲームオーバー判定(戻り値9)
        WaitVSync( 20 );

    }
    if( totalflag == -1 ) return;

    Draw();
    ScreenFlip();

    //GAVE OVER処理
    GameOver();

    totalflag = 0;
}


void Draw(){            //描画///////////////////////////////

    DrawBox( 0 , 0 , WX , WY , 0x000000 , TRUE );

    //背景・ブロック描画
    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            if( y > 1 ){
                DrawGraph( x * 48 , y * 48 , GHbg[ 0 ] , TRUE );
            }else{
                DrawGraph( x * 48 , y * 48 , GHbg[ 1 ] , TRUE );
            }
            if( area[ y ][ x ] > -1 ) DrawGraph( x * 48 , y * 48 , GHblock[ area[ y ][ x ] ] , TRUE );
        }
    }

    //ネクストブロック描画
    DrawGraph( WIDTH * 48 +16 , 48 , GHnext , TRUE );
    for( int i = 0 ; i < 2 ; i++ ){
        DrawGraph( WIDTH * 48 + i * 64 + 24 , 70 , GHblock[ block[ 2 + i * 2 ] ] , TRUE );
        DrawGraph( WIDTH * 48 + i * 64 + 24 , 118 , GHblock[ block[ 3 + i * 2 ] ] , TRUE );
    }

    //スコア描画
    DrawGraph( WIDTH * 48 + 16 , 200 , GHscore , TRUE );
    int sc = score;
    for( int i = 1 ; sc > 0 ; i++ ){
        DrawGraph( WX - i * 16 - 16 , 232 , GHnum[ sc % 10 ] , TRUE );
        sc /= 10;
    }

}    


void Extraction(){        //出現ブロック抽出/////////////////

    int lv = level + 3;        //出現ブロック種類
    if( lv > blockmax ) lv = blockmax;
    if( ( lv + 1 > maxevo ) && ( maxmode == 0 ) ) maxevo = lv + 1;
    int re = 0;                //出現ブロック

    //ネクストブロック入替え
    for( int i = 0 ; i < 4 ; i += 2 ){
        block[ i ]            = block[ i + 2 ];
        block[ i + 1 ]    = block[ i + 3 ];
    }

    for( int j = 0 ; j < 2 ; j++ ){

        int total = 0;            //出現率の合計値

        for( int i = 0 ; i < lv ; i++ ){
            total += relative[ i ];
        }

        //合計値の乱数取得
        int r = GetRand( total -1 );

        //乱数と相関を比較
        for( int i = 0 ; i < lv ; i++ ){
            if( relative[ i ] > r ){
                re = i;
                break;
            }
            r -= relative[ i ];
        }

        //出現- 否出現++
        for( int i = 0 ; i < lv ; i++ ){
            relative[ i ] += 2;
        }
        relative[ re ] -= level + 2;
        if( relative[ re ] < 1 ) relative[ re ] = 1;

        block[ 4 + j ] = re;
    }

}


void Control(){        //操作///////////////////////////////

    combo = 1;

    int movex = 0;                //横移動量
    int movexv = 0;                //横移動向き
    int mover = 0;                //回転移動量
    int moverst = 0;            //回転段階(4段階)
    int moverx[ 2 ] = { 0 };    //回転移動向き横
    int movery[ 2 ] = { 0 };    //回転移動向き縦

    int key = 0;                    //左右入力

    blockx[ 0 ] = WIDTH / 2;        //ブロック出現位置初期化
    blocky[ 0 ] = 0;
    blockx[ 1 ] = WIDTH / 2;
    blocky[ 1 ] = 1;

    while( 1 ){            //ブロック操作ループ

        //終了
        if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ){
            totalflag = -1;
            break;
        }

        //左右の入力チェック
        key = CheckHitKey( KEY_INPUT_RIGHT ) - CheckHitKey( KEY_INPUT_LEFT );
        if( ( key != 0 ) && ( movex == 0 ) ){

            //範囲確認
            if( ( -1 < blockx[ 0 ] + key ) && ( blockx[ 0 ] + key < WIDTH ) &&
                ( -1 < blockx[ 1 ] + key ) && ( blockx[ 1 ] + key < WIDTH ) ){

                    //移動設定
                blockx[ 0 ] += key;
                blockx[ 1 ] += key;
                movex = key * 48;
                movexv = key;
                PlaySoundMem( SHmove , DX_PLAYTYPE_BACK );
            }
        }

        //「↑」の入力チェック
        if( ( CheckHitKey( KEY_INPUT_UP ) == 1 ) && ( mover < 1 ) ){

            //回転段階++
            moverst = ( moverst + 1 ) % 4;
            PlaySoundMem( SHrotate , DX_PLAYTYPE_BACK );

            //段階に応じて移動設定
            for( int i = 0 ; i < 2 ; i++ ){
                moverx[ i ] = 0;
                movery[ i ] = 0;
            }
            switch( moverst ){
            case 0:        //block[1]が左下へ
                moverx[ 1 ] = -1;
                movery[ 1 ] = 1;
                blockx[ 1 ]--;
                blocky[ 1 ]++;
                break;
            case 1:        //[0]が右下へ
                if( blockx[ 0 ] + 1 < WIDTH ){
                    moverx[ 0 ] = 1;
                    movery[ 0 ] = 1;
                    blockx[ 0 ]++;
                    blocky[ 0 ]++;
                } else {
                    movery[ 0 ] = 1;
                    moverx[ 1 ] = -1;
                    blocky[ 0 ]++;
                    blockx[ 1 ]--;
                }
                break;
            case 2:        //[1]が右上へ
                moverx[ 1 ] = 1;
                movery[ 1 ] = -1;
                blockx[ 1 ]++;
                blocky[ 1 ]--;
                break;
            case 3:        //[0]が左上へ
                if( blockx[ 0 ] - 1 > -1 ){
                    moverx[ 0 ] = -1;
                    movery[ 0 ] = -1;
                    blockx[ 0 ]--;
                    blocky[ 0 ]--;
                } else {
                    movery[ 0 ] = -1;
                    moverx[ 1 ] = 1;
                    blocky[ 0 ]--;
                    blockx[ 1 ]++;
                }
                break;
            }
            mover = 48;
        }

        //「↓」を押したら抜ける
        if( ( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) && ( movex == 0 ) && ( mover < 1 ) ) break;

        //横移動
        if( movex != 0 ) movex -= movexv * 4;

        //回転移動
        if( mover > 0 ) mover -= 8;

        //描画
        Draw();
        for( int i = 0 ; i < 2 ; i++ ){
            DrawGraph( blockx[ i ] * 48 - movex - moverx[ i ] * mover ,
                            blocky[ i ] * 48 - movery[ i ] * mover , GHblock[ block[ i ] ] , TRUE );
        }
        ScreenFlip();

    }

    area[ blocky[ 0 ] ][ blockx[ 0 ] ] = block[ 0 ];
    area[ blocky[ 1 ] ][ blockx[ 1 ] ] = block[ 1 ];

}


void Fall(){            //ブロック落下////////////////////

    int fallflag = 0;
    int flag;
    do{
        flag = 0;
        for( int y = HEIGHT - 2 ; y >-1 ; y-- ){
            for( int x = 0 ; x < WIDTH ; x++ ){
                //下に何もなければ1段落下
                if( ( area[ y ][ x ] > -1 ) && ( area[ y + 1 ][ x ] == -1 ) ){
                    area[ y + 1 ][ x ] = area[ y ][ x ];
                    area[ y ][ x ] = -1;
                    flag = 1;
                    fallflag = 1;
                }
            }            //for x
        }                //for y
        Draw();
        ScreenFlip();
    }while( flag == 1 );

    if( fallflag == 1 ) PlaySoundMem( SHfall , DX_PLAYTYPE_BACK );

}


int Evolution(){        //進化///////////////////////////////

    //初期化
    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            areaE[ y ][ x ] = 0;
        }
    }

    int evoflag = 0;

    for( int y = HEIGHT - 1 ; y > 1 ; y-- ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            //進化基点探索
            if( ( area[ y ][ x ] > -1 ) && ( areaE[ y ][ x ] == 0 ) ){
                int flag = 0;
                if( x + 1 < WIDTH ){
                    if( area[ y ][ x ] == area[ y ][ x + 1 ] ){
                        flag = 1;
                    }
                }
                if( area[ y ][ x ] == area[ y - 1 ][ x ] ){
                    flag = 1;
                }
                if( flag == 1 ){

                    //基点から隣接ブロック探索
                    totalbl = 1;            //隣接ブロック合計
                    areaE[ y ][ x ] = 1;

                    EvolutionSearch( x , y );        //再帰探索

                    if( totalbl >= 3 ){
                        //進化可能!
                        for( int ye = 0 ; ye < HEIGHT ; ye++ ){
                            for( int xe = 0 ; xe < WIDTH ; xe++ ){
                                if( areaE[ ye ][ xe ] == 1 ) areaE[ ye ][ xe ] = 3;
                            }    //for xe
                        }        //for ye
                        if( area[ y ][ x ] >= blockmax - 1 ){
                            areaE[ y ][ x ] = 3;
                        }else{
                            areaE[ y ][ x ] = 4;
                        }
                        evoflag = 1;
                    } else {
                        //進化ならず…
                        areaE[ y ][ x ] = 2;
                        if( areaE[ y - 1 ][ x ] == 1 ) areaE[ y - 1 ][ x ] = 2;
                        if( x + 1 < WIDTH ){
                            if( areaE[ y ][ x + 1 ] == 1 ) areaE[ y ][ x + 1 ] = 2;
                        }
                    }

                }
            }
        }        //for x
    }            //for y

    if( evoflag == 0 ) return 0;

    //進化!!!
    DrawEvolution( 1 );

    int num = 0;
    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            if( areaE[ y ][ x ] == 3 ){
                num += area[ y ][ x ] + 1;
                areaE[ y ][ x ] = 0;
                area[ y ][ x ] = -1;
            } else if( areaE[ y ][ x ] == 4 ){
                num += area[ y ][ x ] + 1;
                area[ y ][ x ]++;
                if( area[ y ][ x ] > level + 3 ) level++;
            }
        }
    }
    Draw();
    ScreenFlip();
    DrawEvolution( -1 );
    Draw();
    ScreenFlip();

    score += num * ( 10 + level ) * combo;
    if( combo > maxcombo ) maxcombo = combo;
    combo++;

    WaitVSync( 10 );

    return 1;
}


void EvolutionSearch( int absx , int absy ){    //隣接ブロック探索////////////////////

    int xmin = absx - 1;
    int xmax = absx + 1;
    int ymin = absy - 1;
    int ymax = absy + 1;

    if( xmin > -1 ){
        if( ( area[ absy ][ absx ] == area[ absy ][ xmin ] ) && ( areaE[ absy ][ xmin ] == 0 ) ){
            totalbl++;
            areaE[ absy ][ xmin ] = 1;
            EvolutionSearch( xmin , absy );
        }
    }
    if( xmax < WIDTH ){
        if( ( area[ absy ][ absx ] == area[ absy ][ xmax ] ) && ( areaE[ absy ][ xmax ] == 0 ) ){
            totalbl++;
            areaE[ absy ][ xmax ] = 1;
            EvolutionSearch( xmax , absy );
        }
    }
    if( ymin > -1 ){
        if( ( area[ absy ][ absx ] == area[ ymin ][ absx ] ) && ( areaE[ ymin ][ absx ] == 0 ) ){
            totalbl++;
            areaE[ ymin ][ absx ] = 1;
            EvolutionSearch( absx , ymin );
        }
    }
    if( ymax < HEIGHT ){
        if( ( area[ absy ][ absx ] == area[ ymax ][ absx ] ) && ( areaE[ ymax ][ absx ] == 0 ) ){
            totalbl++;
            areaE[ ymax ][ absx ] = 1;
            EvolutionSearch( absx , ymax );
        }
    }

}


void DrawEvolution( int effect ){        //進化エフェクト/////////////

    int GHtemp = MakeGraph( WX , WY );
    GetDrawScreenGraph( 0 , 0 , WX , WY , GHtemp );

    DrawBox( 0 , 0 , WX , WY , 0x000000 , TRUE );

    int imin;
    int imax;
    if( effect == 1 ){
        imin = 0;
        imax = 16;
        PlaySoundMem( SHevo1 , DX_PLAYTYPE_BACK );
    } else {
        imin = 16;
        imax = 0;
        PlaySoundMem( SHevo2 , DX_PLAYTYPE_BACK );
    }

    for( int i = imin ; i != imax ; i += effect ){

        DrawBox( 0 , 0 , WX , WY , 0x000000 , TRUE );
        DrawGraph( 0 , 0 , GHtemp , TRUE );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , 255 - i * 16 );
        for( int y = 0 ; y < HEIGHT ; y++ ){
            for( int x = WIDTH -1 ; x > -1 ; x-- ){
                if( areaE[ y ][ x ] > 2 ){
                    DrawRotaGraph( x * 48 + 24 , y * 48 + 24 , ( double )i / 2 , 0 , GHblock[ area[ y ][ x ] ] , TRUE , FALSE );
                }
            }    //for x
        }        //for y
        SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );
        ScreenFlip();

    }            //for i

}


void FadeIn(){        //フェードイン////////////////////

    GHfade = MakeGraph( WX , WY );
    GetDrawScreenGraph( 0 , 0 , WX , WY , GHfade );

    for( int i = 0 ; i < 255 ; i += 5 ){
        ClearDrawScreen();
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , i );
        DrawGraph( 0 , 0 , GHfade , TRUE );
        ScreenFlip();
    }
    SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );

    DeleteGraph( GHfade );

}


void FadeOut(){        //フェードアウト/////////////////

    GHfade = MakeGraph( WX , WY );
    GetDrawScreenGraph( 0 , 0 , WX , WY , GHfade );

    for( int i = 255 ; i > 0 ; i -= 5 ){
        ClearDrawScreen();
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , i );
        DrawGraph( 0 , 0 , GHfade , TRUE );
        ScreenFlip();
    }
    SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );

    DeleteGraph( GHfade );

}


int GameOverFlag(){    //ゲームオーバー判定///////////////////

    int flag = 0;
    for( int x = 0 ; x < WIDTH ; x++ ){
        if( area[ 1 ][ x ] > -1 ) flag = 1;
    }
    if( flag == 1 ) return 9;

    return 1;
}


void GameOver(){        //ゲームオーバー//////////////

    StopSoundMem( SHbgm );

    //ハイスコア
    if( score > highscore[ 9 ] ){
        highscore[ 9 ] = score;
        for( int i = 8 ; i > -1 ; i-- ){
            if( score > highscore[ i ] ){
                highscore[ i + 1 ] = highscore[ i ];
                highscore[ i ] = score;
            }
        }
    }

    //初期化
    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            bl[ y ][ x ] = -1;
        }
    }

    //ひとつずつ弾ける
    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            if( area[ y ][ x ] > -1 ){
                xp[ y ][ x ] = x * 48;
                yp[ y ][ x ] = y * 48;
                yv[ y ][ x ] = -9;
                xv[ y ][ x ] = GetRand( 11 ) - 6;
                bl[ y ][ x ] = area[ y ][ x ];
                area[ y ][ x ] = -1;
            }
            DrawGameOver();
            DrawGameOver();
        }    //for x
    }        //for y

    while( 1 ){
        if( DrawGameOver() == 0 ) break;
    }

    Draw();
    FadeOut();

}


int DrawGameOver(){        //描画(Game over)//////////////////

    int flag = 0;
    Draw();

    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            if( area[ y ][ x ] > -1 ) flag = 1;
            if( bl[ y ][ x ] > -1 ){
                DrawGraph( xp[ y ][ x ] , yp[ y ][ x ] , GHblock[ bl[ y ][ x ] ] , TRUE );
                flag = 1;
                yv[ y ][ x ]++;
                yp[ y ][ x ] += yv[ y ][ x ];
                xp[ y ][ x ] += xv[ y ][ x ];
                if( yp[ y ][ x ] > WY ) bl[ y ][ x ] = -1;
            }
        }    //for x
    }        //for y

    ScreenFlip();

    return flag;

}


void Init(){            //スタート時初期化//////////////

    score = 0;
    scoret = 0;
    if( maxmode == 1 ){
        level = maxevo - 4;
        if( level < 0 ) level = 0;
    }else{
        level = 0;
    }

    for( int i = 0 ; i < blockmax ; i++ ){
        relative[ i ] = 1;
    }

    for( int y = 0 ; y < HEIGHT ; y++ ){
        for( int x = 0 ; x < WIDTH ; x++ ){
            area[ y ][ x ] = -1;
        }
    }
}


void Save(){            //書込み////////////////////////////

    FILE *fp;
    errno_t error;

    if( ( error = fopen_s( &fp , "save.sv" , "wb" ) ) != 0 ){
        //エラー
    }else{
        fwrite( highscore , sizeof( int ) , 10 , fp );
        fwrite( &maxevo , sizeof( int ) , 1 , fp );
        fwrite( &maxcombo , sizeof( int ) , 1 , fp );
        fclose( fp );
    }

}


void Load(){            //読込み////////////////////////////


    FILE *fp;
    errno_t error;

    if( ( error = fopen_s( &fp , "save.sv" , "rb" ) ) != 0 ){
        //エラー
    }else{
        fread( highscore , sizeof( int ) , 10 , fp );
        fread( &maxevo , sizeof( int ) , 1 , fp );
        fread( &maxcombo , sizeof( int ) , 1 , fp );
        fclose( fp );
    }

}