レーダースコープ特有のダメージメーターを表示させます。
フォーム下部に貼り付けているピクチャーボックスに表示させるBitmapを取得する処理を示します。
ダメージは32段階で緑と赤で表示します。また上部にDAMAGE METERと白で表記します。
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 { int Damage = 0; int DamageMax = 32; Bitmap GetDamageMeterBitmap(int damage) { Bitmap bitmap = new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height); Graphics graphics = Graphics.FromImage(bitmap); graphics.Clear(GameBackColor); string str = "DAMAGE METER"; Font font = new Font("MS ゴシック", 16, FontStyle.Bold); Size size = TextRenderer.MeasureText(graphics, str, font); int x = (bitmap.Width - size.Width) / 2; TextRenderer.DrawText(graphics, str, font, new Point(x, 0), Color.White); font.Dispose(); int y = size.Height + 10; int width = bitmap.Width / DamageMax; SolidBrush greenBrush = new SolidBrush(Color.LightGreen); SolidBrush redBrush = new SolidBrush(Color.Red); for (int i = 0; i < DamageMax; i++) { int x1 = i * bitmap.Width / DamageMax;; if (damage <= i) graphics.FillRectangle(greenBrush, new Rectangle(x1, y, width - 3, bitmap.Height)); else graphics.FillRectangle(redBrush, new Rectangle(x1, y, width - 3, bitmap.Height)); } greenBrush.Dispose(); redBrush.Dispose(); graphics.Dispose(); return bitmap; } } |
あとはゲームが開始されたら pictureBox1.Image = GetDamageMeterBitmap(0); を実行すればダメージメーターが表示されます。
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 |
public partial class Form1 : Form { protected override void OnLoad(EventArgs e) { InitForm(); Score = 0; GameManager.Init(); GameManager.MineLanding += GameManager_MineLanding; GameManager.JikiDead += GameManager_JikiDead; GameManager.Scored += GameManager_Scored; pictureBox1.Image = GetDamageMeterBitmap(0); base.OnLoad(e); } private void GameManager_MineLanding() { Damage++; pictureBox1.Image = GetDamageMeterBitmap(Damage); } } |
それから本当のレーダースコープでは自機がやられるとダメージはリセットしてしまうのですが、これではドキドキ感がないので(実際のところダメージメーターがフルになったのを見たことがない!)、自機がやられてもダメージメーターはリセットされないことにして、ダメージメーターがいっぱいのときに機雷を打ち漏らすと1機を失うことにします。ステージクリアのときはリセットされることにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { private void GameManager_MineLanding() { Damage++; if (Damage > DamageMax) { GameManager.OnJikiDead(); pictureBox1.Image = GetDamageMeterBitmap(0); Damage = 0; } else pictureBox1.Image = GetDamageMeterBitmap(Damage); } } |
それからステージクリアのときはダメージをリセットする処理を追加します。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { private void GameManager_StageCleared() { Damage = 0; pictureBox1.Image = GetDamageMeterBitmap(Damage); } } |
ゲームオーバーになったらゲームオーバーの表示をして再プレイするための方法を表示させます。
デザイナでLabelを2つフォーム上にドラッグアンドドロップしてInitFormメソッドを以下のように変更します。
このなかではダメージメーターとGAME OVER、Press S key to Retryと表示させるLabelを中央に表示させるためにX座標を取得しています。
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 41 42 43 44 45 46 47 48 |
public partial class Form1 : Form { Color GameBackColor = Color.DarkBlue; void InitForm() { Size controlSize = new Size(620, 430); glControlEx1.Location = new Point(0, 0); glControlEx1.Size = controlSize; glControlEx1.BackColor = GameBackColor; GL.ClearColor(GameBackColor); label1.AutoSize = true; label1.Location = new Point(10, 10); label1.Font = new Font("MS ゴシック", 16, FontStyle.Bold); label1.Text = ""; label1.BackColor = GameBackColor; label1.ForeColor = Color.White; label2.AutoSize = true; label2.Font = new Font("MS ゴシック", 36, FontStyle.Bold); label2.Text = "GAME OVER"; label2.BackColor = GameBackColor; label2.ForeColor = Color.White; // 中央に表示させるためのX座標を取得する int x2 = (controlSize.Width - label2.Size.Width) / 2; label2.Location = new Point(x2, 170); label2.Visible = false; label3.AutoSize = true; label3.Font = new Font("MS ゴシック", 18, FontStyle.Bold); label3.Text = "Press S key to Retry"; label3.BackColor = GameBackColor; label3.ForeColor = Color.White; int x3 = (controlSize.Width - label3.Size.Width) / 2; label3.Location = new Point(x3, 240); label3.Visible = false; Size damageMeterSize = new Size(500, 60); int damageMeterX = (controlSize.Width - damageMeterSize.Width)/2; pictureBox1.Location = new Point(damageMeterX, 360); pictureBox1.Size = damageMeterSize; // フォームのサイズを変更すると表示されない部分が出るのでサイズ変更不可にする this.Size = new Size(637, 468); this.FormBorderStyle = FormBorderStyle.FixedSingle; } } |
次にIsGameOverプロパティを作成してtrueのときだけこれを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { bool _isGameOver = false; bool IsGameOver { get { return _isGameOver; } set { _isGameOver = value; label2.Visible = _isGameOver; label3.Visible = _isGameOver; } } } |
Sキーが押されたらもう一度ゲームができるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { protected override void OnKeyDown(KeyEventArgs e) { if (e.KeyCode == Keys.Left) GameManager.MoveLeft = true; if (e.KeyCode == Keys.Right) GameManager.MoveRight = true; if (e.KeyCode == Keys.Space) GameManager.Shot(); if (e.KeyCode == Keys.S) Retry(); base.OnKeyDown(e); } void Retry() { IsGameOver = false; Score = 0; Damage = 0; pictureBox1.Image = GetDamageMeterBitmap(Damage); GameManager.GameRetry(); } } |
ステージクリアしたら次のステージでは敵の動きを速くしたり複雑化するなど課題はたくさんあるけど、とりあえず完成!