Created
February 14, 2011 21:59
-
-
Save nefigah/826649 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BspLevel | |
{ | |
public Tile[] Tiles { get; set; } | |
public int Width { get; set; } | |
public int Height { get; set; } | |
public ArraySegment<Tile>[] Rows { get; set; } | |
private const int minDimension = 4; | |
private const int maxRoomSize = 480; | |
private const int minRoomSize = 16; | |
public BspLevel LeftSublevel { get; set; } | |
public BspLevel RightSublevel { get; set; } | |
public BspLevel(int width, int height) | |
{ | |
Width = width; | |
Height = height; | |
Tiles = new Tile[width * height]; | |
Rows = new ArraySegment<Tile>[height]; | |
InitializeTiles(); | |
Split(); | |
GenerateRooms(); | |
} | |
public BspLevel(ArraySegment<Tile>[] tiles) | |
{ | |
Rows = tiles; | |
Width = tiles.First().Count; | |
Height = tiles.Length; | |
Split(); | |
} | |
public Tile this[int x, int y] | |
{ | |
get { return GetTile(y, x); } | |
} | |
public bool HasSublevels | |
{ | |
get | |
{ | |
return !(LeftSublevel == null && RightSublevel == null); | |
} | |
} | |
private void GenerateRooms() | |
{ | |
foreach (var subdungeon in this.CollectSublevels()) | |
{ | |
if (Util.SomeChanceInX(9, 10) && subdungeon.Width * subdungeon.Height > minRoomSize) | |
{ | |
double widthPercent = WpfRogueGame.RNG.Next(50, 100) / 100.0; | |
double heightPercent = WpfRogueGame.RNG.Next(50, 100) / 100.0; | |
int width = (int)(subdungeon.Width * widthPercent); | |
int height = (int)(subdungeon.Height * heightPercent); | |
int x = (subdungeon.Width - width) / 2; | |
int y = (subdungeon.Height - height) / 2; | |
var room = new Rectangle(x, y, width, height); | |
SetRectangularArea(TileType.DiscoveredFloor, room); | |
} | |
} | |
} | |
private void SetRectangularArea(TileType tileType, Rectangle room) | |
{ | |
for (int y = room.Y; y < room.Height; y++) | |
{ | |
for (int x = room.X; x < room.Width; x++) | |
{ | |
SetTile(tileType, y, x); | |
} | |
} | |
} | |
private IEnumerable<BspLevel> CollectSublevels() | |
{ | |
if (!HasSublevels) | |
{ | |
yield return this; | |
} | |
else | |
{ | |
if (LeftSublevel != null) | |
foreach (var sublevel in LeftSublevel.CollectSublevels()) | |
yield return sublevel; | |
if (RightSublevel != null) | |
foreach (var sublevel in RightSublevel.CollectSublevels()) | |
yield return sublevel; | |
} | |
} | |
private void InitializeTiles() | |
{ | |
for (int i = 0; i < Tiles.Length; i++) | |
{ | |
Tiles[i] = Tile.Make(TileType.Rock); | |
} | |
for (int i = 0; i < Height; i++) | |
{ | |
Rows[i] = new ArraySegment<Tile>(Tiles, i * Width, Width); | |
} | |
} | |
private void Split() | |
{ | |
bool split = (Rows.Length * Rows.First().Count >= maxRoomSize) || (Rows.Length >= minDimension * 2 && Rows.First().Count >= minDimension * 2 && Util.SomeChanceInX(7, 10)); | |
if (split) | |
{ | |
Tuple<BspLevel, BspLevel> splitted; | |
if (Util.SomeChanceInX(50, 100)) | |
{ | |
splitted = SplitHorizontally(); | |
} | |
else | |
{ | |
splitted = SplitVertically(); | |
} | |
LeftSublevel = splitted.Item1; | |
RightSublevel = splitted.Item2; | |
} | |
} | |
private Tuple<BspLevel, BspLevel> SplitVertically() | |
{ | |
if (Rows.First().Count <= minDimension * 2) | |
return new Tuple<BspLevel, BspLevel>(null, null); | |
int splitAt = WpfRogueGame.RNG.Next(0, Rows.First().Count - minDimension); | |
var level1 = new ArraySegment<Tile>[Rows.Length]; | |
var level2 = new ArraySegment<Tile>[Rows.Length]; | |
for (int j = 0; j < Rows.Length; j++) | |
{ | |
level1[j] = new ArraySegment<Tile>(Rows[j].Array, Rows[j].Offset, splitAt); | |
level2[j] = new ArraySegment<Tile>(Rows[j].Array, Rows[j].Offset + splitAt, Rows[j].Count - splitAt); | |
} | |
return new Tuple<BspLevel, BspLevel>(new BspLevel(level1), new BspLevel(level2)); | |
} | |
private Tuple<BspLevel, BspLevel> SplitHorizontally() | |
{ | |
if (Rows.Length <= minDimension * 2) | |
return new Tuple<BspLevel, BspLevel>(null, null); | |
int splitAt = WpfRogueGame.RNG.Next(0, Rows.Length - minDimension); | |
var level1 = new ArraySegment<Tile>[splitAt]; | |
var level2 = new ArraySegment<Tile>[Rows.Length - splitAt]; | |
for (int i = 0; i < splitAt; i++) | |
{ | |
level1[i] = Rows[i]; | |
} | |
for (int i = 0; i < Rows.Length - splitAt; i++) | |
{ | |
level2[i] = Rows[i]; | |
} | |
return new Tuple<BspLevel, BspLevel>(new BspLevel(level1), new BspLevel(level2)); | |
} | |
private Tile GetTileFromRow(ArraySegment<Tile> row, int column) | |
{ | |
return row.Array[row.Offset + column]; | |
} | |
private Tile GetTile(int row, int column) | |
{ | |
var segment = Rows[row]; | |
return GetTileFromRow(segment, column); | |
} | |
private void SetTile(TileType type, int row, int column) | |
{ | |
var segment = Rows[row]; | |
segment.Array[segment.Offset + column] = Tile.Make(type); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment