• FEATURED

View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# 2D Tile based water using cellular automata.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

### #1Aaru  Members

Posted 04 November 2012 - 03:43 PM

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[Left].TileProp != TILE_GROUND)
{
//Equalize the amount of water in this block and it's neighbour
Flow = (TileList[ID].Mass - TileList[Left].Mass)/4;
if(Flow > MinFlow){Flow *= 0.05f;}
Flow = Constrain(Flow, 0, remainingmass);
TileList[ID].NewMass -= Flow;
TileList[Left].NewMass += Flow;
remainingmass -= Flow;
}
if(remainingmass <= 0)continue;
//Right
if(TileList[Right].TileProp != TILE_GROUND)
{
//Equalize the amount of water in this block and it's neighbour
Flow =(TileList[ID].Mass - TileList[Right].Mass)/4;
if(Flow > MinFlow){Flow *= 0.05f;}
Flow = Constrain(Flow, 0, remainingmass);
TileList[ID].NewMass -= Flow;
TileList[Right].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?

Edited by Aaru, 04 November 2012 - 03:50 PM.

### #2Aaru  Members

Posted 20 November 2012 - 12:08 PM

I fixed the issues myself(took me a while) here is the final video of it working.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.