// Ctor : provides Map and mode (combat or not). Beware, use a Fight context un fight, and a Map out of fights public PathFinder(IMapContext map, bool fight) { Debug.Assert(fight && map is Fight || !fight && map is IMap); _isInFight = fight; _map = map; _cells = new CellInfo[map.Cells.Count]; for (int i = 0; i < map.Cells.Count; i++) _cells[i] = new CellInfo(map.Cells[i]); PathPacker = new MapMovement(_cells); }
/// <summary> /// PathFinding main method /// </summary> /// <param name="startingCells"></param> /// <param name="exitCells"></param> /// <param name="selectFartherCells"></param> /// <param name="firstStepOnly"></param> /// <returns></returns> public bool FindPath(short[] startingCells, short[] exitCells, bool selectFartherCells = false, bool firstStepOnly = false, int maxDistanceParam = CellInfo.DEFAULT_DISTANCE) { Random rnd = new Random(); if ((startingCells == null) || (startingCells.Length == 0)) { return(false); // We need at least one starting stCell } if (!firstStepOnly && (exitCells == null || exitCells.Length == 0)) { return(false); // We need at least one exit stCell for step 2 } // PC starts at distance of 0. Set 0 to all possible starting cells CellInfo[] changed = new CellInfo[560]; int changedPtr = 0; CellInfo[] changing = new CellInfo[560]; int changingPtr = 0; bool optimizerActiv = !firstStepOnly && !selectFartherCells; // This strong optimization may fail to find a path. In that case, the non-optimized algorithm is run while (true) { ClearLogic(startingCells, exitCells); uint EstimatedDistance = CellInfo.DEFAULT_DISTANCE; Cell bestStartingCell = null; Cell bestEndingCell = null; foreach (short stCell in startingCells) { if (_cells[stCell] != null) { _cells[stCell].DistanceSteps = 0; changed[changedPtr++] = _cells[stCell]; if (!firstStepOnly && !selectFartherCells) { foreach (short exCell in exitCells) { if (exCell == stCell) { PathResult = new List <short> { stCell }; return(true); // Empty path : starting stCell = exit stCell } if (optimizerActiv) { uint distance = _cells[stCell].Cell.ManhattanDistanceTo(_cells[exCell].Cell); if (distance < EstimatedDistance) { bestStartingCell = _cells[stCell].Cell; bestEndingCell = _cells[exCell].Cell; EstimatedDistance = distance; } } } } } } // cells[StartingCell].distanceSteps = 0; int maxDistance = maxDistanceParam; // We won't search over this distance - this optimization is OK in all cases if (optimizerActiv && bestStartingCell == null || bestEndingCell == null) { optimizerActiv = false; } while (changedPtr > 0) { changingPtr = 0; // Look at each square on the board. while (changedPtr > 0) { CellInfo curCell = changed[--changedPtr]; if (curCell.IsCloseToEnemy && _isCautious) { continue; // Cautious mode (in or out of fight) : Can't move from a cell near an ennemy } if (curCell.DistanceSteps < maxDistance) { if (optimizerActiv) // Strong optimisation { uint lastEstimatedDistance = curCell.Cell.ManhattanDistanceTo(bestEndingCell); uint startDistance = curCell.Cell.ManhattanDistanceTo(bestStartingCell); if (startDistance + lastEstimatedDistance > EstimatedDistance) { continue; } } //Debug.Assert((curCell != null && curCell.DistanceSteps < CellInfo.DEFAULT_DISTANCE)); short[] cellNeighbours = neighbours[curCell.CellId]; for (short i = 0; i < cellNeighbours.Length; i++) { CellInfo newCell = _cells[cellNeighbours[i]]; if (newCell == null) { continue; } if (newCell.DistanceSteps != 0 && !SquareOpen(newCell, null)) { continue; } //uint currentDistance = newCell.Cell.ManhattanDistanceTo(_cells[exitCells[0]].Cell); //if (currentDistance >= EstimatedDistance || currentDistance >= lastEstimatedDistance) continue; int newPass = curCell.DistanceSteps; if (curCell.IsCloseToEnemy) { newPass++; // Penality when close of an ennemy (same in fight and RP map) } if (_isInFight) { newPass++; } else { newPass += newCell.Weight; } if (newCell.DistanceSteps > newPass) { newCell.DistanceSteps = newPass; changing[changingPtr++] = newCell; if (!firstStepOnly && !selectFartherCells && newPass < maxDistance && exitCells.Any(id => newCell.CellId == id)) { maxDistance = newPass; // We won't search on distance over closest exit } } } if (_isInFight) { continue; } cellNeighbours = diagNeighbours[curCell.CellId]; for (short i = 0; i < cellNeighbours.Length; i++) // Process diagonals { CellInfo newCell = _cells[cellNeighbours[i]]; if (newCell == null) { continue; } if (newCell.DistanceSteps != 0 && !SquareOpen(newCell, null)) { continue; } int newPass = curCell.DistanceSteps; if (curCell.IsCloseToEnemy) { newPass++; // Penality when close of an ennemy (same in fight and RP map) } if (_isInFight) { newPass++; } else { newPass += (int)(newCell.Weight * 1.414); } if (newCell.DistanceSteps > newPass) { newCell.DistanceSteps = newPass; changing[changingPtr++] = newCell; if (!firstStepOnly && !selectFartherCells && newPass < maxDistance && exitCells.Any(id => newCell.CellId == id)) { maxDistance = newPass; // We won't search on distance over closest exit } } } } } CellInfo[] tmpChanged = changed; changed = changing; changedPtr = changingPtr; changing = tmpChanged; } if (firstStepOnly) { return(true); } // Step 2 // Mark the path from Exit to Starting position. // if several Exit cells, then get the lowest distance one = the closest from one starting cell // (or the highest distance one if selectFartherCells) ExitCell = exitCells[0]; int MinDist = _cells[ExitCell].DistanceSteps; foreach (short cell in exitCells) { if ((selectFartherCells && _cells[cell].DistanceSteps > MinDist) || (!selectFartherCells && _cells[cell].DistanceSteps < MinDist)) { ExitCell = cell; MinDist = _cells[cell].DistanceSteps; } } if (optimizerActiv == false || MinDist < CellInfo.DEFAULT_DISTANCE) { break; // No need to run a second unoptimized algorithm } else { optimizerActiv = false; } } //int no = 0; //Debug.WriteLine("PathFinding from {0} ({1}) to {2} ({3})", _cells[startingCells[0]].cell, _cells[startingCells[0]].distanceSteps, _cells[ExitCell].cell, _cells[ExitCell].distanceSteps); /*List<Cell> ListMax = new List<Cell>(); * List<Cell> ListInc = new List<Cell>(); * foreach (var cell in _cells) * { * if (cell.distanceSteps >= CellInfo.DEFAULT_DISTANCE) * ListMax.Add(cell.cell); * if (cell.distanceSteps <= MinDist) * ListInc.Add(cell.cell); * //else * // continue; * Debug.Write(String.Format("{0} : {1}, ", cell.cell, cell.distanceSteps)); * if (no++ == 5) * { * Debug.WriteLine(""); * no = 0; * } * }*/ //Debug.WriteLine(""); //BotManager.Instance.Bots[0].Character.ResetCellsHighlight(); //BotManager.Instance.Bots[0].Character.HighlightCells(ListMax, Color.Black); //BotManager.Instance.Bots[0].Character.HighlightCells(ListMax, Color.DarkGray); short CurrentCell = ExitCell; PathResult.Add(ExitCell); _cells[ExitCell].IsInPath = true; CellInfo[] lowestPoints = changed; // No ned to alloc a new one, this one won't be used anymore int lowestPointsPtr = 0; short lowestPoint; int lowest; while (true) { // Look through each MapNeighbour and find the square // with the lowest number of steps marked. lowestPoint = CellInfo.CELL_ERROR; lowest = CellInfo.DEFAULT_DISTANCE; short[] neighbours = GetNeighbours(CurrentCell, _isInFight); for (short i = 0; i < neighbours.Length; i++) { //foreach (CellInfo newCell in ValidMoves(curCell, false)) CellInfo newCell = _cells[neighbours[i]]; if (newCell == null || (newCell.IsCloseToEnemy && _isCautious && newCell.DistanceSteps != 0)) { continue; // In cautious mode, don't come close to an enemy } //for (CellInfo NewCell in ValidMoves(_cells[CurrentCell], true)) //{ int distance = newCell.DistanceSteps; /*if (distance > CellInfo.DEFAULT_DISTANCE) * { * Debug.Assert(false, "Distance shouldn't be higher than DEFAULT_DISTANCE", "Distance = {0} > Max = {1}", distance, CellInfo.DEFAULT_DISTANCE); * continue; * }*/ if (distance < lowest) { lowestPointsPtr = 1; lowest = distance; lowestPoints[0] = newCell; } else if (distance == lowest) { lowestPoints[lowestPointsPtr++] = newCell; } } if (lowest == CellInfo.DEFAULT_DISTANCE) { break; // Can't find a valid way :( } if (lowestPointsPtr > 1) // Several points with same distance =>> randomly select one of them { lowestPoint = lowestPoints[rnd.Next(lowestPointsPtr)].CellId; } else { lowestPoint = lowestPoints[0].CellId; } // Mark the square as part of the path if it is the lowest // number. Set the current position as the square with // that number of steps. PathResult.Add(lowestPoint); if (PathResult.Count > _cells.Length) { Debug.Assert(false, "PathFinder can't find a path - overflow"); break; } //Debug.Assert(_cells[lowestPoint].IsInPath == false, "Point already in path", "CurrentCell : {0}, Lowest : {1} - distance : {2}, path : {3}", _cells[CurrentCell].Cell, _cells[lowestPoint].Cell, lowest, string.Join(",", _cells.Where(stCell => stCell.IsInPath))); _cells[lowestPoint].IsInPath = true; CurrentCell = lowestPoint; if (_cells[CurrentCell].DistanceSteps == 0) // Exit reached { StartingCell = CurrentCell; // We went from closest Exit to a Starting position, so we're finished. break; } } PathResult.Reverse(); return(CurrentCell == StartingCell); }
// Return each valid square we can move to. private IEnumerable<CellInfo> ValidMoves(CellInfo cell, bool fast) { CellInfo newCell; if ((newCell = getNeighbourCell(cell, 1, 0)) != null) yield return newCell; if ((newCell = getNeighbourCell(cell, 0, 1)) != null) yield return newCell; if ((newCell = getNeighbourCell(cell, -1, 0)) != null) yield return newCell; if ((newCell = getNeighbourCell(cell, 0, -1)) != null) yield return newCell; if (!_isInFight) { if ((newCell = getNeighbourCell(cell, 1, 1)) != null) yield return newCell; if ((newCell = getNeighbourCell(cell, 1, -1)) != null) yield return newCell; if ((newCell = getNeighbourCell(cell, -1, 1)) != null) yield return newCell; if ((newCell = getNeighbourCell(cell, -1, -1)) != null) yield return newCell; } }
private CellInfo getNeighbourCell(CellInfo cell, int deltaX, int deltaY) { int NewCellId = cell.GetNeighbourCell(deltaX, deltaY); if (NewCellId == CellInfo.CELL_ERROR) return null; return _cells[NewCellId]; }
/// <summary> /// PathFinding main method /// </summary> /// <param name="startingCells"></param> /// <param name="exitCells"></param> /// <param name="selectFartherCells"></param> /// <param name="firstStepOnly"></param> /// <returns></returns> private int SubMapFiller(CellInfo startingCell, byte RegionNb) { Debug.Assert(RegionNb > 0); // If a wrong or non-walkable cell or already with the given Region number, then return 0. if ((startingCell == null) || !_map.IsCellWalkable(startingCell.Cell, true, null) || !(!_isInFight || startingCell.IsCombatWalkable) || (startingCell.SubMapId == RegionNb) ) return 0; _isInFight = false; Random rnd = new Random(); List<CellInfo> changed = new List<CellInfo>(); List<CellInfo> changing; int cellCounter = 0; startingCell.SubMapId = RegionNb; changed.Add(startingCell); while (changed.Count > 0) { cellCounter += changed.Count; changing = new List<CellInfo>(); // Look at each square on the board. foreach (CellInfo curCell in changed) { //Debug.Assert((curCell != null && curCell.distanceSteps < CellInfo.DEFAULT_DISTANCE)); foreach (CellInfo newCell in ValidMoves(curCell, true)) if (newCell.SubMapId != RegionNb && _map.IsCellWalkable(newCell.Cell, true, null) && (!_isInFight || newCell.IsCombatWalkable)) { newCell.SubMapId = RegionNb; changing.Add(newCell); } } changed = changing; } return cellCounter; }
static public double GetFlightDistance(CellInfo StartCell, CellInfo EndCell, bool isInFight) { int dx = Math.Abs(StartCell.X - EndCell.X); int dy = Math.Abs(StartCell.Y - EndCell.Y); if (isInFight) return dx + dy; if (dx > dy) return dy * 1.414 /* diagonale part */ + /* straight line part */ dx - dy; else return dx * 1.414 /* diagonale part */ + /* straight line part */ dy - dx; }
CellInfo getNeighbourCell(CellInfo cell, int deltaX, int deltaY, bool fast) { int NewCellId = cell.GetNeighbourCell(deltaX, deltaY); CellInfo NewCell = NewCellId == CellInfo.CELL_ERROR ? null : _cells[NewCellId]; if (fast || NewCell == null || NewCell.DistanceSteps == 0) return NewCell; if (!SquareOpen(NewCell, cell)) return null; NewCell.IsDiagonal = deltaX != 0 && deltaY != 0; return NewCell; }
private bool SquareOpen(CellInfo cell, CellInfo originCell = null) { if (cell == null) return false; if (cell.IsOpen == null) if (_isInFight) cell.IsOpen = cell.IsCombatWalkable && _map.IsCellWalkable(cell.Cell, false, originCell == null ? null : originCell.Cell)/* && !cell.IsCloseToEnemy*/; else cell.IsOpen = _map.IsCellWalkable(cell.Cell, !_isCautious, originCell == null ? null : originCell.Cell)/* && (!_isCautious || !cell.IsCloseToEnemy)*/; return cell.IsOpen.Value; }
/// <summary> /// PathFinding main method /// </summary> /// <param name="startingCells"></param> /// <param name="exitCells"></param> /// <param name="selectFartherCells"></param> /// <param name="firstStepOnly"></param> /// <returns></returns> public bool FindPath(short[] startingCells, short[] exitCells, bool selectFartherCells = false, bool firstStepOnly = false, int maxDistanceParam = CellInfo.DEFAULT_DISTANCE) { Random rnd = new Random(); if ((startingCells == null) || (startingCells.Length == 0)) return false; // We need at least one starting stCell if (!firstStepOnly && (exitCells == null || exitCells.Length == 0)) return false; // We need at least one exit stCell for step 2 // PC starts at distance of 0. Set 0 to all possible starting cells CellInfo[] changed = new CellInfo[560]; int changedPtr = 0; CellInfo[] changing = new CellInfo[560]; int changingPtr = 0; bool optimizerActiv = !firstStepOnly && !selectFartherCells; // This strong optimization may fail to find a path. In that case, the non-optimized algorithm is run while (true) { ClearLogic(startingCells, exitCells); uint EstimatedDistance = CellInfo.DEFAULT_DISTANCE; Cell bestStartingCell = null; Cell bestEndingCell = null; foreach (short stCell in startingCells) if (_cells[stCell] != null) { _cells[stCell].DistanceSteps = 0; changed[changedPtr++] = _cells[stCell]; if (!firstStepOnly && !selectFartherCells) foreach (short exCell in exitCells) { if (exCell == stCell) { PathResult = new List<short> { stCell }; return true; // Empty path : starting stCell = exit stCell } if (optimizerActiv) { uint distance = _cells[stCell].Cell.ManhattanDistanceTo(_cells[exCell].Cell); if (distance < EstimatedDistance) { bestStartingCell = _cells[stCell].Cell; bestEndingCell = _cells[exCell].Cell; EstimatedDistance = distance; } } } } // cells[StartingCell].distanceSteps = 0; int maxDistance = maxDistanceParam; // We won't search over this distance - this optimization is OK in all cases if (optimizerActiv && bestStartingCell == null || bestEndingCell == null) optimizerActiv = false; while (changedPtr > 0) { changingPtr = 0; // Look at each square on the board. while (changedPtr > 0) { CellInfo curCell = changed[--changedPtr]; if (curCell.IsCloseToEnemy && _isCautious) continue; // Cautious mode (in or out of fight) : Can't move from a cell near an ennemy if (curCell.DistanceSteps < maxDistance) { if (optimizerActiv) // Strong optimisation { uint lastEstimatedDistance = curCell.Cell.ManhattanDistanceTo(bestEndingCell); uint startDistance = curCell.Cell.ManhattanDistanceTo(bestStartingCell); if (startDistance + lastEstimatedDistance > EstimatedDistance) continue; } //Debug.Assert((curCell != null && curCell.DistanceSteps < CellInfo.DEFAULT_DISTANCE)); short[] cellNeighbours = neighbours[curCell.CellId]; for (short i = 0; i < cellNeighbours.Length; i++) { CellInfo newCell = _cells[cellNeighbours[i]]; if (newCell == null) continue; if (newCell.DistanceSteps != 0 && !SquareOpen(newCell, null)) continue; //uint currentDistance = newCell.Cell.ManhattanDistanceTo(_cells[exitCells[0]].Cell); //if (currentDistance >= EstimatedDistance || currentDistance >= lastEstimatedDistance) continue; int newPass = curCell.DistanceSteps; if (curCell.IsCloseToEnemy) newPass++; // Penality when close of an ennemy (same in fight and RP map) if (_isInFight) newPass++; else newPass += newCell.Weight; if (newCell.DistanceSteps > newPass) { newCell.DistanceSteps = newPass; changing[changingPtr++] = newCell; if (!firstStepOnly && !selectFartherCells && newPass < maxDistance && exitCells.Any(id => newCell.CellId == id)) maxDistance = newPass; // We won't search on distance over closest exit } } if (_isInFight) continue; cellNeighbours = diagNeighbours[curCell.CellId]; for (short i = 0; i < cellNeighbours.Length; i++) // Process diagonals { CellInfo newCell = _cells[cellNeighbours[i]]; if (newCell == null) continue; if (newCell.DistanceSteps != 0 && !SquareOpen(newCell, null)) continue; int newPass = curCell.DistanceSteps; if (curCell.IsCloseToEnemy) newPass++; // Penality when close of an ennemy (same in fight and RP map) if (_isInFight) newPass++; else newPass += (int)(newCell.Weight * 1.414); if (newCell.DistanceSteps > newPass) { newCell.DistanceSteps = newPass; changing[changingPtr++] = newCell; if (!firstStepOnly && !selectFartherCells && newPass < maxDistance && exitCells.Any(id => newCell.CellId == id)) maxDistance = newPass; // We won't search on distance over closest exit } } } } CellInfo[] tmpChanged = changed; changed = changing; changedPtr = changingPtr; changing = tmpChanged; } if (firstStepOnly) return true; // Step 2 // Mark the path from Exit to Starting position. // if several Exit cells, then get the lowest distance one = the closest from one starting cell // (or the highest distance one if selectFartherCells) ExitCell = exitCells[0]; int MinDist = _cells[ExitCell].DistanceSteps; foreach (short cell in exitCells) if ((selectFartherCells && _cells[cell].DistanceSteps > MinDist) || (!selectFartherCells && _cells[cell].DistanceSteps < MinDist)) { ExitCell = cell; MinDist = _cells[cell].DistanceSteps; } if (optimizerActiv == false || MinDist < CellInfo.DEFAULT_DISTANCE) break; // No need to run a second unoptimized algorithm else optimizerActiv = false; } //int no = 0; //Debug.WriteLine("PathFinding from {0} ({1}) to {2} ({3})", _cells[startingCells[0]].cell, _cells[startingCells[0]].distanceSteps, _cells[ExitCell].cell, _cells[ExitCell].distanceSteps); /*List<Cell> ListMax = new List<Cell>(); List<Cell> ListInc = new List<Cell>(); foreach (var cell in _cells) { if (cell.distanceSteps >= CellInfo.DEFAULT_DISTANCE) ListMax.Add(cell.cell); if (cell.distanceSteps <= MinDist) ListInc.Add(cell.cell); //else // continue; Debug.Write(String.Format("{0} : {1}, ", cell.cell, cell.distanceSteps)); if (no++ == 5) { Debug.WriteLine(""); no = 0; } }*/ //Debug.WriteLine(""); //BotManager.Instance.Bots[0].Character.ResetCellsHighlight(); //BotManager.Instance.Bots[0].Character.HighlightCells(ListMax, Color.Black); //BotManager.Instance.Bots[0].Character.HighlightCells(ListMax, Color.DarkGray); short CurrentCell = ExitCell; PathResult.Add(ExitCell); _cells[ExitCell].IsInPath = true; CellInfo[] lowestPoints = changed; // No ned to alloc a new one, this one won't be used anymore int lowestPointsPtr = 0; short lowestPoint; int lowest; while (true) { // Look through each MapNeighbour and find the square // with the lowest number of steps marked. lowestPoint = CellInfo.CELL_ERROR; lowest = CellInfo.DEFAULT_DISTANCE; short[] neighbours = GetNeighbours(CurrentCell, _isInFight); for (short i = 0; i < neighbours.Length; i++) { //foreach (CellInfo newCell in ValidMoves(curCell, false)) CellInfo newCell = _cells[neighbours[i]]; if (newCell == null || (newCell.IsCloseToEnemy && _isCautious && newCell.DistanceSteps != 0)) continue; // In cautious mode, don't come close to an enemy //for (CellInfo NewCell in ValidMoves(_cells[CurrentCell], true)) //{ int distance = newCell.DistanceSteps; /*if (distance > CellInfo.DEFAULT_DISTANCE) { Debug.Assert(false, "Distance shouldn't be higher than DEFAULT_DISTANCE", "Distance = {0} > Max = {1}", distance, CellInfo.DEFAULT_DISTANCE); continue; }*/ if (distance < lowest) { lowestPointsPtr = 1; lowest = distance; lowestPoints[0] = newCell; } else if (distance == lowest) lowestPoints[lowestPointsPtr++] = newCell; } if (lowest == CellInfo.DEFAULT_DISTANCE) break; // Can't find a valid way :( if (lowestPointsPtr > 1) // Several points with same distance =>> randomly select one of them lowestPoint = lowestPoints[rnd.Next(lowestPointsPtr)].CellId; else lowestPoint = lowestPoints[0].CellId; // Mark the square as part of the path if it is the lowest // number. Set the current position as the square with // that number of steps. PathResult.Add(lowestPoint); if (PathResult.Count > _cells.Length) { Debug.Assert(false, "PathFinder can't find a path - overflow"); break; } //Debug.Assert(_cells[lowestPoint].IsInPath == false, "Point already in path", "CurrentCell : {0}, Lowest : {1} - distance : {2}, path : {3}", _cells[CurrentCell].Cell, _cells[lowestPoint].Cell, lowest, string.Join(",", _cells.Where(stCell => stCell.IsInPath))); _cells[lowestPoint].IsInPath = true; CurrentCell = lowestPoint; if (_cells[CurrentCell].DistanceSteps == 0) // Exit reached { StartingCell = CurrentCell; // We went from closest Exit to a Starting position, so we're finished. break; } } PathResult.Reverse(); return CurrentCell == StartingCell; }
public bool DrawCurrentMap(PictureBox pictureBox, bool isCombatMap, bool showAllCells, CellInfo.FieldNames SelectedInfo) { if (mapMngr.MapData == null) return false; g.Clear(Color.CadetBlue); g.SmoothingMode = SmoothingMode.HighQuality; Debug.Assert(mapMngr.MapData.Cells.Count == 560); int x = 0; int y = 0; //P.x = cellId % MAP_WIDTH + (cellId / MAP_WIDTH)/2 //P.y = cellId % MAP_WIDTH - (cellId / MAP_WIDTH)/2 for (int j = 0; j <= 39; j++) for (int i = 0; i <= 13; i++) { x = i * 64 + 32; if ((j & 1) == 1) x += 32; int cellId = j * 14 + i; y = j * 18 + 18; Color couleur = cells[cellId].color; Point center = new Point(x, y); //couleur = Color.Chartreuse; if ((/*!isCombatMap && */!cells[cellId].isWalkable) || (isCombatMap && !cells[cellId].isCombatWalkable)) couleur = Color.Black; if (PathFindingDone) { //if (mapMngr.CellsInfos[cellId].isInPath1) // couleur = Color.Blue; //if ((cellId == StartingCell) || (cellId == ExitCell)) // couleur = Color.LightBlue; } if (mapMngr.CellsInfos[cellId].drawable || showAllCells) { DrawPolygon(center, couleur, cells[cellId].isInPath1, cells[cellId].isInPath2, (cellId == StartingCell), (cellId == ExitCell), StartingCells != null && StartingCells.Contains(cellId), ExitCells != null && ExitCells.Contains(cellId)); if (SelectedInfo != CellInfo.FieldNames.Nothing) { center = new Point(center.X - 10, center.Y - 7); g.DrawString(cells[cellId].getValue(SelectedInfo), Control.DefaultFont, Brushes.AliceBlue, center); } //g.DrawString(CellsInfos[cellId].speed.ToString(), Font, Brushes.AliceBlue, center); } } //mise en picturebox //pictureBox.Invalidate(); pictureBox.Image = (Image)b.Clone(); return true; }
public MapMovement(CellInfo[] _cells) { cells = _cells; }