
ゲーム・スクランブルでは地上にミサイルが設置されていて戦闘機にむけて発射されます。
Mと書かれている部分がミサイル設置地点です。

Missileクラスの作成
まずミサイルのクラスを作成します。
メソッド
void Fly()
上へむけて移動させる
void Draw(Graphics g)
パネル上に描画する
プロパティ
int initX, initY
最初に設置されている座標
int moveY
どれだけ上へ移動したか?
bool IsDead
破壊されているかどうか?
(破壊されていなくても、描画の必要がない場合はIsDead == true とする)
bool IsFlying
飛行中かどうか
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 class Missile { public Missile(Form1 form1, int x, int y) { initX = x; initY = y; MainForm = form1; } Form1 MainForm { get; set; } = null; public int initX { get; protected set; }= 0; public int initY { get; protected set; } = 0; public int moveY { get; protected set; } = 0; public void Fly() { if(!IsDead && IsFlying) moveY += 5; } public bool IsFlying { get; set; } } |
画面がスクロールされたり上へ移動した結果、表示する必要がなくなったら、IsDead = trueにします。
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 class Missile { bool isDead = false; public bool IsDead { get { if(isDead) return true; int displacement = MainForm.Jiki.Displacement; // 画面が左にスクロールされて左から画面外へ。表示の必要なし。 if((initX - displacement < -10)) isDead = true; // 上昇して上から画面外へ。表示の必要なし。 if(initY - moveY < -10) isDead = true; return isDead; } set { // 破壊されたら isDead = trueにする isDead = value; } } } |
以下はミサイルを描画するためのメソッドです。IsDead == trueなら表示の必要はありません。まだ発射されていないのであれば発射すべきかどうかも、ここで判定します。自機とミサイルの位置関係で判定していますが、すべてのミサイルが同じタイミングで発射されないように乱数を使っています。
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 class Missile { Bitmap Bitmap = Properties.Resources.missile; static Random r = new Random(); public void Draw(Graphics g) { // IsDead == trueなら表示の必要なし if(!IsDead) { int displacement = MainForm.Jiki.Displacement; g.DrawImage(Bitmap, new Point(initX - displacement, initY - moveY)); // ミサイルは飛ばすべきか? // 発射するかどうか? int rand2 = r.Next(20); if(rand2 != 0) return; // 自機とミサイルの位置関係から発射するかどうか決める Point point = GetJikiPosition(); if(initX - point.X - 100 < initY - point.Y) IsFlying = true; } } public Point GetJikiPosition() { return new Point(MainForm.Jiki.Displacement + MainForm.Jiki.X, MainForm.Jiki.Y); } } |
Topographyクラスの変更
ミサイルの設置位置は地形クラスで管理します。Mがミサイルの設置場所です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public class Topography { string topography0 = "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"; string topography1 = "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"; string topography2 = "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"; string topography3 = "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"; string topography4 = "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"; string topography5 = "□□□□□□□□□□▲△□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□"; string topography6 = "□□□□□□□□□▲■■△□□□□□□□□□□□□□□□□▲△□□□□□□□□□□□□□□"; string topography7 = "□□□□□□□□▲■■■■△□□□□□□□□□□□□□□▲■■△□□□□□□□□□□□□□"; string topography8 = "□□□□□□□▲■■■■■■△□M□MMMM□MMM□▲■■■■△□□□□□□□□□□□□"; string topography9 = "□□□□□□▲■■■■■■■■■■■■■■■■■■■■■■■■■■△□□□□□□□□□□□"; string topography10 = "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■△□□□□□□□□□□"; string topography11 = "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■△□MMMMMMMM"; string topography12 = "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"; string topography13 = "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"; string topography14 = "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"; } |
GetInitMissilePosition()メソッドは、ミサイルの設置座標を取得するためのメソッドです。
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 Topography { public List<Point> GetInitMissilePosition() { List<string> listTopography = GetListTopography(); List<Point> MissilePositions = new List<Point>(); // blockSizeとミサイルのサイズが違うので補正 Bitmap MissileBitmap = Properties.Resources.missile; int correction = MissileBitmap.Height - blockSize.Height; int y = 0; foreach(string str in listTopography) { Char[] vs = str.ToArray(); int x = 0; foreach(Char c in vs) { if(c == 'M') { Point pt = new Point(x * blockSize.Width, y * blockSize.Height - correction); MissilePositions.Add(pt); } x++; } y++; } return MissilePositions; } } |
その他のメソッド、プロパティ、フィールド変数は前回と同じです。
Form1クラスの変更
ゲームが開始されたらミサイルの設置位置を調べてミサイルの初期化をします。
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 { List<Missile> Missiles = new List<Missile>(); // ミサイルの設置位置を調べてリストに格納する void InitMissiles() { List<Point> missilePositions = Topography.GetInitMissilePosition(); Missiles = new List<Missile>(); foreach(Point pt in missilePositions) { Missiles.Add(new Missile(this, pt.X, pt.Y)); } } private void GameStartMenuItem_Click(object sender, EventArgs e) { Jiki.DoesShow = true; InitMissiles(); Timer.Start(); } } |
Tickイベントが発生したらすでに発射されているミサイルのY座標を上へ移動させます。panelEx1.Invalidate()が実行されたらイベントハンドラPanelEx1_Paintによって自機と地形、ミサイルが描画されます。
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 { private void Timer_Tick(object sender, EventArgs e) { TimerTick_JikiMove(); CheckIsDead(); foreach(Missile missile in Missiles) { // ここでミサイルの飛行中のY座標が変化する missile.Fly(); } panelEx1.Invalidate(); } 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); } } } |
鳩でも分かるC#管理人からのお願い
できる仕事であれば請け負います。鳩でもわかるC#管理人はクラウドワークスに在宅ワーカーとして登録しています。お仕事の依頼もお待ちしております。
⇒ 仕事を依頼する
コメントについて
コメントで英語などの外国語でコメントをされる方がいますが、管理人は日本語以外はわからないので基本的に内容が理解できず、承認することもありません。それからへんな薬を売っているサイトやリンク先のサイトが存在しないというスパムコメントも多々あります。
Some people make comments in foreign languages such as English, but since the manager does not understand anything other than Japanese, he basically cannot understand the content and does not approve it. Please use Japanese when making comments.
そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。
そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。
管理人のモチベーションアップのために
よろしければご支援お願いします。
⇒ 管理人の物乞いリスト