ブラウザゲームを作ってみよう(その11:サンプルゲーム作成その4)

# はじめに
[その10](https://qiita.com/noji505/items/a4fa4d9a1f37a80d7690)ではゲームのバランス調整を行いました。
今回はオプションモードを追加してみたいと思います。

# オプションモードについて
タイトル画面からオプション画面へ入れるようにし、そこでゲームのパラメータを変更できるようにしてみます。
以下のような形で、タイトル画面からの遷移が増えるイメージになります。

[遷移イメージ]
![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/d0871d3a-8d4e-1980-bfd1-ffa849ce1a69.png)

変更するパラメータは以下とします。
* ライフの初期値
* コイン出現間隔(〇点獲得で出現間隔スピードが2倍になる)
* コイン出現数(□点獲得で出現数が△枚になる)

# ソースコード
まずはタイトル画面にオプション画面への遷移を追加します。
ソースコードは以下となります。

```javascript:オプション画面追加

// 変数
var cursorNum;                  // カーソル選択値

// タイトル画面初期化
function titleInit()
{
    cursorNum = 0;
    gameState = 0;  // タイトル画面ループへ
}

// タイトル画面ループ
function titleMainLoop()
{
    drawText( "コインゲット", 0, 20, '#000000', 12, TEXT_HCENTER );


    drawText( "ゲーム開始", 0, SC_H - 80, '#000000', 12, TEXT_HCENTER );
    drawText( "オプション", 0, SC_H - 50, '#000000', 12, TEXT_HCENTER );

    if( keyTrg == KEY_UP ){
        cursorNum = 0;
    }
    if( keyTrg == KEY_DOWN ){
        cursorNum = 1;
    }
    // 選択カーソル表示
    if( cursorNum == 0 ){
        drawFill( 100, SC_H - 78, 12, 12, 0x0000FF, null );
        drawFill( 188, SC_H - 78, 12, 12, 0x0000FF, null );

    } else if( cursorNum == 1 ){
        drawFill( 100, SC_H - 48, 12, 12, 0x0000FF, null );
        drawFill( 188, SC_H - 48, 12, 12, 0x0000FF, null );

    }

    if( keyTrg == KEY_SPACE ){
        if( cursorNum == 0 ){
            gameInit();  // ゲーム画面初期化へ
        } else if( cursorNum == 1 ){
            optionInit();  // オプション画面初期化へ
        }
    }
}
```

■変更点ポイント
* ゲーム開始の下に「オプション画面」の項目を追加
* ゲーム開始、オプション選択の両端に選択カーソルの表示を追加

HTMLだとaタグを追加し、クリックすると遷移～という風に作成すると思うのですが、
ゲームだとそれが難しいため「今どこが選択されているか？」を示すカーソルを表示する必要があります。

続いて、オプション画面のソースコードは以下となります。

```javascript:オプション画面

// 変数宣言
var initLife = 3;               // 初期ライフ値
var initCoinChangeScore = 5;    // コイン出現間隔変更の初期スコア値
var initCoinShowNumScore = 10;  // コイン同時出現数変更の初期スコア値
var initCoinShowNum = 2;        // コイン同時出現数の初期枚数

var updateLife = initLife;
var updateCoinChangeScore = initCoinChangeScore;
var updateCoinShowNumScore = initCoinShowNumScore;
var updateCoinShowNum = initCoinShowNum;

//=======================================================================================
//  オプション画面
//=======================================================================================

// オプション画面初期化
function optionInit()
{
    cursorNum = 0;
    gameState = 3;    // オプション画面ループへ
}

// オプション画面ループ
function optionMainLoop()
{
    drawText( "オプション画面", 0, 20, '#000000', 12, TEXT_HCENTER );

    drawText( "ライフ初期値(1-10)", 10, 60, '#000000', 12, TEXT_NONE );
    drawText( "コイン出現間隔変更スコア枚数(1-99)", 10, 80, '#000000', 12, TEXT_NONE );
    drawText( "コイン出現数変更スコア枚数(1-99)", 10, 100, '#000000', 12, TEXT_NONE );
    drawText( "コイン出現数(1-5)", 10, 120, '#000000', 12, TEXT_NONE );

    drawText( updateLife, SC_W - 30, 60, '#000000', 12, TEXT_NONE );
    drawText( updateCoinChangeScore, SC_W - 30, 80, '#000000', 12, TEXT_NONE );
    drawText( updateCoinShowNumScore, SC_W - 30, 100, '#000000', 12, TEXT_NONE );
    drawText( updateCoinShowNum, SC_W - 30, 120, '#000000', 12, TEXT_NONE );

    drawText( "リセット", 10, 150, '#000000', 12, TEXT_HCENTER );
    drawText( "タイトル画面へ", 10, 180, '#000000', 12, TEXT_HCENTER );

    // カーソル移動
    if( keyTrg == KEY_UP ){
        cursorNum--;
        if( cursorNum < 0 ){
            cursorNum = 0;
        }
    }

    if( keyTrg == KEY_DOWN ){
        cursorNum++;
        if( cursorNum > 5 ){
            cursorNum = 5;
        }
    }
    // パラメータ変更
    if( (keyPress & KEY_LEFT) != 0 ){
        if( cursorNum == 0 ){
            updateLife--;
            if( updateLife < 1 ){
                updateLife = 1;
            }

        } else if( cursorNum == 1 ){
            updateCoinChangeScore--;
            if( updateCoinChangeScore < 1 ){
                updateCoinChangeScore = 1;
            }

        } else if( cursorNum == 2 ){
            updateCoinShowNumScore--;
            if( updateCoinShowNumScore < 1 ){
                updateCoinShowNumScore = 1;
            }

        } else if( cursorNum == 3 ){
            updateCoinShowNum--;
            if( updateCoinShowNum < 1 ){
                updateCoinShowNum = 1;
            }

        }
    }
    if( (keyPress & KEY_RIGHT) != 0 ){
        if( cursorNum == 0 ){
            updateLife++;
            if( updateLife > 10 ){
                updateLife = 10;
            }

        } else if( cursorNum == 1 ){
            updateCoinChangeScore++;
            if( updateCoinChangeScore > 99 ){
                updateCoinChangeScore = 99;
            }

        } else if( cursorNum == 2 ){
            updateCoinShowNumScore++;
            if( updateCoinShowNumScore > 99 ){
                updateCoinShowNumScore = 99;
            }

        } else if( cursorNum == 3 ){
            updateCoinShowNum++;
            if( updateCoinShowNum > 5 ){
                updateCoinShowNum = 5;
            }

        }
    }
    // カーソル表示
    if( cursorNum == 0 ){
        drawFill( 250, 62, 10, 10, 0x0000FF, null );

    } else if( cursorNum == 1 ){
        drawFill( 250, 82, 10, 10, 0x0000FF, null );

    } else if( cursorNum == 2 ){
        drawFill( 250, 102, 10, 10, 0x0000FF, null );

    } else if( cursorNum == 3 ){
        drawFill( 250, 122, 10, 10, 0x0000FF, null );

    } else if( cursorNum == 4 ){
        drawFill( 110, 152, 12, 12, 0x0000FF, null );
        drawFill( 180, 152, 12, 12, 0x0000FF, null );

    } else if( cursorNum == 5 ){
        drawFill( 82, 182, 12, 12, 0x0000FF, null );
        drawFill( 200, 182, 12, 12, 0x0000FF, null );

    }

    if( keyTrg == KEY_SPACE ){
        if( cursorNum == 4 ){    // リセット
            updateLife = initLife;
            updateCoinChangeScore = initCoinChangeScore;
            updateCoinShowNumScore = initCoinShowNumScore;
            updateCoinShowNum = initCoinShowNum;

        } else if( cursorNum == 5 ){    // タイトル画面へ
            titleInit();
        }
    }
}
```

■ポイント
基本的にはタイトル画面でのカーソル表示・選択と変わらないのですが、左右キーで設定値の変更が出来るようになっています。
また設定値の変更は素早く行いたい場合が多いと思うので、押しっぱなしで値が変更出来るようになっています。


# サンプル更新

今回の変更点を全て反映したサンプルは以下になります。

<p class="codepen" data-height="300" data-default-tab="html" data-slug-hash="qBppZvZ" data-user="noji505" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/noji505/pen/qBppZvZ">
  Qiita22_sample01</a> by nojima (<a href="https://codepen.io/noji505">@noji505</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

設定変更し実際に反映されるか試してみて下さい。

# 最後に
今回はオプションモードを追加し、パラメータを変更出来るようにしました。
後から容易に変更・調整が出来るように設定値などは極力変数にしておくと良いと思います。