internal void onTileHover(Tile newTile) { if (hoveredTile != null) { FlagsHelper.Unset(ref hoveredTile.highlightStatus, TileHighlightStatus.Highlighted); } if (newTile != null) { hoveredTile = newTile; FlagsHelper.Set(ref hoveredTile.highlightStatus, TileHighlightStatus.Highlighted); } }
internal void onAttackTile(Tile newTile) { if (attackTile != null) { FlagsHelper.Unset(ref attackTile.highlightStatus, TileHighlightStatus.Attack); } attackTile = newTile; if (attackTile != null) { FlagsHelper.Set(ref attackTile.highlightStatus, TileHighlightStatus.Attack); } }
internal void onTileSelected(Tile newTile) { if (selectedTile != null) { FlagsHelper.Unset(ref selectedTile.highlightStatus, TileHighlightStatus.Selected); selectedTile.showPieceRotation = false; } selectedTile = newTile; if (selectedTile != null) { FlagsHelper.Set(ref selectedTile.highlightStatus, TileHighlightStatus.Selected); selectedTile.showPieceRotation = true; } }
private Dictionary<Vector2, Tile> CreateTiles(int x, int z) { var tiles = new Dictionary<Vector2, Tile>(); for (int i = 0; i < x; i++) { for (int j = 0; j < z; j++) { var fullPosition = new Vector3(i, 0, j); var position = new Vector2(i, j); var newTile = new Tile() { gameObject = null, position = position, fullPosition = fullPosition }; tiles.Add(position, newTile ); } } return tiles; }
void onTileHover(Tile tile) { tileHover.Dispatch(tile); view.onTileHover(tile); if (selectedPiece != null && tile != null && !selectedPiece.hasMoved) { var gameTile = map.tiles.Get(selectedPiece.tilePosition); var enemyOccupyingDest = pieces.Pieces.Any(m => m.tilePosition == tile.position && !m.currentPlayerHasControl && !FlagsHelper.IsSet(m.statuses, Statuses.Cloak) ); //don't show move path for ranged units hovering over an enemy if (!(enemyOccupyingDest && selectedPiece.range.HasValue)) { //add an extra tile of movement if the destination is an enemy to attack since you don't have to go all the way to them var boost = enemyOccupyingDest ? 1 : 0; var path = mapService.FindPath(gameTile, tile, selectedPiece.movement + boost, gameTurn.currentPlayerId); view.toggleTileFlags(path, TileHighlightStatus.PathFind); if (enemyOccupyingDest && path != null ) { view.onAttackTile(tile); } else { view.onAttackTile(null); } } else { view.toggleTileFlags(null, TileHighlightStatus.PathFind); } } else { view.toggleTileFlags(null, TileHighlightStatus.PathFind); view.onAttackTile(null); } //display area preview on area targeting if ( selectingArea != null && selectingArea.area != null && selectingArea.area.isCursor && !selectingArea.area.stationaryArea && tile != null && FlagsHelper.IsSet(tile.highlightStatus, TileHighlightStatus.TargetTile) ) { List<Tile> tiles = null; switch (selectingArea.area.areaType) { case AreaType.Square: tiles = mapService.GetKingTilesInRadius(tile.position, selectingArea.area.size).Values.ToList(); break; case AreaType.Cross: tiles = mapService.GetCrossTiles(tile.position, selectingArea.area.size).Values.ToList(); break; case AreaType.Line: case AreaType.Row: case AreaType.Diagonal: if (selectingArea.selectedPosition != null) { tiles = mapService.GetLineTiles( selectingArea.selectedPosition.Value, tile.position, selectingArea.area.size, selectingArea.area.bothDirections ?? false ).Values.ToList(); } break; } if (tiles != null) { //TODO: find out from area if it can hit friendlies setAttackRangeTiles(tiles, true); } } }
public void CreateMap(MapImportModel map) { var mapTilePrefab = Resources.Load("Tile") as GameObject; var mapMaterials = new Dictionary<string, Material>(); mapMaterials["clay"] = Resources.Load("Materials/tiles/tile_clay") as Material; mapMaterials["grass"] = Resources.Load("Materials/tiles/tile_grass") as Material; mapMaterials["rock"] = Resources.Load("Materials/tiles/tile_rock") as Material; mapMaterials["sand"] = Resources.Load("Materials/tiles/tile_sand") as Material; mapMaterials["water"] = Resources.Load("Materials/tiles/tile_water") as Material; var goMap = GameObject.Find("Map"); if (goMap != null) { GameObject.Destroy(goMap); } goMap = new GameObject("Map"); goMap.transform.parent = contextView.transform; mapModel.root = goMap; mapModel.name = map.name; mapModel.maxPlayers = map.maxPlayers; mapModel.tiles = new Dictionary<Vector2, Tile>(); foreach (var t in map.tiles) { var fullPosition = new Vector3(t.transform.x, t.transform.y, t.transform.z); var newTileGO = GameObject.Instantiate( mapTilePrefab, fullPosition, Quaternion.identity ) as GameObject; newTileGO.transform.parent = goMap.transform; //set up material var tileRenderer = newTileGO.transform.Find("cube").GetComponent<MeshRenderer>(); tileRenderer.material = mapMaterials[t.material]; var tileVarietyColor = Random.Range(0.85f, 1); tileRenderer.material.color = new Color(tileVarietyColor, tileVarietyColor, tileVarietyColor); //position and set up map references var position = new Vector2(t.transform.x, t.transform.z); var newTile = new Tile() { gameObject = newTileGO, position = position, fullPosition = fullPosition, unpassable = t.unpassable }; mapModel.tiles.Add(position, newTile ); newTileGO.AddComponent<TileView>(); newTileGO.GetComponent<TileView>().tile = newTile; var indicator = newTileGO.transform.Find("Indicator").gameObject; indicator.AddComponent<TilePieceIndicatorialView>(); } mapCreated.Dispatch(); }
public List<Tile> FindPath(Tile start, Tile end, int maxDist, int controllingPlayerId) { var ret = new List<Tile>(); if(start == end) return ret; // The set of nodes already evaluated. var closedset = new List<Tile>(); // The set of tentative nodes to be evaluated, initially containing the start node var openset = new List<Tile>(){ start }; // The map of navigated nodes. var came_from = new Dictionary<Tile, Tile>(); var g_score = new Dictionary<Tile, int>(); g_score[start] = 0; // Cost from start along best known path. // Estimated total cost from start to goal through y. var f_score = new Dictionary<Tile, int>(); f_score[start] = g_score[start] + heuristic_cost_estimate(start, end); while (openset.Count > 0) { // the node in openset having the lowest f_score[] value var current = openset.OrderBy(x => getValueOrMax(f_score,x)).First(); if (current == end) { return ReconstructPath(came_from, end); } openset.Remove(current); closedset.Add(current); var neighbors = GetMovableNeighbors(current, controllingPlayerId, end); foreach (var neighborDict in neighbors) { var neighbor = neighborDict.Value; if(closedset.Contains(neighbor)){ continue; } var tentative_g_score = getValueOrMax(g_score,current) + TileDistance(current.position, neighbor.position); if (!openset.Contains(neighbor) || tentative_g_score < getValueOrMax(g_score,neighbor)) { //check for max dist along path if (tentative_g_score > maxDist) { continue; } came_from[neighbor] = current; g_score[neighbor] = tentative_g_score; f_score[neighbor] = getValueOrMax(g_score,neighbor) + TileDistance(neighbor.position, end.position); if (!openset.Contains(neighbor)) { openset.Add(neighbor); } } } } return null; }
private List<Tile> ReconstructPath(Dictionary<Tile, Tile> came_from, Tile current) { var total_path = new List<Tile>() { current }; while( came_from.ContainsKey(current)){ current = came_from[current]; total_path.Add(current); } total_path.Reverse(); //remove starting tile return total_path.Skip(1).ToList(); }
private int heuristic_cost_estimate(Tile start, Tile end) { return TileDistance(start.position, end.position); }
private int getValueOrMax(Dictionary<Tile, int> dict, Tile key) { if(dict.ContainsKey(key)) return dict[key]; return int.MaxValue; }
public bool isHeightPassable(Tile start, Tile end) { return Math.Abs(start.fullPosition.y - end.fullPosition.y ) < Constants.heightDeltaThreshold; }
/// <summary> /// Find neighboring tiles that aren't occupied by enemies, /// but always include the dest tile for attacking if it's passed /// but also make sure not to land on a tile with an occupant if attacking /// </summary> public Dictionary<Vector2, Tile> GetMovableNeighbors(Tile center, int controllingPlayerId, Tile dest = null) { var ret = GetNeighbors(center.position); //filter tiles that are too high/low to move to & are passable ret = ret.Where(t => !t.Value.unpassable && isHeightPassable(t.Value, center)).ToDictionary(k => k.Key, v => v.Value); //filter out tiles with enemies on them that aren't the destination ret = ret.Where(t => (dest != null && t.Key == dest.position) || !pieces.Pieces.Any(m => m.tilePosition == t.Key && m.playerId != controllingPlayerId) ).ToDictionary(k => k.Key, v => v.Value); bool destinationOccupied = dest != null && pieces.Pieces.Any(p => p.tilePosition == dest.position); //make sure not to consider tiles that would be where the moving pieces lands when it attacks ret = ret.Where(t => dest == null || dest.position == t.Key || !destinationOccupied || TileDistance(t.Key, dest.position) > 1 || !pieces.Pieces.Any(p => p.tilePosition == t.Key) ).ToDictionary(k => k.Key, v => v.Value); return ret; }
private bool updateTarget(Tile tile) { if(cardTarget == null) return false; if(cardTarget.area == null) return true; if (!FlagsHelper.IsSet(tile.highlightStatus, TileHighlightStatus.TargetTile)) { cancelSelectTarget.Dispatch(cardTarget.targetingCard); return false; } if (!cardTarget.selectedPosition.HasValue) { cardTarget.selectedPosition = tile.position; } else if(cardTarget.selectedPosition != tile.position) { cardTarget.selectedPivotPosition = tile.position; } updateTargetSignal.Dispatch(cardTarget); return true; }