IntVector3 FindStartLoc(Random r, SideEdge edge) { int side = m_terrain.Width; int yo = r.Next(0, side); int zo = m_terrain.GetSurfaceLevel(MapCoord(yo, edge)); int yu = yo; int zu = zo; for (int y = yo - 1; y >= 0; --y) { int z = m_terrain.GetSurfaceLevel(MapCoord(y, edge)); if (z < zu) { zu = z; yu = y; } if (z - 2 > zu) { break; } } int yd = yo; int zd = zo; for (int y = yo + 1; y < side; ++y) { int z = m_terrain.GetSurfaceLevel(MapCoord(y, edge)); if (z < zd) { zd = z; yd = y; } if (z - 2 > zd) { break; } } int yf = zd < zu ? yd : yu; var p2 = MapCoord(yf, edge); return(m_terrain.GetSurfaceLocation(p2)); }
public bool CreateRiverPath() { int offset = m_random.Next(); m_riverPath = null; for (int i = 0; i < 8; ++i) { SideEdge edge = (SideEdge)((i + offset) % 4); var startLoc = FindStartLoc(m_random, edge); var target = new MyTarget(m_terrain, startLoc, edge); int maxNodeCount = 500000; // XXX this should reflect the map size var res = AStar.Find(new IntVector3[] { startLoc }, target, maxNodeCount); if (res.Status != AStarStatus.Found) { continue; } var riverPath = res.GetPathLocationsReverse().Select(p => p.ToIntVector2()).ToArray(); if (riverPath.Length < 100) { Trace.TraceInformation("retry, too short"); continue; } int tot = riverPath.Aggregate(0, (a, p) => a + MyMath.Min(p.X, p.Y, m_terrain.Width - p.X - 1, m_terrain.Height - p.Y - 1)); int avg = tot / riverPath.Length; if (avg < 20) { Trace.TraceInformation("too close to edge, avg {0}", avg); continue; } m_riverPath = riverPath; return(true); } return(false); }
IntVector2 MapCoord(int c, SideEdge edge) { switch (edge) { case SideEdge.Left: return(new IntVector2(0, c)); case SideEdge.Top: return(new IntVector2(c, 0)); case SideEdge.Right: return(new IntVector2(m_terrain.Width - 1, c)); case SideEdge.Bottom: return(new IntVector2(c, m_terrain.Height - 1)); default: throw new Exception(); } }
public MyTarget(TerrainData terrain, IntVector3 origin, SideEdge sourceSide) { m_terrain = terrain; m_origin = origin; m_sourceSide = sourceSide; }
IntVector2 MapCoord(int c, SideEdge edge) { switch (edge) { case SideEdge.Left: return new IntVector2(0, c); case SideEdge.Top: return new IntVector2(c, 0); case SideEdge.Right: return new IntVector2(m_terrain.Width - 1, c); case SideEdge.Bottom: return new IntVector2(c, m_terrain.Height - 1); default: throw new Exception(); } }
IntVector3 FindStartLoc(Random r, SideEdge edge) { int side = m_terrain.Width; int yo = r.Next(0, side); int zo = m_terrain.GetSurfaceLevel(MapCoord(yo, edge)); int yu = yo; int zu = zo; for (int y = yo - 1; y >= 0; --y) { int z = m_terrain.GetSurfaceLevel(MapCoord(y, edge)); if (z < zu) { zu = z; yu = y; } if (z - 2 > zu) break; } int yd = yo; int zd = zo; for (int y = yo + 1; y < side; ++y) { int z = m_terrain.GetSurfaceLevel(MapCoord(y, edge)); if (z < zd) { zd = z; yd = y; } if (z - 2 > zd) break; } int yf = zd < zu ? yd : yu; var p2 = MapCoord(yf, edge); return m_terrain.GetSurfaceLocation(p2); }
public MyTarget(TerrainData terrain, IntVector3 origin, SideEdge sourceSide) { m_terrain = terrain; m_origin = origin; m_sourceSide = sourceSide; }