C#で迷路をつくるの続きです。ゲームとして完成させます。
キー操作で現在位置を移動できるようにする
まずキー操作を可能にするためにOnKeyDownをオーバーライドします。現在位置がどこであるかわかるようにフィールド変数に格納します。最初はCurColum = 0、CurRow = 0です。スタート地点は左上です。
方向キーが押されたらその方向に移動できるか調べて移動できる場合は移動します。ゴールは右下です。ゴールしたら自作メソッドOnFinishを呼び出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public partial class Form1 : Form { int CurColum = 0; int CurRow = 0; protected override void OnKeyDown(KeyEventArgs e) { if (e.KeyCode == Keys.Left) MoveLeft(); if (e.KeyCode == Keys.Up) MoveUp(); if (e.KeyCode == Keys.Right) MoveRight(); if (e.KeyCode == Keys.Down) MoveDown(); Invalidate(); BranchPoint branch = MaseGenerator.BranchPoints.FirstOrDefault(x => x.Colum == CurColum && x.Row == CurRow); if (branch.Row == RowMax - 1 && branch.Colum == ColumMax - 1) OnFinish(); base.OnKeyDown(e); } void OnFinish() { // いまは特にすることはない } } |
左に移動できるかどうかを調べて移動できるなら移動する処理を示します。MaseGenerator.BranchPointsのなかから現在位置に相当するオブジェクトを探し出し、BranchPoint.MoveDirectsプロパティのなかからMoveDirect.Leftがあるか調べます。あれば移動可能です。CurColumをデクリントします。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { void MoveLeft() { BranchPoint branch = MaseGenerator.BranchPoints.FirstOrDefault(x => x.Colum == CurColum && x.Row == CurRow); if (branch != null) { if(branch.MoveDirects.Any(x => x == MoveDirect.Left)) CurColum--; } } } |
同様に上、右、下も以下のように処理をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public partial class Form1 : Form { void MoveUp() { BranchPoint branch = MaseGenerator.BranchPoints.FirstOrDefault(x => x.Colum == CurColum && x.Row == CurRow); if (branch != null) { if (branch.MoveDirects.Any(x => x == MoveDirect.Up)) CurRow--; } } void MoveRight() { BranchPoint branch = MaseGenerator.BranchPoints.FirstOrDefault(x => x.Colum == CurColum && x.Row == CurRow); if (branch != null) { if (branch.MoveDirects.Any(x => x == MoveDirect.Right)) CurColum++; } } void MoveDown() { BranchPoint branch = MaseGenerator.BranchPoints.FirstOrDefault(x => x.Colum == CurColum && x.Row == CurRow); if (branch != null) { if (branch.MoveDirects.Any(x => x == MoveDirect.Down)) CurRow++; } } } |
キーが押されたら再描画がおこなわれるのでOnPaintメソッドのなかで迷路を描画したあと赤い円で、現在位置を描画します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { protected override void OnPaint(PaintEventArgs e) { DrawMaze(e.Graphics); DrawEllipse(e.Graphics); base.OnPaint(e); } void DrawEllipse(Graphics graphics) { int radius = 5; SolidBrush brush = new SolidBrush(Color.Red); BranchPoint branch = MaseGenerator.BranchPoints.FirstOrDefault(x => x.Colum == CurColum && x.Row == CurRow); if (branch != null) { Rectangle rect = new Rectangle(branch.Point.X - radius, branch.Point.Y - radius, radius * 2, radius * 2); graphics.FillEllipse(brush, rect); } brush.Dispose(); } } |
それから新たに迷路が生成されたら現在位置をCurColum = 0、CurRow = 0に戻さないといけません。
1 2 3 4 5 6 7 8 9 10 |
public partial class Form1 : Form { void MaseGenerate() { CurColum = 0; CurRow = 0; MaseGenerator = new MaseGenerator(ColumMax, RowMax, Spacing, LeftMargin, TopMargin); } } |
タイマーを表示させる
さて、これだけではおもしろくないのでタイマーをつけます。
これを使います。
タイマーを表示するためにはTimerが必要です。それからデジタルっぽい表示をするためにリソースからBitmapを取得します。
InitTimerメソッドのなかでTimerの初期化とリソースからBitmapの取得をおこなっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public partial class Form1 : Form { Timer Timer = new Timer(); List<Image> ImageNumbers = new List<Image>(); Image ImageColon = Properties.Resources.colon; DateTime DateTimeStart = DateTime.Now; TimeSpan TimeSpan = TimeSpan.Zero; public Form1() { InitializeComponent(); this.DoubleBuffered = true; this.BackColor = Color.Black; CreateMenu(); MaseGenerate(); InitTimer(); } void InitTimer() { ImageNumbers.Add(Properties.Resources.number0); ImageNumbers.Add(Properties.Resources.number1); ImageNumbers.Add(Properties.Resources.number2); ImageNumbers.Add(Properties.Resources.number3); ImageNumbers.Add(Properties.Resources.number4); ImageNumbers.Add(Properties.Resources.number5); ImageNumbers.Add(Properties.Resources.number6); ImageNumbers.Add(Properties.Resources.number7); ImageNumbers.Add(Properties.Resources.number8); ImageNumbers.Add(Properties.Resources.number9); Timer.Interval = 1000 / 60; Timer.Tick += Timer_Tick; } } |
MaseGenerateメソッドが実行されたら、現在時刻をDateTimeStartに格納してTimerをスタートさせます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { void MaseGenerate() { // 現在位置を左上に戻す CurColum = 0; CurRow = 0; MaseGenerator = new MaseGenerator(ColumMax, RowMax, Spacing, LeftMargin, TopMargin); // 現在時刻をDateTimeStartに格納してTimerをスタートさせる DateTimeStart = DateTime.Now; Timer.Start(); } } |
ゴールについたらタイマーを止めます。
1 2 3 4 5 6 7 |
public partial class Form1 : Form { void OnFinish() { Timer.Stop(); } } |
Timer.Tickイベントが発生したらDateTimeStartからの経過時間を取得してTimeSpanに格納します。そして再描画をおこないます。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { TimeSpan = DateTime.Now - DateTimeStart; Invalidate(); } } |
再描画がおこなわれたら迷路と現在位置のほかにタイマーを表示させます。DrawTimeメソッドのなかではタイマーの各桁の値を求めてここから描画すべきBitmapを取得します。そしてこれを描画します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public partial class Form1 : Form { protected override void OnPaint(PaintEventArgs e) { DrawMaze(e.Graphics); DrawEllipse(e.Graphics); DrawTime(e.Graphics); base.OnPaint(e); } void DrawTime(Graphics graphics) { int minutes10 = TimeSpan.Minutes / 10; // 分 10の位 int minutes1 = TimeSpan.Minutes % 10; // 分 1の位 int seconds10 = TimeSpan.Seconds / 10; // 秒 10の位 int seconds1 = TimeSpan.Seconds % 10; // 秒 1の位 int milliseconds100 = TimeSpan.Milliseconds / 100; // 10分の1秒の位 int milliseconds10 = (TimeSpan.Milliseconds % 100) / 10; // 100分の1秒の位 // 0から順に格納されているのでインデックスをそのまま利用する Image imageMinutes10 = ImageNumbers[minutes10]; Image imageMinutes1 = ImageNumbers[minutes1]; Image imageSeconds10 = ImageNumbers[seconds10]; Image imageSeconds1 = ImageNumbers[seconds1]; Image imageMilliseconds100 = ImageNumbers[milliseconds100]; Image imageMilliseconds10 = ImageNumbers[milliseconds10]; // 適切な位置に描画する(aの値は各自で調整してください) int a = 22; graphics.DrawImage(imageMinutes10, new Rectangle(LeftMargin + a * 0, 330, 20, 40)); graphics.DrawImage(imageMinutes1, new Rectangle(LeftMargin + a * 1, 330, 20, 40)); graphics.DrawImage(ImageColon, new Rectangle(LeftMargin + a * 2, 330, 20, 40)); graphics.DrawImage(imageSeconds10, new Rectangle(LeftMargin + a * 3, 330, 20, 40)); graphics.DrawImage(imageSeconds1, new Rectangle(LeftMargin + a * 4, 330, 20, 40)); graphics.DrawImage(ImageColon, new Rectangle(LeftMargin + a * 5, 330, 20, 40)); graphics.DrawImage(imageMilliseconds100, new Rectangle(LeftMargin + a * 6, 330, 20, 40)); graphics.DrawImage(imageMilliseconds10, new Rectangle(LeftMargin + a * 7, 330, 20, 40)); } } |