では敵の戦車を登場させ、砲撃・破壊することができるようになりました。今回は敵の戦車の数を増やします。ただこれではすぐに撃たれてしまうので、自分の戦車が破壊されてもしばらくしたら復活して戦うことができるようにしました。
メニューの[スタート]を選択すると、敵の戦車が生成されてリスト内に格納され、ゲームが開始されます。
ゲーム再開のときは自分の戦車の位置や状態ももとに戻す必要があります。また視界の設定ももとに戻す必要があります。
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 partial class Form1 : Form { List<EnemyTank> EnemyTanks = new List<EnemyTank>(); public Form1() { InitializeComponent(); ShowLabel(); Tank.Color = Color.Red; InitFloors(); InitTimer(); } void InitTimer() { timer.Interval = 50; timer.Tick += Timer_Tick; } private void StartMenuItem_Click(object sender, EventArgs e) { Start(); } void Start() { EnemyTanks.Clear(); // とりあえず敵は6台とする EnemyTanks.Add(new EnemyTank(this, 8, -8, Color.Blue, 0)); EnemyTanks.Add(new EnemyTank(this, 3, -8, Color.Blue, 0)); EnemyTanks.Add(new EnemyTank(this, -3, -8, Color.Blue, 0)); EnemyTanks.Add(new EnemyTank(this, -8, -8, Color.Blue, 0)); EnemyTanks.Add(new EnemyTank(this, 3, -16, Color.Blue, 0)); EnemyTanks.Add(new EnemyTank(this, -3, -16, Color.Blue, 0)); // 視界をもとに戻す ResetSight(); // 自分の戦車の位置・方向・状態をもとに戻す ResetMyTank(); // 爆発する予定のオブジェクトはクリアする SmallExplosions.Clear(); Explosions.Clear(); timer.Start(); } void ResetSight() { EyeX = 0f; EyeY = 1f; EyeZ = 2.5f; TargetX = 0f; TargetY = 1f; TargetZ = 0f; } void ResetMyTank() { X = 0; Y = 0; Z = 0; RotateY = 180; Tank.isDead = false; Tank.Bullets.Clear(); } } |
敵の位置変更や動作に関する処理はUpdate()メソッドでおこないます。もし自分の戦車が死んでいる場合は敵の戦車は動かないようにします。ただし、すでに発射され飛んでいる砲弾は飛び続けます。そして死んだ自分の戦車は3秒後に生き返ります(敵が多いとこうでもしないとすべて倒せない)。
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 74 75 76 77 78 |
public partial class Form1 : Form { new void Update() { foreach(Bullet bullet in Tank.Bullets) bullet.Move(); foreach(EnemyTank enemyTank in EnemyTanks) { // 死んだ戦車は動かす必要はない // 自分の戦車が死んでいる場合もすべての戦車は停止する if(!enemyTank.isDead && !Tank.isDead) enemyTank.Move(); // 敵の戦車が発射した砲弾を移動させる foreach(Bullet bullet in enemyTank.Bullets) bullet.Move(); // 敵の戦車が発射した砲弾で自分の戦車に命中したものはあるか? Bullet bullet1 = enemyTank.Bullets.FirstOrDefault(x => !x.isDead && Tank.IsBombed(x)); if(bullet1 != null) { // 命中した砲弾は取り除く enemyTank.Bullets.Remove(bullet1); // ここで爆破する Explosions.Add(new Explosion(Tank.X, Tank.Z)); // この部分が実行されるということは、自分の戦車が殺されたということなので // 生き返るためのタイマーをセットする(3秒後に復活する) Timer timer1 = new Timer(); timer1.Interval = 3000; timer1.Tick += Timer1_Tick1; timer1.Start(); } // 自分の戦車が発射した砲弾で敵の戦車に命中したものはあるか? Bullet bullet2 = Tank.Bullets.FirstOrDefault(x => !x.isDead && enemyTank.IsBombed(x)); if(bullet2 != null) { // 命中した砲弾は取り除く Tank.Bullets.Remove(bullet2); // ここで爆破する Explosions.Add(new Explosion(enemyTank.X, enemyTank.Z)); } // 敵の戦車が発射した砲弾のなかに着弾したものは? List<Bullet> enemyBullets1 = enemyTank.Bullets.Where(x => x.Y <= 0).ToList(); // ここで小爆発を発生させる List<SmallExplosion> smallExplosions1 = enemyBullets1.Select(x => new SmallExplosion(x.X, x.Z)).ToList(); SmallExplosions.AddRange(smallExplosions1); } // 自分の戦車が発射した砲弾のなかに着弾したものは? List<Bullet> Bullets2 = Tank.Bullets.Where(x => x.Y <= 0).ToList(); // ここで小爆発を発生させる List<SmallExplosion> smallExplosions2 = Bullets2.Select(x => new SmallExplosion(x.X, x.Z)).ToList(); SmallExplosions.AddRange(smallExplosions2); // 描画する必要がないものはここで取り除く EnemyTanks = EnemyTanks.Where(x => !x.isDead).ToList(); Explosions = Explosions.Where(x => !x.isDead).ToList(); SmallExplosions = SmallExplosions.Where(x => !x.isDead).ToList(); } private void Timer1_Tick1(object sender, EventArgs e) { Timer t = (Timer)sender; t.Stop(); t.Dispose(); // 自分の戦車を生き返らせる Tank.isDead = false; } } |
これまでは描画する必要がないものをglControl_Paint(object sender, PaintEventArgs e)メソッド内で取り除いていましたが、今回は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 |
public partial class Form1 : Form { private void glControl_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); SetSight(); if(!Tank.isDead) Tank.Draw(); foreach(EnemyTank tank in EnemyTanks) tank.Draw(); foreach(Floor floor in Floors) floor.Draw(); foreach(Explosion explosion in Explosions) explosion.Draw(); foreach(SmallExplosion explosion in SmallExplosions) explosion.Draw(); glControl.SwapBuffers(); } } |