モグラ叩き兼タイピング練習ソフトを作ります。
モグラはキーボードのキーの位置に対応する位置に文字とともに現れます。そしてキーを押すと消滅します。
リソース
ではまずモグラを表示させるためのクラスを作成しましょう。
モグラは文字に合わせて出現場所が変わります。文字は乱数で決めますが、直接文字を指定して生成することもできるようにコンストラクタは2種類つくります。キーボード上のキーの位置とあわせていますが、上と左に少しスペースを空けたいので、その値をFieldクラスの静的フィールド変数で定義しておきます。
1 2 3 4 5 |
public class Field { static public int TopMargin = 50; static public int LeftMargin = 20; } |
Moguraクラスのフィールド変数とコンストラクタは以下のとおり。
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 |
public class Mogura { string[] first = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "^", }; string[] second = { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "@", "[", }; string[] third = { "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", ":", "]", }; string[] forth = { "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "\\", }; int _x = 0; int _y = 0; public int Width = 50; public int Height = 80; Bitmap _mogura = Properties.Resources.mogura; public Mogura(Random random) { String = GetString(random); Bitmap = CreateBitmap(); } public Mogura(string str) { String = str; GetPos(str); Bitmap = CreateBitmap(); } } |
GetPos(string str)は、文字からモグラの表示位置を求めるメソッドです。
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 |
public class Mogura { void GetPos(string str) { int index = first.ToList().IndexOf(str); if(index != -1) { _y = 0; _x = index; } index = second.ToList().IndexOf(str); if(index != -1) { _y = 1; _x = index; } index = third.ToList().IndexOf(str); if(index != -1) { _y = 2; _x = index; } index = forth.ToList().IndexOf(str); if(index != -1) { _y = 3; _x = index; } } } |
GetString(Random random)は、乱数から文字を取得し、モグラの表示位置も同時に求めるメソッドです。
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 |
public class Mogura { string GetString(Random random) { string str = ""; _y = random.Next(0, 4); if(_y == 0) { _x = random.Next(0, first.Length); str = first[_x]; } if(_y == 1) { _x = random.Next(0, second.Length); str = second[_x]; } if(_y == 2) { _x = random.Next(0, third.Length); str = third[_x]; } if(_y == 3) { _x = random.Next(0, forth.Length); str = forth[_x]; } return str; } } |
文字が決定したら、次にモグラと文字を合成したビットマップイメージを作成します。このときに最終的な表示位置を確定させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class Mogura { Bitmap CreateBitmap() { Bitmap bitmap = new Bitmap(Width, Height); Graphics g = Graphics.FromImage(bitmap); // 元のイメージは 450px * 250px int height = 50 * _mogura.Height / _mogura.Width; g.DrawImage(_mogura, new Rectangle(0, 0, 50, height)); g.DrawString(String, new Font("MS ゴシック", 16, FontStyle.Bold), new SolidBrush(Color.White), new Point(15, height)); g.Dispose(); // どこに表示する? PosX = Field.LeftMargin + 50 * _x; PosY = Field.TopMargin + 50 * _y; return 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 |
public class Mogura { public int PosX { private set; get; } public int PosY { private set; get; } public Bitmap Bitmap { private set; get; } public string String { private set; get; } } |
Dispose()は、いらなくなったオブジェクトを破棄するためのメソッドです。
1 2 3 4 5 6 7 |
public class Mogura { public void Dispose() { Bitmap.Dispose(); } } |
モグラを叩くためのピコピコハンマーを表示させるためのクラスも作成します。
フィールド変数は以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class Hammer { string[] first = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "^", }; string[] second = { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "@", "[", }; string[] third = { "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", ":", "]", }; string[] forth = { "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "\\", }; int _x = 0; int _y = 0; public int Width = 50; public int Height = 50; } |
コンストラクタ内でリソースからハンマーのビットマップイメージを生成します。それから渡された文字列からどの位置にハンマーを表示させるのかも計算します。そしてプロパティで取得できるようにします。
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 |
public class Hammer { public Hammer(string str) { Bitmap hammer = Properties.Resources.Hammer; Bitmap bitmap = new Bitmap(Width, Height); Graphics g = Graphics.FromImage(bitmap); g.DrawImage(hammer, new Rectangle(0, 0, Width, Height)); g.Dispose(); Bitmap = bitmap; int index = first.ToList().IndexOf(str); if(index != -1) { _y = 0; _x = index; } index = second.ToList().IndexOf(str); if(index != -1) { _y = 1; _x = index; } index = third.ToList().IndexOf(str); if(index != -1) { _y = 2; _x = index; } index = forth.ToList().IndexOf(str); if(index != -1) { _y = 3; _x = index; } // どこに表示する? PosX = Field.LeftMargin + 50 * _x; PosY = Field.TopMargin + 50 * _y - 20; // 20 = モグラより少し上に表示する } } |
以下は、ハンマーの最終的な表示位置、ビットマップイメージを取得するためのプロパティです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class Hammer { public int PosX { private set; get; } public int PosY { private set; get; } public Bitmap Bitmap { private set; get; } } |
Dispose()は、いらなくなったオブジェクトを破棄するためのメソッドです。
1 2 3 4 5 6 7 |
public class Hammer { public void Dispose() { Bitmap.Dispose(); } } |
あとはこれらを使ってアプリケーションを作成します。ためしにすべてのモグラを表示させてみます。
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 49 50 51 52 53 54 |
public partial class Form1 : Form { // debug List<Mogura> Moguras = new List<Mogura>(); public Form1() { InitializeComponent(); this.ImeMode = ImeMode.Disable; this.BackColor = Color.FromArgb(0, 0, 0); Moguras = CreateAllMoguras(); } List<Mogura> CreateAllMoguras() { List<Mogura> moguras = new List<Mogura>(); string[] first = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "^", }; string[] second = { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "@", "[", }; string[] third = { "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", ":", "]", }; string[] forth = { "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "\\", }; foreach(var s in first) moguras.Add(new Mogura(s)); foreach(var s in second) moguras.Add(new Mogura(s)); foreach(var s in third) moguras.Add(new Mogura(s)); foreach(var s in forth) moguras.Add(new Mogura(s)); return moguras; } protected override void OnPaint(PaintEventArgs e) { ShowAllMoguras(e.Graphics); } void ShowAllMoguras(Graphics g) { foreach(var m in Moguras) { Bitmap bitmap = m.Bitmap; // ビットマップの背景が緑なのでこの部分は透明にする bitmap.MakeTransparent(Color.FromArgb(0, 128, 0)); g.DrawImage(bitmap, new Point(m.PosX, m.PosY)); } } } |
試運転はうまくいったので、実際にモグラを一体ずつ出して叩いていくことにします。
フィールド変数とコンストラクタは以下のとおりです。コンストラクタ内で背景を黒にして、乱数とタイマーの初期化をしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { Timer Timer = new Timer(); Random Random = null; public Form1() { InitializeComponent(); Random = new Random((int)DateTime.Now.Ticks); this.ImeMode = ImeMode.Disable; this.BackColor = Color.FromArgb(0, 0, 0); Timer.Interval = 3000; Timer.Tick += Timer_Tick; Timer.Start(); } } |
以下はモグラが顔を出しているか、ハンマーが存在するかを示すプロパティです。
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 |
public partial class Form1 : Form { Mogura _mogura = null; Mogura Mogura { set{ if(_mogura != null) _mogura.Dispose(); _mogura = value; } get{ return _mogura; } } Hammer _hammer = null; Hammer Hammer { set { if(_hammer != null) _hammer.Dispose(); _hammer = value; } get { return _hammer; } } } |
Tickイベントが発生したら乱数オブジェクトをMoguraクラスのコンストラクタに渡してモグラを生成します。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { Mogura = new Mogura(Random); this.Invalidate(); } } |
キーが押されたら対応する部分にハンマーを表示します。そしてその位置にモグラがいたら(Moguraオブジェクトがが存在し、e.KeyChar.ToString() と Mogura.String が一致していたら)モグラを消滅させるために Mogura = null;としてInvalidate()を実行します(空振りでもハンマーを表示させる必要があるので Invalidate()の実行は必要)。
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 OnKeyPress(KeyPressEventArgs e) { Hammer = new Hammer(e.KeyChar.ToString()); if(Mogura != null) { string str = Mogura.String; if(str == e.KeyChar.ToString()) { OnHit(); } } Invalidate(); base.OnKeyPress(e); } void OnHit() { Mogura = null; } } |
キーが離されたらハンマーは消滅します。
1 2 3 4 5 6 7 8 9 10 |
public partial class Form1 : Form { protected override void OnKeyUp(KeyEventArgs e) { Hammer = null; Invalidate(); base.OnKeyUp(e); } } |
最後に描画のためのOnPaint(PaintEventArgs e)を示します。MoguraオブジェクトとHammerオブジェクトが存在するのであれば描画します。一応、モグラ叩きゲームの原形部分は完成です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { protected override void OnPaint(PaintEventArgs e) { if(Mogura != null) { Bitmap bitmap = Mogura.Bitmap; bitmap.MakeTransparent(Color.FromArgb(0, 128, 0)); e.Graphics.DrawImage(bitmap, new Point(Mogura.PosX, Mogura.PosY)); } if(Hammer != null) { Bitmap bitmap = Hammer.Bitmap; bitmap.MakeTransparent(Color.FromArgb(0, 128, 0)); e.Graphics.DrawImage(bitmap, new Point(Hammer.PosX, Hammer.PosY)); } } } |