こんな感じのゲームをつくります。
テキストファイルで以下のようなものをつくって、ここからフィールドをつくります。■は破壊不可能、□は破壊できるブロックです。
まずテキストファイルを読み込みます。
そして■なら破壊できないブロックとして、□であれば破壊可能なブロックとしてオブジェクトを生成します。
Blockクラス
そのまえにブロックを管理するためのクラスを示します。ブロックの大きさは2(戦車のサイズの2倍)とします。1回砲撃されると砲撃された面がなくなり、2回砲撃されることで完全に破壊されるようにします。ひとつのブロックを2×2の小さなブロックでつくります。そのためBlockクラスには破壊されたかどうかを管理するためのフィールド変数を用意しています。
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
public class Block { protected bool IsBrokenNE = false; protected bool IsBrokenNW = false; protected bool IsBrokenSE = false; protected bool IsBrokenSW = false; public Block(int posX, int posZ) { PositionX = posX; PositionZ = posZ; } public float PositionX { get; protected set; } public float PositionZ { get; protected set; } public float Left { get{ return PositionX - 1; } } public float Right { get { return PositionX + 1; } } public float Front { get { return PositionZ + 1; } } public float Back { get { return PositionZ - 1; } } public bool IsBroken { get { if(IsBrokenNE && IsBrokenNW && IsBrokenSE && IsBrokenSW) return true; else return false; } } protected void Draw0() { // 幅と奥行きは1、高さは2とする GL.Begin(BeginMode.Quads); { // 正面 GL.Normal3(Vector3.UnitZ); GL.Vertex3(0.5, 1, 0.5); GL.Vertex3(0.5, -1, 0.5); GL.Vertex3(-0.5, -1, 0.5); GL.Vertex3(-0.5, 1, 0.5); // 後面 GL.Normal3(-Vector3.UnitZ); GL.Vertex3(0.5, 1, -0.5); GL.Vertex3(0.5, -1, -0.5); GL.Vertex3(-0.5, -1, -0.5); GL.Vertex3(-0.5, 1, -0.5); // 右面 GL.Normal3(Vector3.UnitX); GL.Vertex3(0.5, 1, 0.5); GL.Vertex3(0.5, -1, 0.5); GL.Vertex3(0.5, -1, -0.5); GL.Vertex3(0.5, 1, -0.5); // 左面 GL.Normal3(-Vector3.UnitX); GL.Vertex3(-0.5, 1, 0.5); GL.Vertex3(-0.5, -1, 0.5); GL.Vertex3(-0.5, -1, -0.5); GL.Vertex3(-0.5, 1, -0.5); // 上面 GL.Normal3(Vector3.UnitY); GL.Vertex3(0.5, 1, 0.5); GL.Vertex3(0.5, 1, -0.5); GL.Vertex3(-0.5, 1, -0.5); GL.Vertex3(-0.5, 1, 0.5); } GL.End(); } public void Draw() { // Y方向に0.5ずらして高さ1.5になるようにする // 壊れていない場合だけ描画する GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.DarkRed); GL.PushMatrix(); { GL.Translate(PositionX + 0.5, 0.5, PositionZ + 0.5); if(!IsBrokenSE) Draw0(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(PositionX - 0.5, 0.5, PositionZ + 0.5); if(!IsBrokenSW) Draw0(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(PositionX - 0.5, 0.5, PositionZ - 0.5); if(!IsBrokenNW) Draw0(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(PositionX + 0.5, 0.5, PositionZ - 0.5); if(!IsBrokenNE) Draw0(); } GL.PopMatrix(); } } |
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 |
class BorderBlock : Block { public BorderBlock(int posX, int posZ) : base(posX, posZ) { } new public void Draw() { GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.DarkBlue); GL.PushMatrix(); { GL.Translate(PositionX + 0.5, 0.5, PositionZ + 0.5); Draw0(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(PositionX - 0.5, 0.5, PositionZ + 0.5); Draw0(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(PositionX - 0.5, 0.5, PositionZ - 0.5); Draw0(); } GL.PopMatrix(); GL.PushMatrix(); { GL.Translate(PositionX + 0.5, 0.5, PositionZ - 0.5); Draw0(); } GL.PopMatrix(); } } |
あとはテキストファイルを読み込んでオブジェクトをリストに格納し、描画処理ができるようにするだけです。
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 79 80 81 82 83 |
public partial class Form1 : Form { void CreateStage(int i) { string filePath = String.Format("{0}\\stage{1}.txt", Application.StartupPath, i); StreamReader sr = new StreamReader(filePath); List<string> vs1 = new List<string>(); while(true) { string str = sr.ReadLine(); if(str == null) break; vs1.Add(str); } sr.Close(); // 先に読み込んだものを下に表示されるため、上下を入れ替える vs1.Reverse(); BorderBlocks.Clear(); Blocks.Clear(); int z = 0; foreach(string str in vs1) { char[] vs = str.ToArray(); int x = 0; foreach(char c in vs) { if(c == '■') BorderBlocks.Add(new BorderBlock(x * 2, z * (-2))); if(c == '□') Blocks.Add(new Block(x * 2, z * (-2))); x++; } z++; } } private void glControl_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // 視点を変更する SetSight(); if(!Tank.isDead) Tank.Draw(); // 床を描画 DrawFloor(); foreach(Explosion explosion in Explosions) explosion.Draw(); foreach(SmallExplosion explosion in SmallExplosions) explosion.Draw(); foreach(BorderBlock block in BorderBlocks) block.Draw(); foreach(Block block in Blocks) block.Draw(); glControl.SwapBuffers(); } void DrawFloor() { GL.Material(MaterialFace.Front, MaterialParameter.Ambient, Color.White); GL.Begin(BeginMode.Quads); { GL.Normal3(Vector3.UnitY); GL.Vertex3(BorderBlocks.Min(x => x.Left), 0, BorderBlocks.Max(x => x.Front)); GL.Vertex3(BorderBlocks.Max(x => x.Right), 0, BorderBlocks.Max(x => x.Front)); GL.Vertex3(BorderBlocks.Max(x => x.Right), 0, BorderBlocks.Min(x => x.Back)); GL.Vertex3(BorderBlocks.Min(x => x.Left), 0, BorderBlocks.Min(x => x.Back)); } GL.End(); } } |