今回は敵キャラをつくります。そして自機を追わせます。
自機を追わせるには自機に関する情報(フィールドのどこにいるのか?どちらにどれくらいの移動量で移動しているのかなど)が必要です。そこで以下のようなクラスをつくります。
1 2 3 4 5 6 7 8 9 10 |
public class JikiInfo { public float X = 0; public float Y = 0; public float VecX = 0; public float VecY = 0; public float Speed = 0; public float Radius = 0; public bool IsDead = false; } |
他にも必要なものが出てくるかもしれませんが、とりあえず今はこれだけにしておきます。
Form1クラス内にも自機に関する情報を取得できるメソッドを用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using OpenTK; using OpenTK.Graphics.OpenGL; public partial class Form1 : Form { public JikiInfo GetJikiInfo() { JikiInfo info = new JikiInfo(); info.X = Jiki.X; info.Y = Jiki.Y; info.VecX = Jiki.VecX; info.VecY = Jiki.VecY; info.Speed = JikiSpeed; info.Radius = JikiRadius; info.IsDead = Jiki.IsDead; return info; } } |
では敵のクラスをつくります。敵は1種類だけではないので敵の基底クラスをつくってそこから派生クラスをつくるようにします。
EnemyBaseクラスを示します。GetJikiInfo()メソッドを呼び出すことができるようにForm1クラスのインスタンスを渡しています。
1 2 3 4 5 6 7 8 9 10 |
using OpenTK; using OpenTK.Graphics.OpenGL; class EnemyBase:Character { public EnemyBase(Form1 form1, float x, float y, float vecX, float vecY) : base(form1, x, y, vecX, vecY) { } } |
次にEnemy1クラスを示します。GetJikiInfo()メソッドを呼び出すことができるようにForm1クラスのインスタンスを渡しています。オーバーライドされたUpdate()メソッドのなかでForm1.GetJikiInfo()メソッドで得られた自機の情報から自身の移動方向を求めます。移動方向は自機が次回の方向転換のときまでそのまままっすぐに移動したと仮定して、その位置と現在の敵機の座標からMath.Atan2メソッドで求めます。
敵機のXY方向それぞれの移動量が決まったら、あとは基底クラスの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 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 |
using OpenTK; using OpenTK.Graphics.OpenGL; class Enemy1 : EnemyBase { public Enemy1(Form1 form1, float x, float y, float vecX, float vecY) : base(form1, x, y, vecX, vecY) { if (Textures.Count == 0) Textures = CreateTextures(); Radius = Config.EnemyRadius; } static List<int> Textures = new List<int>(); protected override List<Bitmap> GetBitmaps() { List<Bitmap> bitmaps = new List<Bitmap>(); Bitmap bitmap = Properties.Resources.enemy1; bitmap.MakeTransparent(); bitmaps.Add(bitmap); return bitmaps; } public override void Update() { int a = 10; if(UpdateCount % a == 0) { JikiInfo info = MainForm.GetJikiInfo(); float jiki_vx = info.VecX; float jiki_vy = info.VecY; double dx = (info.X - X + jiki_vx * a * info.Speed); double dy = (info.Y - Y + jiki_vy * a * info.Speed); double angle = Math.Atan2(dy, dx); VecX = (float)Math.Cos(angle) * Config.EnemySpeedA; VecY = (float)Math.Sin(angle) * Config.EnemySpeedA; } base.Update(); } public override void Draw() { double rad = Math.Atan2((Double)VecY, (Double)VecX); double angle = rad / (2 * Math.PI) * 360; GL.BindTexture(TextureTarget.Texture2D, Textures[0]); GL.PushMatrix(); { GL.Translate(X, Y, 0); GL.Rotate(angle - 90, 0, 0, 1); GL.Begin(BeginMode.Quads); { GL.TexCoord2(1, 1); GL.Vertex3(Radius, Radius, 0); GL.TexCoord2(0, 1); GL.Vertex3(-Radius, Radius, 0); GL.TexCoord2(0, 0); GL.Vertex3(-Radius, -Radius, 0); GL.TexCoord2(1, 0); GL.Vertex3(Radius, -Radius, 0); } GL.End(); } GL.PopMatrix(); GL.BindTexture(TextureTarget.Texture2D, 0); } } |
では実際に敵キャラを表示させてみましょう。[ゲームスタート]がクリックされたら自機を生成しなおします。そして今回はテスト用の敵を2体だけEnemyBaseのリスト Enemiesに追加します。
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 |
public partial class Form1 : Form { private void MenuItemGameStart_Click(object sender, EventArgs e) { InitGame(); } List<EnemyBase> Enemies = new List<EnemyBase>(); void InitGame() { Jiki = new Jiki(0, 0, 0, 0); UpdateCountEndLeft = -1; UpdateCountEndRight = -1; UpdateCount = 0; Enemies.Clear(); Enemies.Add(new Enemy1(this, 10, 50, 0, 0)); Enemies.Add(new Enemy1(this, 10, 100, 0, 0)); } new void Update() { MoveJiki(); UpdateEnemies(); } void UpdateEnemies() { foreach(EnemyBase enemy in Enemies) { enemy.Update(); } } void Draw() { DrawFieldLines(); Jiki.Draw(); DrawEnemies(); } void DrawEnemies() { foreach(EnemyBase enemy in Enemies) { enemy.Draw(); } } } |
自機と敵機の移動速度は同じです。実験してみるとたしかに自機に向かって衝突してきます。なおボスコニアンに出てくる戦闘機のように見えるザコ敵は戦闘機ではなくミサイルです。なので弾丸を発射してくることはありません。