private static void GenerateLake(System.Random lr, SZoneState zs, int h, int w) { // Select a random center point int lake_centerX = lr.Next(w); int lake_centerY = lr.Next(h); Vector2 lake_center = new Vector2(lake_centerX, lake_centerY); // Select an x, y radius pair double lake_radiusX = LAKE_MIN_RADIUS + lr.NextDouble() * (LAKE_MAX_RADIUS - LAKE_MIN_RADIUS); double lake_radiusY = LAKE_MIN_RADIUS + lr.NextDouble() * (LAKE_MAX_RADIUS - LAKE_MIN_RADIUS); // Select those cells which are in the ellipse for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { Vector3Int pos = new Vector3Int(x, y, 0); float dist = InsideEllipse(lake_center, pos, lake_radiusX, lake_radiusY); if (dist <= 1) { if (lr.NextDouble() > dist * dist) { zs.tileIDs[new SVector2Int(x, y)] = AssetLoader.GetTileID("boundsTile"); isCollidable[x][y] = true; } } } } }
public static SZoneState GenerateZone(long seed, Vector3Int zoneIndex) { int h = 128; int w = 128; SZoneState zs = new SZoneState(h, w, zoneIndex); isCollidable = new bool[w][]; entityGrid = new bool[w][]; for (int i = 0; i < w; i++) { isCollidable[i] = new bool[h]; entityGrid[i] = new bool[h]; } // Generate base map for (int y = -BORDER_THICKNESS; y < h + BORDER_THICKNESS; y++) { for (int x = -BORDER_THICKNESS; x < w + BORDER_THICKNESS; x++) { if (y < 0 || x < 0 || y >= h || x >= w) { // Bounds tile // boundsTilemap.SetTile(new Vector3Int(x, y, 0), AssetLoader.GetTileID("boundsTile").tile); zs.tileIDs.Add(new SVector2Int(x, y), AssetLoader.GetTileID("boundsTile")); } else { // Ground tile // baseTilemap.SetTile(new Vector3Int(x, y, 0), AssetLoader.GetTileID("groundTile").tile); zs.tileIDs.Add(new SVector2Int(x, y), AssetLoader.GetTileID("groundTile")); } } } System.Random r = new System.Random((int)seed); // Generate a river GenerateBezierRiver(r, zs, h, w); // Generate a lake GenerateLake(r, zs, h, w); // Generate trees GenerateTrees(r, zs, h, w); // Generate portals GenerateRightPortal(r, zs, h, w); GenerateLeftPortal(r, zs, h, w); GenerateTopPortal(r, zs, h, w); GenerateBottomPortal(r, zs, h, w); Debug.Log(zs.tileIDs.Count); return(zs); }
private static void GenerateTrees(System.Random lr, SZoneState zs, int h, int w) { // Select 2 to 5 forest starting points // Populate them with a elliptical circle // Add random trees // Make sure to fix the z index later int forest_count = lr.Next(2, 5); for (int i = 0; i < forest_count; i++) { Vector3Int forestCenter = new Vector3Int(); forestCenter.x = lr.Next(w * 1 / 6, w * 5 / 6); forestCenter.y = lr.Next(h * 1 / 6, h * 5 / 6); int forest_xSpan = lr.Next(FOREST_MIN_RADIUS, FOREST_MAX_RADIUS); int forest_ySpan = lr.Next(FOREST_MIN_RADIUS, FOREST_MAX_RADIUS); int maxManhattan = (forest_xSpan + forest_ySpan) / 2; // Debug.Log($"{forestCenter} -- {forestRadius}"); for (int x = forestCenter.x - forest_xSpan / 2; x <= forestCenter.x + forest_xSpan / 2; x++) { for (int y = forestCenter.y - forest_ySpan / 2; y <= forestCenter.y + forest_ySpan / 2; y++) { var vPos = new Vector3Int(x, y, 0); // TODO - check if (entityGrid[x][y] || CloseToBounds(vPos, zs)) { continue; } float manhattanDistance = Math.Abs(vPos.x - forestCenter.x) + Math.Abs(vPos.y - forestCenter.y); float relativeMHD = manhattanDistance / maxManhattan; if (lr.NextDouble() > relativeMHD * 2) { entityGrid[x][y] = true; GameEntityInfo e = new GameEntityInfo(); e.entityID = AssetLoader.GetEntityID("prototypeTree"); e.pos = new SVector3Int(x, y, 0); e.entityType = EntityType.BREAKABLE; zs.entityInfo.Add(e); } } } } }
private static void GenerateRiver(System.Random lr, SZoneState zs, int h, int w) { int river_side = lr.Next(); // Map the positions to the tilemap Vector3Int river_startPos = new Vector3Int(); Vector3Int river_endPos = new Vector3Int(); if (river_side % 2 == 0) { // up to down river_startPos.y = 0; river_endPos.y = h; river_startPos.x = lr.Next() % w; river_endPos.x = lr.Next() % w; } else { // right to left river_startPos.x = 0; river_endPos.x = w; river_startPos.y = lr.Next() % h; river_endPos.y = lr.Next() % h; } var river_direction = river_endPos - river_startPos; var river_normal = new Vector3Int(river_direction.y, -river_direction.x, 0); // Generate a line between startPos and endPos for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { Vector3Int pos = new Vector3Int(x, y, 0); float a1 = Mathf.Abs(Vector3.Dot(pos - river_startPos, river_normal)); // TODO - IMPROVE FOR F***S SAKE if (a1 < RIVER_THICKNESS) { if (a1 / RIVER_THICKNESS < 0.7f || lr.NextDouble() > a1 / RIVER_THICKNESS) { zs.tileIDs[new SVector2Int(x, y)] = AssetLoader.GetTileID("boundsTile"); isCollidable[x][y] = true; } } } } }
private static void AddPortalEntity(SZoneState zs, Vector3Int vPos, Vector3Int nextZone, Direction direction) { PortalInfo p = new PortalInfo(); GameEntityInfo e = new GameEntityInfo(); e.entityID = 2; e.entityType = EntityType.INTERACTABLE | EntityType.HOVERABLE; e.pos = vPos; p.entityInfo = e; p.nextZone = nextZone; p.directionToGo = direction; zs.portalInfo.Add(p); }
private static void GenerateRightPortal(System.Random lr, SZoneState zs, int h, int w) { int x = lr.Next(w / 2, w / 2 + w / 4); int y = lr.Next(h / 2 - (x - w / 2), h / 2 + (x - w / 2)); x += w / 4; Vector3Int vPos = new Vector3Int(x, y, 0); while (entityGrid[y][x] || CloseToBounds(vPos, zs)) { x = lr.Next(w / 2, w / 2 + w / 4); y = lr.Next(h / 2 - (x - w / 2), h / 2 + (x - w / 2)); x += w / 4; vPos = new Vector3Int(x, y, 0); } // Debug.Log("Added portal entity from right at " + vPos); AddPortalEntity(zs, vPos, zs.zoneIndex + Vector3Int.right, Direction.RIGHT); }
private static bool CloseToBounds(Vector3Int pos, SZoneState zs) { try { for (int i = 0; i < 8; i++) { int x = pos.x + Util.SURROUNDING_X[i]; int y = pos.y + Util.SURROUNDING_Y[i]; if (isCollidable[x][y]) { return(true); } } } catch (System.IndexOutOfRangeException) { return(true); } return(false); }
private static void GenerateBottomPortal(System.Random lr, SZoneState zs, int h, int w) { int y = lr.Next(h / 2 - h / 4, h / 2); int x = lr.Next(w / 2 - (h / 2 - y), w / 2 + (h / 2 - y)); y -= h / 4; Vector3Int vPos = new Vector3Int(x, y, 0); while (entityGrid[y][x] || CloseToBounds(vPos, zs)) { y = lr.Next(h / 2 - h / 4, h / 2); x = lr.Next(w / 2 - (h / 2 - y), w / 2 + (h / 2 - y)); y -= h / 4; vPos = new Vector3Int(x, y, 0); } // Debug.Log("Added portal entity from bottom at " + vPos); AddPortalEntity(zs, vPos, zs.zoneIndex + Vector3Int.down, Direction.BOTTOM); }
private static void GenerateTopPortal(System.Random lr, SZoneState zs, int h, int w) { int y = lr.Next(h / 2, h / 2 + h / 4); int x = lr.Next(w / 2 - (y - h / 2), w / 2 + (y - h / 2)); y += h / 4; Vector3Int vPos = new Vector3Int(x, y, 0); while (entityGrid[y][x] || CloseToBounds(vPos, zs)) { y = lr.Next(h / 2, h / 2 + h / 4); x = lr.Next(w / 2 - (y - h / 2), w / 2 + (y - h / 2)); y += h / 4; vPos = new Vector3Int(x, y, 0); } // Debug.Log("Added portal entity from top at " + vPos); AddPortalEntity(zs, vPos, zs.zoneIndex + Vector3Int.up, Direction.TOP); }
private static void GenerateLeftPortal(System.Random lr, SZoneState zs, int h, int w) { int x = lr.Next(w / 2 - w / 4, w / 2); int y = lr.Next(h / 2 - (w / 2 - x), h / 2 + (w / 2 - x)); x -= w / 4; Vector3Int vPos = new Vector3Int(x, y, 0); while (entityGrid[y][x] || CloseToBounds(vPos, zs)) { x = lr.Next(w / 2 - w / 4, w / 2); y = lr.Next(h / 2 - (w / 2 - x), h / 2 + (w / 2 - x)); x -= w / 4; vPos = new Vector3Int(x, y, 0); } // Debug.Log("Added portal entity from left at " + vPos); AddPortalEntity(zs, vPos, zs.zoneIndex + Vector3Int.left, Direction.LEFT); }
private static async Task WriteZoneData() { string zoneDataPath = ZoneLoader.zoneDataPath; UTF8Encoding uEnc = new UTF8Encoding(); byte[] result = await Task <byte[]> .Run(() => { SZoneState currentZoneState = GameState.GetInstance()._ZoneState.Serialize(); string zoneDat = JsonConvert.SerializeObject(currentZoneState); return(uEnc.GetBytes(zoneDat)); }); // Write backup async using (FileStream sw = File.OpenWrite(zoneDataPath + ".bak")) { await Task.Run(() => sw.WriteAsync(result, 0, result.Length)); } await Task.Run(() => File.Move(zoneDataPath, zoneDataPath + ".old")); await Task.Run(() => File.Move(zoneDataPath + ".bak", zoneDataPath)); await Task.Run(() => File.Delete(zoneDataPath + ".old")); }
private static void GenerateBezierRiver(System.Random lr, SZoneState zs, int h, int w) { int river_side = lr.Next(); // Map the positions to the tilemap Vector3Int river_startPos = new Vector3Int(); Vector3Int river_endPos = new Vector3Int(); if (river_side % 2 == 0) { // up to down river_startPos.y = 0; river_endPos.y = h; river_startPos.x = lr.Next() % w; river_endPos.x = lr.Next() % w; } else { // right to left river_startPos.x = 0; river_endPos.x = w; river_startPos.y = lr.Next() % h; river_endPos.y = lr.Next() % h; } // Get a random point around the middle List <Vector2> controlPoints = new List <Vector2>(); controlPoints.Add(Util.ToVector2(river_startPos)); controlPoints.Add(new Vector2(lr.Next(0, w / 4), lr.Next(h / 4, 3 * h / 4))); controlPoints.Add(Util.ToVector2(river_endPos)); BezierCurve bezier = new BezierCurve(controlPoints); for (int i = 0; i < BEZIER_ACCURACY; i++) { double t = i / (BEZIER_ACCURACY + 0.0); var point = bezier.GetPoint(t); Vector3Int tilePos = Util.ToVector3Int(point); zs.tileIDs[new SVector2Int(tilePos.x, tilePos.y)] = AssetLoader.GetTileID("boundsTile"); isCollidable[tilePos.x][tilePos.y] = true; // TODO - change for (int x = -RIVER_BEZIER_WIDTH / 2; x < (RIVER_BEZIER_WIDTH + 1) / 2; x++) { // boundsTilemap.SetTile(tilePos + new Vector3Int(x, 0, 0), AssetLoader.GetTileID("boundsTile").tile); // baseTilemap.SetTile(tilePos + new Vector3Int(x, 0, 0), null); zs.tileIDs[new SVector2Int(tilePos.x + x, tilePos.y)] = AssetLoader.GetTileID("boundsTile"); try { isCollidable[tilePos.x + x][tilePos.y] = true; } catch (Exception) { // Welp can't do much } } } }