Issues with 2D tile-based Sidescroller Water

Started by
12 comments, last by smorgasbord 11 years, 5 months ago
Hey there. On my journey through my sidescroller game I've come to the point where I need to add water. I started out today, and very quickly ended up with decent water. There was an issue though- When the water is finished updating (which might take some time depending on the pool size) the water is rarely flat on top. Let me illustrate

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 tongue.png

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 smile.png

Thank you for reading smile.png

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

Advertisement

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;
}
}
}
}

Fixed.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

From the description of the results you get, the description of the algorithm you wanted to implement, and a very quick look at the code, there is a logical error that you should handle.
Whether or not it gives you correct results is yet to be seen, but it explains why the right buckets have less than the left sides.

That is because you handle filling to the left before filling to the right.
When you are spilling down from a higher bucket into a lower one, there should be an extra check for both the left and right sides needing to be filled.
Currently you check the left, fill it, then check the right. By that time it is possible that there is not enough water to spill over to the right because you used it all on the left.

Before checking for left spillage, add a check for both right and left spillage together, then spill by ? in both directions instead of ¼.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


From the description of the results you get, the description of the algorithm you wanted to implement, and a very quick look at the code, there is a logical error that you should handle.
Whether or not it gives you correct results is yet to be seen, but it explains why the right buckets have less than the left sides.

That is because you handle filling to the left before filling to the right.
When you are spilling down from a higher bucket into a lower one, there should be an extra check for both the left and right sides needing to be filled.
Currently you check the left, fill it, then check the right. By that time it is possible that there is not enough water to spill over to the right because you used it all on the left.

Before checking for left spillage, add a check for both right and left spillage together, then spill by ? in both directions instead of ¼.


L. Spiro


Thanks a lot for the quick response. It makes sense what you say. I won't be able to try it out until tomorrow night (it's over 11pm here). But it does make sense to check in both direction.. But I'm thinking I define ¼. before doing any of the checks, based on the current remaining water. Shouldn't there be enough no matter what? Since 2 * ¼. = ½ of the remaining water. I might be wrong, a bit tired now :)

But I will apply your logic no matter what, since it seems that it favors one side from my tests there must be truth in what you say :D

Again- Thanks a lot for a quick and good response.

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri


I'm thinking I define &frac14;. before doing any of the checks, based on the current remaining water. Shouldn't there be enough no matter what? Since 2 * &frac14;. = &frac12; of the remaining water.

That is technically correct and may even be natural (you could say the water is draining twice as fast because it has twice as many places to go) but it would be worth an investigation to see how it looks when adding only half to each direction.


There is something else that might need to be fixed.
Using only the left code in my example (this applies to both sides), you do this:
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;
}


Due to clause #1 in which you move as much water from the top cell down to the bottom cell as you can, there may be the possibility that water is not distributed in even ¼’s to each cell.
This depends on unknown facts about the environment in which your cells/buckets live, so I can’t say for sure if this is a problem, but if there is any possibility that buckets are increased by anything other than even multiples of ¼, the code above needs to be fixed.
In that case you need to add as much to the bucket as will fit and add the rest to the bucket above it.
If you can guarantee your system always transfers multiples of ¼ each time, this is not a problem.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Hey there.
So I had a few hours to continue with this problem, and I've made some huge changes to how I handle water in my world. Instead of having a specific tile type for water, I instead added a water variable to all tiles. This allows me to flood things, instead of removing them (because the water tile would take the place of the... tree tile for example)This also simplified the code a bit, since I no longer need to check if the neighbouring tile is of the right type or not, I merely check if it contains any water or not, so no more typecasting back and forth smile.png
So this was the good news, I like it when there are positive side effects of problem solving...
Now, although I've been able to simplify my code, I don't feel any closer to a solution.
I tried the solution where I check both sides before pouring water in to them, but it gave the same results. I also tried to make sure that whenever water transfered downwards it was divideable with four. I might have messed something up by trying that, because I got very unpredictable results, but I was unable to see where, if so.
Anyways, now I have two code versions. The one is basically the one I posted earlier, a bit more simplified, which I will post below.
The other version I've made it so that a tile can contain no more than 16 units of water, and every time I transfer left or right, I only transfer 1 unit. This seems to be a very fast method, but the results are... crazy. So I decided to make a small video demonstrating both approaches, but first I'll post the code for them both

Code for 16 units max and 1 unit pr transfer:

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].WaterLevel == 0)
continue;
//Water flows downwards
if (tg.World[x, y + 1].WaterLevel < MAX_WATER_LEVEL && tg.World[x, y + 1].Collision != TileCollision.Impassable)
{
if (tg.World[x, y].WaterLevel >= MAX_WATER_LEVEL - tg.World[x, y + 1].WaterLevel)
{
tg.World[x, y].WaterLevel -= (byte)(MAX_WATER_LEVEL - tg.World[x, y + 1].WaterLevel);
tg.World[x, y + 1].WaterLevel = MAX_WATER_LEVEL;

if (tg.World[x, y].WaterLevel == 0)
continue;
}
else
{
tg.World[x, y + 1].WaterLevel += tg.World[x, y].WaterLevel;
tg.World[x, y].WaterLevel = 0;
continue;
}
}

