• Advertisement
Sign in to follow this  

2D Tile based water using cellular automata.

This topic is 1891 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been trying to implement tile based water similar to terraria. I'm using C++ and SDL.
Here is my code for the simulation aspect of the water tiles.
My code is based off this java tutorial (http://w-shadow.com/...uid-simulation/)

void App::SimulateCompression()
{
float Flow = 0;
float remainingmass = 0;
//Calculate and apply flow for each block
for (int X = 0; X < MAP_WIDTH; X++)
{
for(int Y = 0; Y < MAP_HEIGHT; Y++)
{
int ID = Rect2Lin(TILE_SIZE,X,Y);
int Up = Rect2Lin(TILE_SIZE,X,(Y-1));
int Down = Rect2Lin(TILE_SIZE,X,(Y+1));
int Left = Rect2Lin(TILE_SIZE,(X-1),Y);
int Right = Rect2Lin(TILE_SIZE,(X+1),Y);
//Skip inert ground blocks
if(TileList[ID].TileProp == TILE_GROUND) continue;
//Custom push-only flow
Flow = 0;
remainingmass = TileList[ID].Mass;
if(remainingmass <= 0)continue;
//The block below this one
if(TileList[Down].TileProp != TILE_GROUND)
{
Flow = GetStableWaterState(remainingmass + TileList[Down].Mass) - TileList[Down].Mass;
if(Flow > MinFlow){Flow *= 0.05f;}
Flow = Constrain(Flow, 0, Min(MaxSpeed, remainingmass));
TileList[ID].NewMass -= Flow;
TileList[Down].NewMass += Flow;
remainingmass -= Flow;
}
if(remainingmass <= 0)continue;
//Left
if(TileList

.TileProp != TILE_GROUND)
{
//Equalize the amount of water in this block and it's neighbour
Flow = (TileList[ID].Mass - TileList

.Mass)/4;
if(Flow > MinFlow){Flow *= 0.05f;}
Flow = Constrain(Flow, 0, remainingmass);
TileList[ID].NewMass -= Flow;
TileList

.NewMass += Flow;
remainingmass -= Flow;
}
if(remainingmass <= 0)continue;
//Right
if(TileList

.TileProp != TILE_GROUND)
{
//Equalize the amount of water in this block and it's neighbour
Flow =(TileList[ID].Mass - TileList

.Mass)/4;
if(Flow > MinFlow){Flow *= 0.05f;}
Flow = Constrain(Flow, 0, remainingmass);
TileList[ID].NewMass -= Flow;
TileList

.NewMass += Flow;
remainingmass -= Flow;
}
if(remainingmass <= 0)continue;
//Up. Only compressed water flows upwards.
if(TileList[Up].TileProp != TILE_GROUND)
{
Flow = remainingmass - GetStableWaterState(remainingmass + TileList[Up].Mass);
if (Flow > MinFlow){Flow *= 0.05f;}
Flow = Constrain(Flow, 0, Min(MaxSpeed, remainingmass));
TileList[ID].NewMass -= Flow;
TileList[Up].NewMass += Flow;
remainingmass -= Flow;
}
}
}

//Copy the new mass values
for (int X = 0; X < MAP_WIDTH; X++)
{
for (int Y = 0; Y < MAP_HEIGHT; Y++)
{
int ID = Rect2Lin(TILE_SIZE,X,Y);
TileList[ID].Mass = TileList[ID].NewMass;
}
}
for(int X = 0; X < MAP_WIDTH; X++)
{
for(int Y = 0; Y < MAP_HEIGHT; Y++)
{
int ID = Rect2Lin(TILE_SIZE,X,Y);
//Skip ground blocks
if(TileList[ID].TileProp == TILE_GROUND) continue;
//Flag/unflag water blocks
if(TileList[ID].Mass > MinMass)
{
TileList[ID].TileProp = TILE_WATER;
}else
{
TileList[ID].TileProp = TILE_AIR;
}
}
}
//Remove any water that has left the map
for(int X = 0; X < MAP_WIDTH; X++)
{
TileList[Rect2Lin(TILE_SIZE,X,0)].Mass = 0;
TileList[Rect2Lin(TILE_SIZE,X,0)].TileProp = 0;
TileList[Rect2Lin(TILE_SIZE,X,MAP_HEIGHT - 1)].Mass = 0;
TileList[Rect2Lin(TILE_SIZE,X,MAP_HEIGHT - 1)].TileProp = 0;
//mass[x][0] = 0;
//mass[x][map_height+1] = 0;
}
for(int Y = 0; Y < MAP_HEIGHT; Y++)
{
TileList[Rect2Lin(TILE_SIZE,0,Y)].Mass = 0;
TileList[Rect2Lin(TILE_SIZE,0,Y)].TileProp = 0;
TileList[Rect2Lin(TILE_SIZE,(MAP_WIDTH - 1),Y)].Mass = 0;
TileList[Rect2Lin(TILE_SIZE,(MAP_WIDTH - 1),Y)].TileProp = 0;
//mass[0][y] = 0;
//mass[map_width+1][y] = 0;
}
}


The embeded video shows what happens when using this function. I really need help understanding why I'm not getting the same effects as the tutorial. Maybe, guide me on what I could do to fix these issues. I discovered that it has to do with the "flow" and how the masses are not being distributed among the other tiles. Any Ideas?




[Media]

[/Media] Edited by Aaru

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement