SLGBaseで戦術級シミュレーションゲームを作ってみる

5.テスト用UIおよびテストデータの作成

最終更新:

slgbase

- view
管理者のみ編集可
※これまでの実装結果を確認できるよう、ユーザインターフェースを作成します。
この工程は、本来はSLGBaseライブラリとは関係のない部分です。
なぜなら実際のゲーム開発には個々の開発者によってDirectXやOpenGL、SDL
その他の描画用ライブラリが使用され、WindowsFormsは使用しないことが
予想されるためです。
SLGBaseライブラリはあくまでも内部的なデータ処理のために開発されています
ので、 その上にどのようなユーザインターフェースやゲームシステムを構築
するかは個々の開発者に委ねられています。
本チュートリアルでは、SLGBaseの基本機能が確認できるよう、WindowsFormsを
使用して可能な限りシンプルな内容の実装を行います。

繰り返しますが、あなたがゲームを作る際には、必ずしもこの章の内容に沿って
WindowsFormsで作る必要はありません。

5-1.テスト用のフォームを作成します。

Form1に、PictureBox,HScrollBar,VScrollBarを一つずつ貼り付けます。
名前はそれぞれpictureBox1,hScrollBar1,vScrollBar1となります。
フォームサイズを変更しても大丈夫なように、各コントロールのAnchorプロパティを適切に設定しておくと良いでしょう。
(ピクチャボックスは全方向、HScrollBarは左右下、VScrollBarは上下右)
また、理由は後で述べますが各スクロールバーのLargeChangeプロパティを1に設定しておいてください。

#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (フォーム.jpg)

5-2.Form1.csにマップオブジェクトを追加する

Form1.csに、マップオブジェクトを追加し、初期化処理を行います。
テスト用に、ユニットを一つ追加します。
マップ上に配置するユニットは、MapクラスのUnitsメンバに追加します。これは必須ではありませんが、後に戦術判断処理を行う際に重要になってきます。

Form1.cs(の一部)
public partial class Form1 : Form
    {
        private Map _map = new Map();       //add 5-2
 
        public Form1(){ -- }
 
        //add 5-2
        private void Form1_Load(object sender, EventArgs e)
        {
            _map = new Map();
            _map.Init(50, 50);
 
            Unit u = new Unit();
            u.SetPos(5, 5);
            _map.Units.Add(u);
 
            hScrollBar1.Maximum = _map.Cols;
            vScrollBar1.Maximum = _map.Rows;
 
            pictureBox1.Invalidate();
        }
    }
 
処理の最後にピクチャボックスを再描画し、pictureBox1.Paint()イベント内で地図描画を行うための準備をしておきます。


5-3.マップ描画処理

Mapクラス内に、ピクチャボックスの情報を受け取ってその上に情報を描画するためのDraw()メソッドを用意します。また、その際に必要となる座標変換メソッドも用意します。
Map.csのusing節にFormコントロールとグラフィックス関連の宣言を追加することを忘れないでください。

セルはとりあえず64*64ピクセルのマス目で描くこととし、そのサイズはCellクラスで定義しておきます。

Cell.cs(一部)
public class Cell:CellBase
    {
        //add 5-3
        public static int Width = 64;
        public static int Height = 64;
    }
 

Map.cs(一部)
using System.Windows.Forms;     //add 5-3
using System.Drawing;           //add 5-3
 
namespace SLGTest
{
    //add 3-1
    public class Map: MapBase
    {
 
        //add 5-3
        /// <summary>
        /// マップ描画中心セル
        /// </summary>
        public Position ViewCenter { get; set; }
 
        public void Init(int cols, int rows)
        {
            // - 略 - 
 
            ViewCenter = new Position();        //add 5-3
        }
 
        //add 5-3
        public void Draw(PictureBox pic, Graphics g)
        {
            g.Clear(Color.White);
 
            //セルの表示サイズを基準にして表示範囲を計算
 
            //縦横の表示可能セル数を計算
            int h = pic.Height / Cell.Height;
            int w = pic.Width / Cell.Width;
 
            for (int x = ViewCenter.X - w / 2 - 1; 
                 x <= ViewCenter.X + w / 2 + 1; x++)
                for (int y = ViewCenter.Y - h / 2 - 1; 
                      y <= ViewCenter.Y + h / 2 + 1; y++)
                {
                    if (x >= 0 && x < Cols && y >= 0 && y < Rows)
                    {
                        Position p = Cell2View(pic, GetCell(x, y));
                        g.DrawRectangle(Pens.Green, p.X, p.Y, 
                               Cell.Width, Cell.Height);
                    }
                }
        }
 
        //add 5-3
        /// <summary>
        /// 指定のセルが画面上のどの座標に表示されるかを返す
        /// </summary>
        /// <param name="map"></param>
        /// <param name="pic"></param>
        /// <param name="cell"></param>
        /// <returns></returns>
        public Position Cell2View(PictureBox pic, Position cell)
        {
            return (new Position(
                    (pic.Width - Cell.Width) / 2 + 
                         (cell.X - ViewCenter.X) * Cell.Width,
                    (pic.Height - Cell.Height) / 2 + 
                         (cell.Y - ViewCenter.Y) * Cell.Height
                    )
                );
        }
 
        //add 5-3
        /// <summary>
        /// 画面上の座標がどのセルに該当するかを返す
        /// </summary>
        /// <param name="pic"></param>
        /// <param name="pixelPos"></param>
        /// <returns></returns>
        public Position View2Cell(PictureBox pic, Position pixelPos)
        {
            return (new Position(
                    (int)(ViewCenter.X + (pixelPos.X - 
                      (pic.Width - Cell.Width) / 2.0) / Cell.Width),
                    (int)(ViewCenter.Y + (pixelPos.Y - 
                      (pic.Height - Cell.Height) / 2.0) / Cell.Height)
                    )
                );
        }
    }
}
 


その後、ピクチャボックスのPaint()イベント内から描画処理を呼び出します。
また、ユーザがスクロールバーを操作した際も表示が更新されるよう、各スクロールバーのScroll()イベント内でもピクチャボックスを再描画します。
当然ですが、各イベントのコードはコントロールの該当するイベントに関連付けておいてください。

※スクロールバーのLargeChangeプロパティは1に設定しておかないと末尾まで
スクロールしないことがあります。これは.NetFrameworkの仕様なのでチェックが
必要です。

Form1.cs(一部)
//add 5-3
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            //表示中心セルを指定
            _map.ViewCenter.SetPos(hScrollBar1.Value, vScrollBar1.Value);
 
            //描画
            _map.Draw(pictureBox1, e.Graphics);
        }
 
 
        //add 5-3
        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            pictureBox1.Invalidate();
        }
 
        //add 5-3
        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            pictureBox1.Invalidate();
        }
 


5-4.実行結果とここまでのプロジェクト

#ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (マップ描画.jpg)
スクロールバーを操作するとマップ上を移動します。

ウィキ募集バナー