public static Block[,,] GenerateTile(int tileHeight, int tileWidth, int tileDepth, Tile tile) { if (!initialized) { InitializeMaterials(); } int tileX = tile.tileX; int tileY = tile.tileY; Block[,,] blocks = new Block[tileHeight, tileWidth, tileDepth]; float[,] depth1 = Simplex.Noise.Calc2D(tileWidth, tileHeight, 0.001f); float[,] depth2 = Simplex.Noise.Calc2D(tileWidth, tileHeight, 0.01f); float[,] depth3 = Simplex.Noise.Calc2D(tileWidth, tileHeight, 0.05f); float[,] depth4 = Simplex.Noise.Calc2D(tileWidth, tileHeight, 0.1f); int offsetX = tile.tileX * Map.TILE_WIDTH; int offsetY = tile.tileY * Map.TILE_HEIGHT; for (byte i = 0; i < tileDepth; i++) { for (byte j = 0; j < tileHeight; j++) { int blockDepth1 = (int)Math.Round((depth1[i, j] / 512) * Map.TILE_DEPTH); int blockDepth2 = (int)Math.Round((depth2[i, j] / 1024) * Map.TILE_DEPTH); int blockDepth3 = (int)Math.Round((depth3[i, j] / 2048) * Map.TILE_DEPTH); int blockDepth4 = (int)Math.Round((depth4[i, j] / 4096) * Map.TILE_DEPTH); int blockDepth = (blockDepth1 + blockDepth2 + blockDepth3 + blockDepth4) + 20; for (byte k = 0; k < tileWidth; k++) { if (k < blockDepth) { blocks[i, j, k] = new BlockSolid(materialDirt); } else if (i == 50 && j > 97) //else if (k < WATER_LEVEL) { int worldCol = tile.tileX * Map.TILE_WIDTH + i; int worldRow = tile.tileY * Map.TILE_HEIGHT + j; BlockLiquid newBlock = new BlockLiquid(materialWater, worldCol, worldRow, k); blocks[i, j, k] = newBlock; } else { blocks[i, j, k] = new BlockEmpty(); } } } } return(blocks); }
private List <BlockLiquid> GetAvailableNeighbors() { List <BlockLiquid> neighbors = new List <BlockLiquid>(); int[,] positionsToCheck = { { worldCol + 1, worldRow, depth }, { worldCol - 1, worldRow, depth }, { worldCol, worldRow + 1, depth }, { worldCol, worldRow - 1, depth }, }; for (int i = 0; i < positionsToCheck.GetLength(0); i++) { // First, get the block Block neighbor = Map.GetInstance().GetBlockAt( positionsToCheck[i, 0], positionsToCheck[i, 1], positionsToCheck[i, 2] ); // We'll need this later BlockLiquid neighborLiquid; // If there's an empty block, put an empty liquid block there BlockEmpty neighborEmpty = neighbor as BlockEmpty; if (neighborEmpty != null) { neighborLiquid = new BlockLiquid( material, positionsToCheck[i, 0], positionsToCheck[i, 1], (byte)positionsToCheck[i, 2], 0); neighborLiquid.SetSelfInTile(); neighbors.Add(neighborLiquid); } else if (neighbor is BlockLiquid) { //TODO: DO /*neighborLiquid = (BlockLiquid)neighbor; * neighbors.Add(neighborLiquid);*/ } } return(neighbors); }
public override void Update(GameTime gameTime) { // When there is no liquid left, there's no point in keeping the block around if (quantity == 0) { tile.SetBlock(col, row, depth, new BlockEmpty()); return; } // Check for an valid neighbor below if (depth > 0) { // Empty neighbor below, we can just move down directly Block neighborBelow = Map.GetInstance().GetBlockAt(worldCol, worldRow, depth - 1); if (neighborBelow is BlockEmpty) { tile.SetBlock(col, row, depth, new BlockEmpty()); BlockLiquid newBlockBelow = new BlockLiquid(material, worldCol, worldRow, (byte)(depth - 1), quantity); newBlockBelow.SetSelfInTile(); quantity = 0; return; } // Liquid below, transfer what we can if (neighborBelow is BlockLiquid) { BlockLiquid liquidNeighborBelow = (BlockLiquid)neighborBelow; byte freeSpaceBelow = (byte)(byte.MaxValue - liquidNeighborBelow.quantity); if (freeSpaceBelow > 0) { if (quantity <= freeSpaceBelow) { tile.SetBlock(col, row, depth, new BlockEmpty()); liquidNeighborBelow.quantity += quantity; } else { quantity -= freeSpaceBelow; AddToUpdateQueue(); liquidNeighborBelow.quantity += freeSpaceBelow; } liquidNeighborBelow.AddToUpdateQueue(); } } } if (quantity == 1) { quantity = 0; tile.SetBlock(col, row, depth, new BlockEmpty()); } /*if (quantity < 3) * { * return; * }*/ // If we reach this point, it means there is still water in this block // Try to spread to sides List <BlockLiquid> spreadBlocks = GetAvailableNeighbors(); if (spreadBlocks.Count == 0) { return; } spreadBlocks.Add(this); int totalQuantity = 0; foreach (BlockLiquid block in spreadBlocks) { totalQuantity += block.quantity; } byte averageQuantity = (byte)(totalQuantity / spreadBlocks.Count); int rest = totalQuantity % spreadBlocks.Count; foreach (BlockLiquid block in spreadBlocks) { if (Math.Abs(quantity - averageQuantity) <= 1) { return; } block.quantity = averageQuantity; if (rest > 0 && block.quantity < byte.MaxValue) { rest--; block.quantity++; } block.AddToUpdateQueue(); } }