スクランブルではUFOのステージが終わると水平方向に高速で飛ぶファイアボールが出現します。
この処理を追加します。
まずFireballクラスを示します。
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
public class Fireball { public Fireball(float x, float y) { X = x; Y = y; } public float X { get; private set; } public float Y { get; private set; } public bool isDead { get; set; } = false; static public float FireballSpeed = 0.8f; public void Move() { X -= FireballSpeed; } public void Draw() { if(!isDead) { GL.PushMatrix(); { GL.Translate(X, Y, 0); GL.Color3(Color.White); GL.BindTexture(TextureTarget.Texture2D, Form1.FireBallTexture); GL.Begin(BeginMode.Quads); { GL.TexCoord2(1, 1); GL.Vertex3(0.5, 0.3, 0); GL.TexCoord2(1, 0); GL.Vertex3(0.5, -0.3, 0); GL.TexCoord2(0, 0); GL.Vertex3(-0.5, -0.3, 0); GL.TexCoord2(0, 1); GL.Vertex3(-0.5, 0.3, 0); } GL.End(); GL.BindTexture(TextureTarget.Texture2D, 0); } GL.PopMatrix(); } } public RectangleF DeadRectangleF() { float x = X - 0.5f; float y = Y - 0.3f; float width = 1f; float height = 0.6f; return new RectangleF(x, y, width, height); } } |
StageクラスのUpdate()メソッドでファイアボールを生成して移動させます。
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 Stage { public void Update() { UpdateJikiPosition(); UpdateMissilesPosition(); UpdateUFOsPosition(); // ファイアボールを生成して移動させる CreateFireball(); UpdateFireballsPosition(); if(IsDead()) { Jiki.IsShow = false; // 自機死亡のイベントを発生させる JikiDead?.Invoke(this, new EventArgs()); return; } UpdateBulletsPosition(); GetObjectsHitBullet(); UpdateBombsPosition(); GetObjectsHitBomb(); } } |
実際にファイアボールを生成して移動させる処理を示します。
CreateFireball()メソッドはUpdate()メソッドが呼び出されるたびに実行されますが、実際に処理をおこなうのはファイアボールが出現するステージを通過中のときだけです。その場合も実際に処理を行なうのは5回に1回だけです(毎回ではファイアボールだらけになる)。
ファイアボール生成時のX座標は画面のすぐ右側、Y座標は乱数で決めます。
移動させるときは画面の左側に達したものはリストから取り除きます。また山に当たったものも取り除きます。ゲームを攻略するにはファイアボールが飛んでこない低空をうまく飛行する必要があります。
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 |
public class Stage { Random r = new Random(); int TickCountFireball = 0; void CreateFireball() { // ファイアボールが出現するステージを通過中のとき以外はなにもしない if(Form1.GetEyeX() > ThirdBegin && Form1.GetEyeX() < ForthBegin) { TickCountFireball++; if(TickCountFireball % 5 != 0) return; TickCountFireball = 0; float y = BlockAspect * (r.Next(15) - 6); Fireball fireball = new Fireball((float)Form1.GetEyeX() + Form1.ProjectionWidth / 2, y); Fireballs.Add(fireball); } } void UpdateFireballsPosition() { // 画面の左側に達したものはリストから取り除く Fireballs = Fireballs.Where(x => x.X > - Form1.ProjectionWidth / 2).ToList(); // 山に当たったファイアボールはリストから取り除く RemoveFireballsHitBlock(); foreach(Fireball fireball in Fireballs) fireball.Move(); } // 山に当たったファイアボールはリストから取り除く void RemoveFireballsHitBlock() { List<Block> blocks = GetTestBlocks(); foreach(Fireball fireball in Fireballs) { RectangleF rect1 = fireball.DeadRectangleF(); if(blocks.Any(x => IsPiledRectange(rect1, x.DeadRectangleF()))) fireball.isDead = true; } Fireballs = Fireballs.Where(x => !x.isDead).ToList(); } } |
描画の処理をするDraw()メソッドにファイアボールを描画する処理を追加します。
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 class Stage { public void Draw() { DrawGround(); foreach(Missile missile in Missiles) missile.Draw(); foreach(FuelTank fuelTank in FuelTanks) fuelTank.Draw(); foreach(UFO ufo in UFOs) ufo.Draw(); // ファイアボールを描画する foreach(Fireball fireball in Fireballs) fireball.Draw(); foreach(Bullet bullet in Bullets) bullet.Draw(); foreach(Bomb bomb in Bombs) bomb.Draw(); Jiki.Draw(); } } |
敵との接触を判定するIsDead()メソッドにファイアボールとの接触があったかどうか調べる処理を追加します。
それからミスをしたあとゲーム再開の処理をするときにFireballsリストをクリアします(しないとミス処理がおわってゲーム再開になった瞬間、ミスとなる)。
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 class Stage { bool IsDead() { RectangleF deadRect = Jiki.DeadRectangleF(); // 地面に接触または墜落 List<Block> blocks = GetTestBlocks(); if(blocks.Any(x => IsPiledRectange(deadRect, x.DeadRectangleF()))) return true; // ミサイルに接触 if(Missiles.Any(x => !x.isDead && IsPiledRectange(deadRect, x.DeadRectangleF()))) return true; // 燃料タンクに接触 if(FuelTanks.Any(x => !x.isDead && IsPiledRectange(deadRect, x.DeadRectangleF()))) return true; // UFOに接触 List<UFO> ufos = UFOs.Where(x => !x.isDead && IsInSight(x.X, x.Y)).ToList(); if(ufos.Any(x => IsPiledRectange(deadRect, x.DeadRectangleF()))) return true; // ファイアボールと接触 if(Fireballs.Any(x => !x.isDead && IsPiledRectange(deadRect, x.DeadRectangleF()))) return true; return false; } public bool Init() { Fireballs.Clear(); // 必要 // 他は以前と同じ } } |