//Water flows leftwards
//byte onefourth = (byte)(tg.World[x, y].WaterLevel / 4);
byte onefourth = 1;
if (tg.World[x - 1, y].WaterLevel + onefourth <= MAX_WATER_LEVEL && tg.World[x - 1, y].Collision != TileCollision.Impassable)
{
tg.World[x - 1, y].WaterLevel += onefourth;
tg.World[x, y].WaterLevel -= onefourth;
}

//Water flows Rightwards
if (tg.World[x + 1, y].WaterLevel + onefourth <= MAX_WATER_LEVEL && tg.World[x + 1, y].Collision != TileCollision.Impassable)
{
tg.World[x + 1, y].WaterLevel += onefourth;
tg.World[x, y].WaterLevel -= onefourth;
}
}
}
}



The "original code" - Max waterlevel = 100, and transfers 1/4 left and right.

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].WaterLevel == 0)
continue;
//Water flows downwards
if (tg.World[x, y + 1].WaterLevel < MAX_WATER_LEVEL && tg.World[x, y + 1].Collision != TileCollision.Impassable)
{
if (tg.World[x, y].WaterLevel >= MAX_WATER_LEVEL - tg.World[x, y + 1].WaterLevel)
{
tg.World[x, y].WaterLevel -= (byte)(MAX_WATER_LEVEL - tg.World[x, y + 1].WaterLevel);
tg.World[x, y + 1].WaterLevel = MAX_WATER_LEVEL;

if (tg.World[x, y].WaterLevel == 0)
continue;
}
else
{
tg.World[x, y + 1].WaterLevel += tg.World[x, y].WaterLevel;
tg.World[x, y].WaterLevel = 0;
continue;
}
}
//Water flows leftwards
byte onefourth = (byte)(tg.World[x, y].WaterLevel / 4);

if (tg.World[x - 1, y].WaterLevel + onefourth <= MAX_WATER_LEVEL && tg.World[x - 1, y].Collision != TileCollision.Impassable)
{
tg.World[x - 1, y].WaterLevel += onefourth;
tg.World[x, y].WaterLevel -= onefourth;
}
else if (tg.World[x - 1, y].WaterLevel + (byte)(onefourth / 2) <= MAX_WATER_LEVEL && tg.World[x - 1, y].Collision != TileCollision.Impassable)
{
tg.World[x - 1, y].WaterLevel += (byte)(onefourth / 2);
tg.World[x, y].WaterLevel -= (byte)(onefourth / 2);
}
//Water flows Rightwards
if (tg.World[x + 1, y].WaterLevel + onefourth <= MAX_WATER_LEVEL && tg.World[x + 1, y].Collision != TileCollision.Impassable)
{
tg.World[x + 1, y].WaterLevel += onefourth;
tg.World[x, y].WaterLevel -= onefourth;
}
else if (tg.World[x + 1, y].WaterLevel + (byte)(onefourth / 2) <= MAX_WATER_LEVEL && tg.World[x + 1, y].Collision != TileCollision.Impassable)
{
tg.World[x + 1, y].WaterLevel += (byte)(onefourth / 2);
tg.World[x, y].WaterLevel -= (byte)(onefourth / 2);
}
}
}


And here's the video:

[media]
[/media]

I'll throw in a few annotations in the video to help guide the attention. It's just a quick video with very little editing.

I really appreciate any time spend helping me out smile.png I feel I'm soo close to getting water off my to do list smile.png Thanks

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

Take the update order into account. For each tile, BOTH push and pull water to balance the levels. Else the update order affects how the water moves.

You should probably divide the water-flow-speed by 2 because for each link between 2 tiles, there might be 1 pull and 1 push if it doesnt balance out in the first tile update.

o3o


Take the update order into account. For each tile, BOTH push and pull water to balance the levels. Else the update order affects how the water moves.

You should probably divide the water-flow-speed by 2 because for each link between 2 tiles, there might be 1 pull and 1 push if it doesnt balance out in the first tile update.

If I understood you correctly each time I push water to the other tiles, I then try to pull some back, in case the push caused the receiveing tile to become more filled than the pushing tile. Is this correct?
Assuming it is I will try this solution, thanks you smile.png

Edit:
Or do you mean I should run through all the water twice, one forward and one backwards? Each taking their turn, so 30 updates for left to right, and 30 for right to left? - Left, right, left, right etc.?

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

no, first move water down.

then on another run, for both sides of a water, if the side is higher water level you pull water to the middle, else you push water to it.

so each water pushes and/or pulls water from both sides depending on whether they have more or less water.

And when pushing or pulling make sure you dont overfill a water block

o3o


no, first move water down.

then on another run, for both sides of a water, if the side is higher water level you pull water to the middle, else you push water to it.

so each water pushes and/or pulls water from both sides depending on whether they have more or less water.

And when pushing or pulling make sure you dont overfill a water block


