マイクロソフトの田中達彦です。
本連載では、Windowsストアアプリとして作成したパズルゲームである、Line Attackのプログラムを解説します。
Line Attack : http://apps.microsoft.com/webpdp/app/f11e327c-6228-4c8f-8245-ea57d65e0f09


[注意事項]

- この連載で提供するプロジェクトファイルは、サンプルとして提供しています。
- 毎回の記事で提供するプロジェクトファイルは、その時点でのソースコードです。最終バージョンのソースコードと異なる場合があります。


[今回のプロジェクトファイル]
今まで公開したプロジェクトはテスト用のステージを1面用意していただけです。
今回公開するプロジェクトは、複数のステージを用意して、アプリバーを使ってステージを変える部分を実装しています。




[ステージの追加]
ステージのデータは、以下のように増やしていきます。

// Stage 1
stage = 1;

lineData[0] = "++++++";
lineData[1] = "++++++";
lineData[2] = "111111";
lineData[3] = "111111";
lineData[4] = "++++++";
lineData[5] = "++++++";
LineDataToStageData(stage, lineData);

lineData[0] = "++11++";
lineData[1] = "++11++";
lineData[2] = "++11++";
lineData[3] = "++11++";
lineData[4] = "++11++";
lineData[5] = "++11++";
LineDataToStageResultData(stage, lineData);

// Stage 2
stage = 2;

lineData[0] = "++++++";
lineData[1] = "++++++";
lineData[2] = "111111";
lineData[3] = "111111";
lineData[4] = "++++++";
lineData[5] = "++++++";
LineDataToStageData(stage, lineData);

lineData[0] = "+1++1+";
lineData[1] = "++11++";
lineData[2] = "+1++1+";
lineData[3] = "++11++";
lineData[4] = "+1++1+";
lineData[5] = "++11++";
LineDataToStageResultData(stage, lineData);

そして、ステージの数をMaxStageNumberに入れておきます。
今回のプロジェクトでは6つのステージを用意したので、以下のように6を代入します。

public int MaxStageNumber = 6;


[ステージの切り替え]
ステージを変える方法は、いくつか考えられます。
例えば、ステージをクリアしたら次のステージに自動的に変える方法もありますし、画面上にボタンを設けて、ボタンをクリックするとステージを変えるようにもできます。
Windowsストア アプリでは、コマンド類をなるべくメイン画面に置かないという方針があるので、Line Attackではアプリバーにボタンを2つ配置し、前後のステージに移動できるように実装します。


[アプリバーとボタンの追加]
アプリバーを使うには、まずXAMLのコードにアプリバーを追加します。
アプリバーは、画面の下と上の両方に設置できます。
下のアプリバーにはコマンド類、上のアプリバーにはナビゲーション系のコマンド、すなわち画面遷移を伴うコマンドをを置きます。
下のアプリバーの中でも、ボタンを右端に配置するときと左端に配置するときがあります。
右側には、アプリ全体や表示されているページにかかわるコマンドを配置します。
左側には、選択しているアイテムにかかわるコマンドを配置します。
ここで配置する前後のステージに移動するコマンドは、アプリ全体にかかわるコマンドなので右側に配置します。

アプリバーには、以下のように前のステージに移動するPreviousというボタンと、次のステージに移動するNextというボタンを配置します。



MainPage.xamlには、以下のコードを追加します。

<Page.BottomAppBar>
    <AppBar x:Name="BottomAppBar1" Padding="10,0,10,0" Background="DarkBlue">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="30*"/>
                <ColumnDefinition Width="70*"/>
            </Grid.ColumnDefinitions>
            <StackPanel x:Name="RightPanel" Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right">
                <Button x:Name="Prev" Style="{StaticResource PreviousAppBarButtonStyle}" Tag="Prev" Click="Prev_Click"/>
                <Button x:Name="Next" Style="{StaticResource NextAppBarButtonStyle}"  Tag="Next" Click="Next_Click"/>
            </StackPanel>
        </Grid>
    </AppBar>
</Page.BottomAppBar>

この中で、黄色くマーカーした部分でアプリバーを2つに分けています。
左側が30%、右側が70%の割合で分けています。
サンプルなどで左右に50%ずつ分けているものがあります。
左右に50%ずつ分けると、片方にボタンを2つ配置したときにスナップするとボタンが切れてしまうという現象が発生します。
今回は、右側に2つのボタンを配置しますので、右側の割合を増やしています。

