Jump to content

  • Log In with Google      Sign In   
  • Create Account

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.

  • You cannot reply to this topic
1 reply to this topic

#1 Aaru   Members   -  Reputation: 224

Like
0Likes
Like

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?




http://www.youtube.com/watch?v=MpouMU62nK4&feature=youtu.be

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


Sponsor:

#2 Aaru   Members   -  Reputation: 224

Like
0Likes
Like

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.



PARTNERS