What I would like is the water surface to be like this:
------------------------------ <--- surface
But what I might get is something like this:
---______________ <--- Undesirable surface.
Basically the surface is leaning in either direction (thought it appears to be leaning to the right mostly)
I've spend about eight hours working on this, and I am no closer to a good solution.
While searching the web I found this method for handling water:
1.From bottom to top, if a cell which contains water is over a cell which could contain water but is not full, move as much water as can be moved from the upper cell to the lower one.
2.From bottom to top, for each cell which contains water, if the cell below cannot accommodate any more water, transfer 1/4 of the 'starting amount' of water to each side if there's room.
One full tile of water contains 100 units of water. I even tried doing it by transfering 1 unit instead og 1/4.. but this gave extremely undesirable effects, like floating water covering large areas very quickly... strange stuff
When I draw the water tiles (a tile is 16X16) I draw the depth of each tile like this - 16/100 * waterLevel. So a tile with 50 units of water will be drawn as 8 pixels deep. As you may notice in the code I keep the waterlevel value in bytes, to save memory and world file size.
Anyways, my current code will follow shortly - It is the simplest form I've made based on the method above- And also the most succesful one:
private void UpdateWater(GameTime gameTime)
{
/*_waterTimer -= (float)gameTime.ElapsedGameTime.TotalMilliseconds;
if (_waterTimer > 0)
return;
_waterTimer = 34;*/
for (int x = (int)(_pc.Position.X / StaticTileInfo.Size.X) - UPDATE_RADIUS_X; x < (int)(_pc.Position.X / StaticTileInfo.Size.X) + UPDATE_RADIUS_X; x++)
{
for (int y = (int)(_pc.Position.Y / StaticTileInfo.Size.Y) + UPDATE_RADIUS_Y; y > (int)(_pc.Position.Y / StaticTileInfo.Size.Y) - UPDATE_RADIUS_Y; y--)
{
if (x < 0 || x > tg.World.GetLength(0) || y < 0 || y > tg.World.GetLength(1))
continue;
if (tg.World[x, y].Type != TileType.Water)
continue;
//Water flows downwards
if (tg.World[x, y + 1].Type == TileType.Water)
{
if (((FluidTile)tg.World[x, y + 1]).WaterLevel < MAX_WATER_LEVEL)
{
if (((FluidTile)tg.World[x, y]).WaterLevel >= MAX_WATER_LEVEL - ((FluidTile)tg.World[x, y + 1]).WaterLevel)
{
((FluidTile)tg.World[x, y]).WaterLevel -= (byte)(MAX_WATER_LEVEL - ((FluidTile)tg.World[x, y + 1]).WaterLevel);
((FluidTile)tg.World[x, y + 1]).WaterLevel = MAX_WATER_LEVEL;
if (((FluidTile)tg.World[x, y]).WaterLevel == 0)
{
tg.World[x, y] = new Tile(TileType.None, tg.World[x, y].BackgroundType);
continue;
}
}
else
{
((FluidTile)tg.World[x, y + 1]).WaterLevel += ((FluidTile)tg.World[x, y]).WaterLevel;
tg.World[x, y] = new Tile(TileType.None, tg.World[x, y].BackgroundType);
continue;
}
}
}
else if (tg.World[x, y + 1].Collision != TileCollision.Impassable)
{
tg.World[x, y + 1] = new FluidTile(TileType.Water, tg.World[x, y + 1].BackgroundType, ((FluidTile)tg.World[x, y]).WaterLevel);
tg.World[x, y] = new Tile(TileType.None, tg.World[x, y].BackgroundType);
continue;
}
//Water flows leftwards
byte onefourth = (byte)(((FluidTile)tg.World[x, y]).WaterLevel / 4);
if (tg.World[x - 1, y].Type == TileType.Water)
{
if (((FluidTile)tg.World[x - 1, y]).WaterLevel + onefourth <= MAX_WATER_LEVEL)
{
((FluidTile)tg.World[x - 1, y]).WaterLevel += onefourth;
((FluidTile)tg.World[x, y]).WaterLevel -= onefourth;
}
}
else if (tg.World[x - 1, y].Collision != TileCollision.Impassable)
{
tg.World[x - 1, y] = new FluidTile(TileType.Water, tg.World[x - 1, y].BackgroundType, onefourth);
((FluidTile)tg.World[x, y]).WaterLevel -= onefourth;
}
//Water flows Rightwards
if (tg.World[x + 1, y].Type == TileType.Water)
{
if (((FluidTile)tg.World[x + 1, y]).WaterLevel + onefourth <= MAX_WATER_LEVEL)
{
((FluidTile)tg.World[x + 1, y]).WaterLevel += onefourth;
((FluidTile)tg.World[x, y]).WaterLevel -= onefourth;
}
}
else if (tg.World[x + 1, y].Collision != TileCollision.Impassable)
{
tg.World[x + 1, y] = new FluidTile(TileType.Water, tg.World[x + 1, y].BackgroundType, onefourth);
((FluidTile)tg.World[x, y]).WaterLevel -= onefourth;
}
}
}
}
The code in the top that is commented out is partly for controlling speed, but also because I feared performance issues, so I have it in place to limit the amount of cycles pr second used, if needed.
So my questions are:
- Did I stare myself blind on this and did I make an error I failed to find?
- If not- What changes to this method would possibly improve this?
If I am going about this the wrong way, don't hesitate to point it out- This game is supposed to be a learning experience after all
Thank you for reading