自機から弾丸を発射し、敵に命中したときは命中処理を行ないます
Zキーが押されたら弾丸を発射します。弾丸の発射はJiki.Shotメソッドで処理をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { // 発射された弾丸を格納するリスト List<Point> bulletList = new List<Point>(); private void Form1_KeyDown(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.Up) JikiDirect = JikiDirect.Up; if(e.KeyCode == Keys.Down) JikiDirect = JikiDirect.Down; if(e.KeyCode == Keys.Left) JikiDirect = JikiDirect.Left; if(e.KeyCode == Keys.Right) JikiDirect = JikiDirect.Right; if(e.KeyCode == Keys.Z) Jiki.Shot(bulletList); } } |
自機は80×30ピクセルで表示されているので自機が表示されるX座標に80、Y座標に15を加算したものでPointを作成し、List
1 2 3 4 5 6 7 8 9 |
public class Jiki { public void Shot(List<Point> bulletList) { // 自機は80×30ピクセルで表示されているので bulletList.Add(new Point(X + 80, Y + 15)); } } |
発射された弾丸の移動はForm1クラス内で行ないます。
Tickイベントが発生したら、弾丸を前へ10移動させます。そして地形に当たったりフィールドの右端から外へ出たものは取り除きます。
以下は地形に当たった弾丸を取り除くメソッドです。
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 { void RemoveBalletsHitTopography() { Rectangle[] rects = Topography.GetRectangles(); List<Point> removePoints = new List<Point>(); foreach(Point pt in bulletList) { Rectangle rect1 = new Rectangle(pt, GetBulletSize()); foreach(Rectangle rect2 in rects) { if(rect1.Bottom < rect2.Top || rect1.Top > rect2.Bottom || rect1.Right < rect2.Left || rect1.Left > rect2.Right) { // 自機から放たれた弾丸は命中していない } else { removePoints.Add(pt); break; } } } foreach(Point pt in removePoints) bulletList.Remove(pt); } } |
またRemoveBalletsOutOfField()メソッドはフィールドの右端から外へ出たものは取り除くためのメソッドです。
1 2 3 4 5 6 7 |
public partial class Form1 : Form { void RemoveBalletsOutOfField() { bulletList = bulletList.Where(x => x.X < panelEx1.Width).ToList(); } } |
RemoveBalletsHitMissile()メソッドは自機の弾丸が敵のミサイルに命中したかどうかを調べ、命中したミサイルに死亡フラグをセットするとともに、命中した弾丸を取り除くメソッドです。
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 |
public partial class Form1 : Form { // 敵ミサイルを撃墜したときのイベント public event EventHandler HitMissile; void RemoveBalletsHitMissile() { foreach(Missile missile in Missiles) { if(missile.IsDead) continue; missile.Fly(); int hitIndex = -1; foreach(Point pt in bulletList) { Rectangle rect = new Rectangle(pt, GetBulletSize()); if(rect.Bottom < missile.DeadRectangle.Top || rect.Top > missile.DeadRectangle.Bottom || rect.Right < missile.DeadRectangle.Left || rect.Left > missile.DeadRectangle.Right) { // 自機から放たれた弾丸は命中していない } else { missile.IsDead = true; hitIndex = bulletList.IndexOf(pt); HitMissile?.Invoke(this, new EventArgs()); break; } } if(hitIndex != -1) bulletList.RemoveAt(hitIndex); } } Size GetBulletSize() { return new Size(5, 2); } } |
MissileクラスのDeadRectangleはミサイルの当たり判定用の矩形を取得するためのプロパティです。
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Missile { public Rectangle DeadRectangle { get { int displacement = MainForm.Jiki.Displacement; Point pt = new Point(initX - displacement, initY - moveY); return new Rectangle(pt, new Size(Bitmap.Width, Bitmap.Height)); } } } |
Tickイベントが発生したら飛行中の敵ミサイルを移動させ、自機から発射された弾丸がある場合は、これを前(右)に10ピクセル移動させます。そして当たり判定をおこないます。
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 partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { TimerTick_JikiMove(); FlyingMissilesMove(); panelEx1.Invalidate(); // 弾丸を前へ移動させる bulletList = bulletList.Select(x => new Point(x.X + 10, x.Y)).ToList(); // 命中した弾丸は取り除く RemoveBalletsHitTopography(); RemoveBalletsOutOfField(); RemoveBalletsHitMissile(); CheckIsDead(); } // 飛行中のミサイルを上昇(見た目は斜め上方に移動)させる void FlyingMissilesMove() { foreach(Missile missile in Missiles) { if(missile.IsDead) continue; missile.Fly(); } } } |
最後にPanelEx1でPaintイベントが発生したら描画処理を行ないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { private void PanelEx1_Paint(object sender, PaintEventArgs e) { // 自機を描画する Jiki.Show(e.Graphics); // 地形を描画する Topography.Show(e.Graphics); // ミサイルを描画する foreach(Missile missile in Missiles) missile.Draw(e.Graphics); // 自機から発射された弾丸を描画する foreach(Point pt in bulletList) { e.Graphics.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(pt.X, pt.Y), GetBulletSize())); } } } |