Rally-Xもどきの完成度を高めます。
コースのマップを公開しているサイトはないか探してみるとこんなページが見つかりました。
サイトに掲載されていたマップを写し取ったのがこれです。緑の部分が通路、青と赤がマイカーとレッドカーの初期位置、黄色がチェックポイントの位置です。マップには16箇所ありますが、実際に出現するのはこのなかの10箇所です。
マップは1マス16ピクセルなので各マスの中央の色を読み取れば通路の位置がわかります。
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 139 140 141 142 143 144 145 146 147 148 149 150 |
public partial class Form1 : Form { // 道路を構成するブロックの位置 public List<Block> RoadBlocks { get; private set; } // 各ステージのレッドカーの初期位置 List<Position> InitRedCarPositions = null; // 各ステージのマイカーの初期位置 Position InitMyCarPosition = null; // チェックポイントの位置 List<Position> CheckPointPositions = null; void GetCourseData(int stage) { Bitmap bitmap = Properties.Resources.road1; if(stage == 1) { bitmap = Properties.Resources.road1; GL.ClearColor(Color.Magenta); } else if(stage == 2) { bitmap = Properties.Resources.road2; GL.ClearColor(Color.SkyBlue); } else if(stage == 3) { bitmap = Properties.Resources.road3; GL.ClearColor(Color.Brown); } else if(stage == 4) { bitmap = Properties.Resources.road4; GL.ClearColor(Color.Green); } else { bitmap = Properties.Resources.road1; GL.ClearColor(Color.Magenta); } List<Position> roadPositions = new List<Position>(); List<Position> initRedCarPositions = new List<Position>(); List<Position> checkPointPositions = new List<Position>(); Position initMyCarPosition = null; Color red = Color.FromArgb(255, 0, 0); Color green = Color.FromArgb(0, 255, 0); Color blue = Color.FromArgb(0, 0, 255); Color yellow = Color.FromArgb(255, 255, 0); // ビットマップイメージからコースデータを取得する int width = bitmap.Width; int height = bitmap.Height; int indexY = 0; for(int y = 8; y < height; y += 16) { List<int> xs = new List<int>(); int indexX = 0; for(int x = 8; x < width; x += 16) { if(bitmap.GetPixel(x, y) == green || bitmap.GetPixel(x, y) == red || bitmap.GetPixel(x, y) == blue || bitmap.GetPixel(x, y) == yellow) roadPositions.Add(new Position(indexX, indexY)); if(bitmap.GetPixel(x, y) == red) initRedCarPositions.Add(new Position(indexX, indexY)); if(bitmap.GetPixel(x, y) == yellow) checkPointPositions.Add(new Position(indexX, indexY)); if(bitmap.GetPixel(x, y) == blue) initMyCarPosition = new Position(indexX, indexY); indexX++; } indexY++; } // Y座標を逆にする int MaxY = roadPositions.Max(x1 => x1.Y); roadPositions = roadPositions.Select(x1 => new Position(x1.X, MaxY - x1.Y)).ToList(); initRedCarPositions = initRedCarPositions.Select(x1 => new Position(x1.X, MaxY - x1.Y)).ToList(); checkPointPositions = checkPointPositions.Select(x1 => new Position(x1.X, MaxY - x1.Y)).ToList(); initMyCarPosition = new Position(initMyCarPosition.X, MaxY - initMyCarPosition.Y); // 道路をつくる List<Block> blocks = new List<Block>(); foreach(Position position in roadPositions) { blocks.Add(new Block(position.X, position.Y)); } RoadBlocks = blocks; // マイカー、レッドカーの初期位置をセット InitRedCarPositions = initRedCarPositions; InitMyCarPosition = initMyCarPosition; Random random = new Random((int)DateTime.Now.Ticks); List<int> vs = new List<int>(); // チェックポイント16箇所のなかから実際に表示させる10箇所をランダムに選ぶ int allCount = checkPointPositions.Count; while(vs.Count < 10) { int r = random.Next(0, allCount); if(!vs.Any(x => x == r)) vs.Add(r); } CheckPointPositions = new List<Position>(); foreach(int i in vs) CheckPointPositions.Add(checkPointPositions[i]); } private void GlControlEx1_Load(object sender, EventArgs e) { GL.ClearColor(glControl1.BackColor); // Projection の設定 SetProjection(); // 視界の設定 SetSight(); GetSmokeTexture(); // デプスバッファの使用 GL.Enable(EnableCap.DepthTest); // 初期の表示 GetCourseData(1); ResetMyCar(); } void InitSideBar() { Font font = new Font("MS UI Gothic", 14, FontStyle.Bold); labelStage.BackColor = Color.Black; labelStage.ForeColor = Color.White; labelStage.Font = font; // 他はこれまでと同じなので省略 // } } |
あとはゲームが開始されたら、コースデータを読み出してこれを表示させます。
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 |
public partial class Form1 : Form { void GameStart() { isGameOver = false; Rest = MaxRest; Score = 0; Stage = 1; GetCourseData(Stage); TimerReset(); ResetMyCar(); ResetRedCars(); ResetCheckPoints(); InitFuel(); timer.Start(); } int _stage = 1; int Stage { get { return _stage; } set { _stage = value; labelStage.Text = "Stage " + _stage.ToString(); } } void ResetMyCar() { CurDirect = Direct.North; NextDirect = Direct.North; EyeX = InitMyCarPosition.X; EyeY = InitMyCarPosition.Y; } void ResetRedCars() { RedCars.Clear(); foreach(Position position in InitRedCarPositions) { RedCar redCar = new RedCar(RoadBlocks, position.X, position.Y, Direct.North); redCar.StopInterval = 3 * 1000; redCar.CurDirect = Direct.North; RedCars.Add(redCar); } } } |
次にステージクリアしたら次のステージに進めます。
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 |
public partial class Form1 : Form { void StageClear() { if(!isGameOver) { // クリアしたらタイマーを止める timer.Stop(); // 別のタイマーをセット Timer timer3 = new Timer(); timer3.Interval = 30; timer3.Tick += Timer3_Tick; timer3.Start(); // ステージクリア時もGetCountをリセット GetCount = 0; } } private void Timer3_Tick(object sender, EventArgs e) { // クリアボーナスを追加 // 燃料3に対して10点だが、10点ずつ加算していては時間がかかるので8単位まとめて加算する // 8未満は最後に加算する if(progressBar1.Value > 8 * 3) { progressBar1.Value -= 8 * 3; Score += 80; } else if(progressBar1.Value > 0) { Score += 10 * progressBar1.Value / 3; progressBar1.Value = 0; } else { // クリアボーナスを追加しおわったらタイマーは破棄 // 新しいステージへ Timer t = (Timer)sender; t.Stop(); t.Dispose(); Smokes.Clear(); StartNewStage(); } } void StartNewStage() { // 新しいマップデータを読み込む Stage++; GetCourseData(Stage); ResetMyCar(); ResetRedCars(); SetCheckPoints(); // 燃料をリセット(満タン)にして再スタート InitFuel(); timer.Start(); } } |