/// <summary> /// Calculate the cost to traverse this edge based on the slope between the two tile centers /// </summary> /// <param name="n1"></param> /// <param name="n2"></param> /// <returns></returns> private static float CalculateCost(MapTile n1, MapTile n2) { var dx = Math.Abs(n1.WorldPos.X - n2.WorldPos.X); var dz = Math.Abs(n1.WorldPos.Z - n2.WorldPos.Z); var dy = Math.Abs(n1.WorldPos.Y - n2.WorldPos.Y); var dxz = MathF.Sqrt(dx * dx + dz * dz); var slope = dy / dxz; return 1 +slope; }
public Unit(BasicModelInstance model, MapTile mp, Terrain terrain) { _modelInstance = model; MapTile = mp; _terrain = terrain; _position = mp.WorldPos; _position.Y += HeightOffset; Time = 0.0f; _activeWP = 0; Moving = false; MovePrc = 0; Speed = 1.0f; }
public List <MapTile> GetPath(Point start, Point goal) { var startTile = GetTile(start); var goalTile = GetTile(goal); // check that the start and goal positions are valid, and are not the same if (!Within(start) || !Within(goal) || start == goal || startTile == null || goalTile == null) { return(new List <MapTile>()); } // Check that start and goal are walkable and that a path can exist between them if (startTile.Set != goalTile.Set) { return(new List <MapTile>()); } // reset costs foreach (var t in _tiles) { t.F = t.G = float.MaxValue; } var open = new PriorityQueue <MapTile>(_tiles.Length); var closed = new HashSet <MapTile>(); startTile.G = 0; startTile.F = h(start, goal); open.Enqueue(startTile, startTile.F); MapTile current = null; while (open.Any() && current != goalTile) { current = open.Dequeue(); closed.Add(current); for (var i = 0; i < 8; i++) { var edge = current.Edges[i]; if (edge == null) { continue; } var neighbor = edge.Node2; var cost = current.G + edge.Cost; if (open.Contains(neighbor) && cost < neighbor.G) { open.Remove(neighbor); } if (closed.Contains(neighbor) && cost < neighbor.G) { closed.Remove(neighbor); } if (!open.Contains(neighbor) && !closed.Contains(neighbor)) { neighbor.G = cost; var f = cost + h(neighbor.MapPosition, goal); open.Enqueue(neighbor, f); neighbor.Parent = current; } } } System.Diagnostics.Debug.Assert(current == goalTile); var path = new List <MapTile>(); while (current != startTile) { path.Add(current); current = current.Parent; } path.Reverse(); return(path); }
protected override void OnMouseDown(object sender, MouseEventArgs e) { switch (e.Button) { case MouseButtons.Left: _minimap.OnClick(e); _lastMousePos = e.Location; Window.Capture = true; break; case MouseButtons.Right: // move the unit around using the right clicks var ray = _camera.GetPickingRay(new Vector2(e.X, e.Y), new Vector2(Viewport.Width, Viewport.Height)); var tile = new MapTile(); var worldPos = new Vector3(); // do intersection test if (!_terrain.Intersect(ray, ref worldPos, ref tile)) { return; } Console.WriteLine("Clicked at " + worldPos.ToString()); if (tile == null) { return; } // move the unit towards the new goal Console.WriteLine("Hit tile " + tile.MapPosition); Console.WriteLine("Moving unit to " + tile.MapPosition); _unit.Goto(tile); break; } }
public bool Intersect(Ray ray, ref Vector3 worldPos, ref MapTile mapPos) { Vector3 ret; QuadTreeNode ret2; if (!QuadTree.Intersects(ray, out ret, out ret2)) { return false; } ret.Y = Height(ret.X, ret.Z); worldPos = ret; mapPos = ret2.MapTile; return true; }
private void ResetTileMap() { _widthInTiles = Info.HeightMapWidth / TileSize; _heightInTiles = Info.HeightMapHeight / TileSize; _tiles = new MapTile[_widthInTiles * _heightInTiles]; for (var i = 0; i < _tiles.Length; i++) { _tiles[i] = new MapTile(); } }
/// <summary> /// Factory method to create an edge between two terrain tiles /// If the slope between two tiles is too great, return null, indicating that there is no connection between tiles /// </summary> /// <param name="tile"></param> /// <param name="neighbor"></param> /// <returns></returns> public static MapEdge Create(MapTile tile, MapTile neighbor) { var cost = CalculateCost(tile, neighbor); if (cost < 1+MapTile.MaxSlope) { return new MapEdge(tile, neighbor, cost); } return null; }
private MapEdge(MapTile n1, MapTile n2, float cost) { Node1 = n1; Node2 = n2; Cost = cost; }
private void MoveUnit(MapTile to) { // set the unit's last position to its current position _lastWP = MapTile.WorldPos; _lastWP.Y = _terrain.Height(_lastWP.X, _lastWP.Z) + HeightOffset; // set the unit's position to the next leg in the path MapTile = to; MovePrc = 0.0f; // set the next position to the next leg's position _nextWP = MapTile.WorldPos; _nextWP.Y = _terrain.Height(_nextWP.X, _nextWP.Z) + HeightOffset; }
public void Goto(MapTile mp) { if (_terrain == null) return; _path.Clear(); _activeWP = 0; if (Moving) { _path.Add(MapTile); var tmpPath = _terrain.GetPath(MapTile.MapPosition, mp.MapPosition); _path.AddRange(tmpPath); } else { _path = _terrain.GetPath(MapTile.MapPosition, mp.MapPosition); if (_path.Count <= 0) { // unit is already at goal position return; } Moving = true; MoveUnit(_path[_activeWP]); } }
protected override void OnMouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { _lastMousePos = e.Location; Window.Capture = true; } else if (e.Button == MouseButtons.Right) { var ray = _camera.GetPickingRay(new Vector2(e.X, e.Y), new Vector2(Viewport.Width, Viewport.Height)); var tile = new MapTile(); var worldPos = new Vector3(); _showSphere = _terrain.Intersect(ray, ref worldPos, ref tile); _spherePos = worldPos; Console.WriteLine("Clicked at " + _spherePos.ToString()); if (tile != null) { Console.WriteLine("Hit tile " + tile.MapPosition); } } }