水色でマーカーした部分で、PreviousAppBarButtonStyleとNextAppBarButtonStyleというものを使っています。
Visual Studio 2012でプロジェクトを作ったときに、Commonというフォルダーが作られて、その中にStandardStyles.xamlというファイルが入っています。
このファイルには、よく使われるボタンや、アイテムを表示させるときのテンプレートが入っています。
アプリバーにボタンを追加するとき、もし追加したいボタンがStandardStyles.xamlにあればそれを使います。
Previous、NextのボタンもStandardStyles.xamlに含まれているので、それを使います。
しかし、デフォルトの状態ではボタン��部分がコメントアウトされています。
StandardStyles.xamlから以下の部分を見つけ、黄色くマーカーしている --> と <-- を追加して、これらのボタンの部分をコメントでないようにします。

-->
   
<Style x:Key="NextAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="NextAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Next"/>
    <Setter Property="Content" Value="&#xE111;"/>
</Style>
<Style x:Key="PreviousAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="PreviousAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Previous"/>
    <Setter Property="Content" Value="&#xE112;"/>
</Style>
   
<!--


[ステージ移行用のメソッド]
MainPage.xamlに追加したアプリバーは、Nextボタンを押したらNext_Clickイベントハンドラーが、Previousボタンを押したらPrev_Clickイベントハンドラーが呼ばれるように実装されています。
Line Attackでは、Next_Clickイベントハンドラーの中でNextStageメソッドを、Prev_Clickイベントハンドラーの中でPrevStageメソッドをそれぞれ呼んでいて、ステージを切り替えています。

private void NextStage()
{
    if (StageNumber >= MaxStageNumber)
        return;

    StageNumber++;

    SetPanel(StageNumber);
}

private void PrevStage()
{
    if (StageNumber <= 1)
        return;

    StageNumber--;

    SetPanel(StageNumber);
}

private void Next_Click(object sender, RoutedEventArgs e)
{
    NextStage();
}

private void Prev_Click(object sender, RoutedEventArgs e)
{
    PrevStage();
}


[アプリバーの自動表示]
マウスの右ボタンを押すか、画面の下端から上方向にスワイプすると、いつでもアプリバーが表示されます。
しかし、できればステージをクリアしたときに自動的にアプリバーを表示させたいものです。
アプリバーを自動的に表示させる方法はとても簡単で、以下の1文のコードを追加するだけです。
JudgeResultメソッドに、このコードを追加しています。

BottomAppBar1.IsOpen = true;


[ラインの移動数と所要時間の計測]
今回のプロジェクトを実行すると、左上に小さな文字列が表示されます。
今までもテスト用に座標などを表示していました。
今回もテスト用ですが、ラインの移動数と時間を表示するようにしています。

ラインの移動数は、

int MoveLineCount = 0;

というフィールドを定義しているので、ラインを動かすたびにこのフィールドの値を+1させます。

とはいえ、ラインを動かしたにもかかわらず結局宝石をもとの場所に戻したときや、続けて同じラインを動かしたときはラインの移動数を増やさないようにしています。
縦方向にラインを動かしたときは、以下のように直前に動かしたラインの番号であるPreviousMoveLineと、いま動かしたラインの番号を比較し、もしいま動かしたラインが直前に動かしたラインと同じであれば移動数を変更しないようにしています。

if (delta != 0)
{
    if (PressedPieceX != PreviousMoveLine)
    {
        MoveLineCount++;
        PreviousMoveLine = PressedPieceX;
    }
}

横方向にラインと動かしているときは、ラインの番号に20という適当な数値を足して、同じPreviousMoveLineフィールドを再利用しています。
今の方法だと、マス目の数が20x20を超えたときにうまく動かなくなります。
きれいなコードを書くのであれば、PreviousMoveLineXとPreviousMoveLineYの2つのフィールドを作るべきでした。
この部分は、完成版でも変わっていません。

所要時間は、ゲームを開始したときの時間をStartTimeというフィールドに入れ、ラインを動かすごとに現在の時間からStartTimeを引くことで経過時間を計算しています。
そして、GamePage_PointerReleasedイベントハンドラーの中で以下のように表示しています。

TimeSpan gameTime = DateTime.Now - StartTime;
testText.Text = "MoveLineCount : " + MoveLineCount.ToString() + "  /  " + gameTime.ToString();


[その他]
2013/2/3から2013/2/10までアメリカに出張しているので、その期間更新頻度が下がるかもしれません。


[前後の記事]
第4回 点滅セルの設定と合否判定
第6回 ハイスコアの記録と表示


マイクロソフト
田中達彦