//////////////////////////////////////////////////////////////////////// // 該当タイルを更新 //////////////////////////////////////////////////////////////////////// public static bool UpdateTile(Vector2 coord, TileType type) { if (!VaildCoord(coord)) { return(false); } var block = GetTileBlock(new Vector2(coord.x, coord.y)); if (block == null) { return(false); } if (block.GetTileType() != type) { block.SetTileType(type); var rect = GetRectangle(coord); DrawRectWithTileType(TileType.NullTile, rect); LoggerForm.WriteInfo(string.Format("Tile Updated | X: {0}, Y: {1}", coord.x, coord.y)); return(DrawRectWithTileType(type, rect)); } else { return(false); } }
//////////////////////////////////////////////////////////////////////// // マップデータを入力 //////////////////////////////////////////////////////////////////////// public static void ImportMapData(TileBlock[,] datas) { try { UpdateMap(datas); } catch (IndexOutOfRangeException ex) { LoggerForm.WriteError("例外エラー: " + ex.Message); } }
//////////////////////////////////////////////////////////////////////// // オーバーロード // typeがTileTypeの範囲を超えた場合InvaildCastExceptionが発生することを考慮 //////////////////////////////////////////////////////////////////////// public void SetTileType(int type) { try { tile.tileType = (TileType)type; } catch (InvalidCastException ex) { LoggerForm.WriteError("例外エラー: " + ex.Message); } }
//////////////////////////////////////////////////////////////////////// // フォームが表示された時に発生するイベント //////////////////////////////////////////////////////////////////////// private void Form1_Shown(object sender, EventArgs e) { LoggerForm form = new LoggerForm(); form.StartPosition = FormStartPosition.Manual; form.Location = new Point(this.Location.X + this.Width, this.Location.Y); form.Show(); World.CreateContext(); World.CreateMap(); }
//////////////////////////////////////////////////////////////////////// // ビットマップを使用して描画するための初期化関数 //////////////////////////////////////////////////////////////////////// public static void CreateContext() { graphics = Graphics.FromImage(GetBitmap()); if (graphics != null) { LoggerForm.WriteSuccess("Context created."); } else { LoggerForm.WriteError("CreateContext() failed."); } }
//////////////////////////////////////////////////////////////////////// // テキストファイルとしてマップを入力 //////////////////////////////////////////////////////////////////////// private void button4_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.InitialDirectory = Environment.CurrentDirectory; dialog.Filter = "テキストファイル(*.txt) | *.txt"; dialog.Title = "マップを読込"; dialog.RestoreDirectory = true; if (dialog.ShowDialog() == DialogResult.OK) { var fileName = dialog.FileName; using (StreamReader reader = new StreamReader(fileName, Encoding.UTF8)) { var line = string.Empty; TileBlock[,] datas = World.ExportCurrentMapData(); List <string> list = new List <string>(); while ((line = reader.ReadLine()) != null) { list.Add(line); } int counter = 0; for (int x = 0; x < World.MAX_COORD_X; x++) { for (int y = 0; y < World.MAX_COORD_Y; y++) { counter++; if (World.IsTileBlockExists(new Vector2(x, y))) { int result = 5; if (int.TryParse(list[counter - 1], out result)) { datas[x, y].SetTileType(int.Parse(list[counter - 1])); } else { LoggerForm.WriteError(string.Format("Failed to parse data[{0}, {1}] [{2}]", x, y, list[counter - 1])); } } else { LoggerForm.WriteError(string.Format("Failed to load data[{0}, {1}] [{2}]. Tile is not exists.", x, y, list[counter - 1])); } } } World.ImportMapData(datas); } } }
//////////////////////////////////////////////////////////////////////// // マップを探索 //////////////////////////////////////////////////////////////////////// public static async void AnalyzeMap() { LoggerForm.WriteSuccess("探索開始"); //各タイル座標に属性を付与 SetTileAttributesToAll(); var startTile = GetTileBlockByTileType(TileType.StartTile); var goalTile = GetTileBlockByTileType(TileType.GoalTile); if (startTile == null || goalTile == null) { if (startTile == null) { LoggerForm.WriteError("Start tile not found."); } else if (goalTile == null) { LoggerForm.WriteError("Goal tile not found."); } return; } var startTileCoord = startTile.GetCoordinate(); var goalTileCoord = goalTile.GetCoordinate(); var k = 0; TileBlock bestTile = startTile; while (k < 999) { k++; if (bestTile == null || !IsTileBlockExists(bestTile.GetCoordinate())) { LoggerForm.WriteError("Tile not found."); break; } else if (bestTile.GetTileType() == TileType.GoalTile) { LoggerForm.WriteSuccess("Goal found."); break; } else { bestTile = GetBestTile(bestTile, k); } await Task.Delay(10); } }
//////////////////////////////////////////////////////////////////////// // タイル座標を取得 //////////////////////////////////////////////////////////////////////// public static Vector2 GetTileCoordByTileType(TileType type) { for (int x = 0; x < MAX_COORD_X; x++) { for (int y = 0; y < MAX_COORD_Y; y++) { if (GetTileBlock(new Vector2(x, y)).GetTileType() == type) { return(new Vector2(x, y)); } } } LoggerForm.WriteError("GetTileCoordByTileType() Tile not found!"); return(new Vector2(0, 0)); }
//////////////////////////////////////////////////////////////////////// // タイル属性からタイルクラスを取得 //////////////////////////////////////////////////////////////////////// public static TileBlock GetTileBlockByTileType(TileType type) { for (int x = 0; x < MAX_COORD_X; x++) { for (int y = 0; y < MAX_COORD_Y; y++) { var tile = GetTileBlock(new Vector2(x, y)); if (tile.GetTileType() == type) { return(tile); } } } LoggerForm.WriteError("GetTileBlockByTileType() Tile not found!"); return(null); }
//////////////////////////////////////////////////////////////////////// // マップを初期化 & 空タイルを敷き詰める //////////////////////////////////////////////////////////////////////// public static void CreateMap() { tileBlocks = new TileBlock[MAX_COORD_X, MAX_COORD_Y]; tileSizeX = (bitmap.Width) / MAX_COORD_X; tileSizeY = (bitmap.Height) / MAX_COORD_Y; for (int x = 0; x < MAX_COORD_X; x++) { for (int y = 0; y < MAX_COORD_Y; y++) { AddTile(new Vector2(x, y), TileType.Walkable); } } LoggerForm.WriteSuccess("Map created."); }
//////////////////////////////////////////////////////////////////////// // 4方向から進むに最適なタイルを算出 //////////////////////////////////////////////////////////////////////// private static TileBlock GetBestTile(TileBlock origin, int cost) { if (origin.GetTileType() == TileType.GoalTile || origin.GetAnalyzed()) { return(origin); } var goalCoord = GetTileBlockByTileType(TileType.GoalTile).GetCoordinate(); var originCoord = origin.GetCoordinate(); var up = GetTileBlock(new Vector2(originCoord.x, originCoord.y - 1)); var bottom = GetTileBlock(new Vector2(originCoord.x, originCoord.y + 1)); var right = GetTileBlock(new Vector2(originCoord.x + 1, originCoord.y)); var left = GetTileBlock(new Vector2(originCoord.x - 1, originCoord.y)); if (up != null && up.GetTileType() != TileType.Walkable && up.GetTileType() != TileType.GoalTile) { up = null; } if (bottom != null && bottom.GetTileType() != TileType.Walkable && bottom.GetTileType() != TileType.GoalTile) { bottom = null; } if (right != null && right.GetTileType() != TileType.Walkable && right.GetTileType() != TileType.GoalTile) { right = null; } if (left != null && left.GetTileType() != TileType.Walkable && left.GetTileType() != TileType.GoalTile) { left = null; } if (up != null && up.GetAnalyzed()) { up = null; } if (bottom != null && bottom.GetAnalyzed()) { bottom = null; } if (right != null && right.GetAnalyzed()) { right = null; } if (left != null && left.GetAnalyzed()) { left = null; } if (up != null && up.GetTileType() == TileType.GoalTile) { DrawLineCenterTileToTile(origin.GetCoordinate(), up.GetCoordinate()); } if (bottom != null && bottom.GetTileType() == TileType.GoalTile) { DrawLineCenterTileToTile(origin.GetCoordinate(), bottom.GetCoordinate()); } if (right != null && right.GetTileType() == TileType.GoalTile) { DrawLineCenterTileToTile(origin.GetCoordinate(), right.GetCoordinate()); } if (left != null && left.GetTileType() == TileType.GoalTile) { DrawLineCenterTileToTile(origin.GetCoordinate(), left.GetCoordinate()); } var up_hcost = 0; var bottom_hcost = 0; var right_hcost = 0; var left_hcost = 0; if (up != null) { up_hcost = CalculateHeuristic(up.GetCoordinate(), goalCoord); } if (bottom != null) { bottom_hcost = CalculateHeuristic(bottom.GetCoordinate(), goalCoord); } if (right != null) { right_hcost = CalculateHeuristic(right.GetCoordinate(), goalCoord); } if (left != null) { left_hcost = CalculateHeuristic(left.GetCoordinate(), goalCoord); } if (up != null) { up.SetAnalyzeData(cost, up_hcost); } if (bottom != null) { bottom.SetAnalyzeData(cost, bottom_hcost); } if (right != null) { right.SetAnalyzeData(cost, right_hcost); } if (left != null) { left.SetAnalyzeData(cost, left_hcost); } var up_score = 0; var bottom_score = 0; var right_score = 0; var left_score = 0; if (up != null) { up_score = up.GetScore(); } if (bottom != null) { bottom_score = bottom.GetScore(); } if (right != null) { right_score = right.GetScore(); } if (left != null) { left_score = left.GetScore(); } var scores = new int[4]; scores[0] = up_score; scores[1] = bottom_score; scores[2] = right_score; scores[3] = left_score; var hcosts = new int[4]; hcosts[0] = up_hcost; hcosts[1] = bottom_hcost; hcosts[2] = right_hcost; hcosts[3] = left_hcost; var tiles = new TileBlock[4]; tiles[0] = up; tiles[1] = bottom; tiles[2] = right; tiles[3] = left; var min_score = int.MaxValue; var min_cost = int.MaxValue; var min_hcost = int.MaxValue; var min_tile = origin; for (int m = 0; m < 4; m++) { if (scores[m] == 0) { continue; } if (scores[m] > min_score) { continue; } if (scores[m] == min_score && cost >= min_cost) { continue; } min_score = scores[m]; min_cost = cost; min_tile = tiles[m]; min_hcost = hcosts[m]; } if (origin != null) { origin.Close(); } if (min_tile.GetTileType() == TileType.Walkable) { origin.SetAnalyzed(true); DrawLineCenterTileToTile(origin.GetCoordinate(), min_tile.GetCoordinate()); bool showScore = f.checkBox1.Checked; if (up != null && showScore) { DrawText((up_hcost + cost).ToString(), Brushes.Black, PointToVector2(GetRednerTileLocation(up.GetCoordinate()))); LoggerForm.WriteWarn("UP HCOST: " + up_hcost.ToString()); LoggerForm.WriteWarn("UP COST: " + cost.ToString()); LoggerForm.WriteWarn("UP SCORE: " + up_score.ToString()); LoggerForm.WriteInfo("-------------"); } if (bottom != null && showScore) { DrawText((bottom_hcost + cost).ToString(), Brushes.Black, PointToVector2(GetRednerTileLocation(bottom.GetCoordinate()))); LoggerForm.WriteWarn("BOTTOM HCOST: " + bottom_hcost.ToString()); LoggerForm.WriteWarn("BOTTOM COST: " + cost.ToString()); LoggerForm.WriteWarn("BOTTOM SCORE: " + bottom_score.ToString()); LoggerForm.WriteInfo("-------------"); } if (right != null && showScore) { DrawText((right_hcost + cost).ToString(), Brushes.Black, PointToVector2(GetRednerTileLocation(right.GetCoordinate()))); LoggerForm.WriteWarn("RIGHT HCOST: " + right_hcost.ToString()); LoggerForm.WriteWarn("RIGHT COST: " + cost.ToString()); LoggerForm.WriteWarn("RIGHT SCORE: " + right_score.ToString()); LoggerForm.WriteInfo("-------------"); } if (left != null && showScore) { DrawText((left_hcost + cost).ToString(), Brushes.Black, PointToVector2(GetRednerTileLocation(left.GetCoordinate()))); LoggerForm.WriteWarn("LEFT HCOST: " + left_hcost.ToString()); LoggerForm.WriteWarn("LEFT COST: " + cost.ToString()); LoggerForm.WriteWarn("LEFT SCORE: " + left_score.ToString()); LoggerForm.WriteInfo("-------------"); } } return(min_tile); }