Hey there. Thanks for the advice. I've now tried what you suggested but the results aren't that good. I get this.. wobbly surface, as if small regions are pushing water back and forth between each other.
I've tried the following:
- One run where it only updates the water downwards, followed by another run, doing pushes and pulls both left and right for each tile.
- Two runs, where each run both updates water downwards and pushes and pulls in both direction. One run updating towards left, and the other towards right.
- Two runs, no pulling only pushing. Each update both updates downwards and left and right. One updating from left to right, and the other right to left.

The best result is the last method, but that doesn't necesarily makes it the most correct one, since none of them is doing it right.
My current code is based on your suggestion, so please do tell me if I misunderstood that as well tongue.png


private void UpdateWater(GameTime gameTime)
{
if (!_updateWaterDown)
{
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].WaterLevel == 0)
continue;
//Water flows to/from left
byte onefourth = (byte)(tg.World[x, y].WaterLevel / 4);
if (onefourth == 0)
onefourth = 1;
if (tg.World[x, y].WaterLevel > tg.World[x - 1, y].WaterLevel)
{
if (tg.World[x - 1, y].WaterLevel + onefourth <= MAX_WATER_LEVEL && tg.World[x - 1, y].Collision != TileCollision.Impassable)
{
tg.World[x - 1, y].WaterLevel += onefourth;
tg.World[x, y].WaterLevel -= onefourth;
}
else if (tg.World[x - 1, y].WaterLevel + (byte)(onefourth / 2) <= MAX_WATER_LEVEL && tg.World[x - 1, y].Collision != TileCollision.Impassable)
{
tg.World[x - 1, y].WaterLevel += (byte)(onefourth / 2);
tg.World[x, y].WaterLevel -= (byte)(onefourth / 2);
}
}
else if (tg.World[x, y].WaterLevel < tg.World[x - 1, y].WaterLevel)
{
if (tg.World[x, y].WaterLevel + onefourth <= MAX_WATER_LEVEL)
{
tg.World[x, y].WaterLevel += onefourth;
tg.World[x - 1, y].WaterLevel -= onefourth;
}
else if (tg.World[x, y].WaterLevel + (byte)(onefourth / 2) <= MAX_WATER_LEVEL)
{
tg.World[x, y].WaterLevel += (byte)(onefourth / 2);
tg.World[x - 1, y].WaterLevel -= (byte)(onefourth / 2);
}
}
//Water flows to/from right
if (tg.World[x, y].WaterLevel > tg.World[x + 1, y].WaterLevel)
{
if (tg.World[x + 1, y].WaterLevel + onefourth <= MAX_WATER_LEVEL && tg.World[x + 1, y].Collision != TileCollision.Impassable)
{
tg.World[x + 1, y].WaterLevel += onefourth;
tg.World[x, y].WaterLevel -= onefourth;
}
else if (tg.World[x + 1, y].WaterLevel + (byte)(onefourth / 2) <= MAX_WATER_LEVEL && tg.World[x + 1, y].Collision != TileCollision.Impassable)
{
tg.World[x + 1, y].WaterLevel += (byte)(onefourth / 2);
tg.World[x, y].WaterLevel -= (byte)(onefourth / 2);
}
}
else if (tg.World[x, y].WaterLevel < tg.World[x + 1, y].WaterLevel)
{
if (tg.World[x, y].WaterLevel + onefourth <= MAX_WATER_LEVEL)
{
tg.World[x, y].WaterLevel += onefourth;
tg.World[x + 1, y].WaterLevel -= onefourth;
}
else if (tg.World[x, y].WaterLevel + (byte)(onefourth / 2) <= MAX_WATER_LEVEL)
{
tg.World[x, y].WaterLevel += (byte)(onefourth / 2);
tg.World[x + 1, y].WaterLevel -= (byte)(onefourth / 2);
}
}
}
}
_updateWaterDown = !_updateWaterDown;
}
else
{
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].WaterLevel == 0)
continue;
//Water flows downwards
if (tg.World[x, y + 1].WaterLevel < MAX_WATER_LEVEL && tg.World[x, y + 1].Collision != TileCollision.Impassable)
{
if (tg.World[x, y].WaterLevel >= MAX_WATER_LEVEL - tg.World[x, y + 1].WaterLevel)
{
tg.World[x, y].WaterLevel -= (byte)(MAX_WATER_LEVEL - tg.World[x, y + 1].WaterLevel);
tg.World[x, y + 1].WaterLevel = MAX_WATER_LEVEL;
if (tg.World[x, y].WaterLevel == 0)
continue;
}
else
{
tg.World[x, y + 1].WaterLevel += tg.World[x, y].WaterLevel;
tg.World[x, y].WaterLevel = 0;
continue;
}
}
}
}
_updateWaterDown = !_updateWaterDown;
}
}


Am I doing it the right way?
Is there another approach I should consider?

This is a tough one, and I've failed to dig up much information about tile based water online. I really appreciate all the help I get here, and any suggestions are welcome.

Thank you smile.png

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

This topic is closed to new replies.

Advertisement