Rally-Xは画面の右側にレーダーがあり、マイカーの位置とレッドカーの位置、チェックポイントの位置が表示されます。これをプレイヤーはこれを頼りに敵とチェックポイントの位置を知り、ゲームを進めていきます。
まずデザイナでレーダー表示用のPanelを追加します。右側にあるのがPanelです。
最初にチェックポイントを表示させます。
チェックポイントの位置を適当に決めます。
CheckPointクラスはチェックポイントの位置と状態を管理するためのクラスです。
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 |
public class CheckPoint { public CheckPoint(int x, int y) { IndexX = x; IndexY = y; Cleared = false; } public int IndexX { get; private set; } public int IndexY { get; private set; } public bool Cleared { get; set; } } |
ゲームが開始されたらチェックポイントを適当な位置に配置します。
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 |
public partial class Form1 : Form { public Form1() { SetCheckPoints(); // その他は同じなので省略 // } List<CheckPoint> CheckPoints = new List<CheckPoint>(); void SetCheckPoints() { CheckPoints.Add(new CheckPoint(2, 22)); CheckPoints.Add(new CheckPoint(4, 18)); CheckPoints.Add(new CheckPoint(3, 6)); CheckPoints.Add(new CheckPoint(1, 0)); CheckPoints.Add(new CheckPoint(12, 20)); CheckPoints.Add(new CheckPoint(14, 20)); CheckPoints.Add(new CheckPoint(18, 22)); CheckPoints.Add(new CheckPoint(21, 18)); CheckPoints.Add(new CheckPoint(22, 13)); CheckPoints.Add(new CheckPoint(20, 6)); } void DrawCheckPoints() { foreach(CheckPoint check in CheckPoints) { if(check.Cleared) continue; DrawCheckPoint(check.IndexX, check.IndexY); } } void DrawCheckPoint(int indexX, int indexY) { double x = indexX; double y = indexY; GL.Color3(Color.LightGreen); GL.PushMatrix(); { GL.Translate(x, y, 0); GL.Begin(BeginMode.Quads); { GL.Vertex3(-0.3, 0.4, 0.01); GL.Vertex3(-0.2, 0.4, 0.01); GL.Vertex3(-0.2, -0.4, 0.01); GL.Vertex3(-0.3, -0.4, 0.01); } GL.End(); GL.Begin(BeginMode.Triangles); { GL.Vertex3(-0.2, 0.4, 0.01); GL.Vertex3(0.3, 0.25, 0.01); GL.Vertex3(-0.2, 0, 0.01); } GL.End(); } GL.PopMatrix(); } private void GlControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); DrawRoad(); DrawMyCar(); DrawRedCars(); DrawCheckPoints(); glControl1.SwapBuffers(); } } |
チェックポイントを設定したら、次にレーダーを表示させてみましょう。
レーダーにマイカーとレッドカー、通過前のチェックポイントの位置を表示させます。
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 |
public partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { MoveMyCar(); MoveRedCars(); glControl1.Refresh(); panelRadar.Invalidate(); } // ブロックの縦横の数を取得する int GetRoadBlocksCountX() { int minX = RoadBlocks.Min(x => x.IndexX); int maxX = RoadBlocks.Max(x => x.IndexX); int minY = RoadBlocks.Min(x => x.IndexY); int maxY = RoadBlocks.Max(x => x.IndexY); return maxX - minX + 1; } int GetRoadBlocksCountY() { int minX = RoadBlocks.Min(x => x.IndexX); int maxX = RoadBlocks.Max(x => x.IndexX); int minY = RoadBlocks.Min(x => x.IndexY); int maxY = RoadBlocks.Max(x => x.IndexY); return maxY - minY + 1; } private void PanelRadar_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(Color.Blue); int roadBlocksCountX = GetRoadBlocksCountX(); int roadBlocksCountY = GetRoadBlocksCountY(); // 少し内側に表示する int margin = 10; int panelRadarInnerWidht = panelRadar.Width - margin * 2; int panelRadarInnerHeight = panelRadar.Width - margin * 2; // GLControlとはY座標の上下が逆なので注意する // マイカーの位置 { int x = (int)(EyeX * panelRadarInnerWidht / roadBlocksCountX); int y = (int)(EyeY * panelRadarInnerHeight / roadBlocksCountY); Point point = new Point(x + margin, panelRadarInnerHeight - y + margin); e.Graphics.FillRectangle(new SolidBrush(Color.White), new Rectangle(point.X, point.Y, 5, 5)); } // レッドカーの位置 foreach(RedCar red in RedCars) { int x = (int)(red.X * panelRadarInnerWidht / roadBlocksCountX); int y = (int)(red.Y * panelRadarInnerHeight / roadBlocksCountY); Point point = new Point(x + margin, panelRadarInnerHeight - y + margin); e.Graphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(point.X, point.Y, 5, 5)); } // 未通過のチェックポイントの位置 foreach(CheckPoint check in CheckPoints) { if(check.Cleared) continue; int x = check.IndexX * panelRadarInnerWidht / roadBlocksCountX; int y = check.IndexY * panelRadarInnerHeight / roadBlocksCountY; Point point = new Point(x + margin, panelRadarInnerHeight - y + margin); e.Graphics.FillRectangle(new SolidBrush(Color.LightGreen), new Rectangle(point.X, point.Y, 5, 5)); } } } |