Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Aaru

Member Since 08 Aug 2011
Offline Last Active Nov 28 2013 03:47 PM

Topics I've Started

2D Tile based water using cellular automata.

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

UDP Multiplayer with SDL_net

08 August 2011 - 08:53 PM

Hello, this is my first time posting in these forums. I have been developing a game for several months now. I wanted to implement SDL_net into my code because my entire game engine uses SDL and many of the other addons (SDL_ttf/mixer/image..etc.) I have been coding the Multiplayer aspect of my game(2d side scroller). My experience with c++ is between 5-6 years so i have an understanding of the language. I'm using UDP for my game. The problem I'm having with SDL_net is that there are like no tutorials or examples on the net, which is very frustrating for someone trying to learn how to use it ( I have spent countless hours and days working on this without any help until now, i have used the faqs on this forum as well as the search bar where i searched through countless posts (dating back up to 4 years ago) about SDL_net where i saw a few people with my same problem but it looked like no one wanted to help them...) I am not asking to be spoon fed because i know thats not the right way and im a hard headed a@#hole who likes to learn by countless hours of trial and error. however, i just need a few hints on how to proceed. Ok, so now i will explain what I'm trying to freaken do lol:

tl;dr -> my client sends a packet with a "connecting" string to server, server reads packet and determines if there are available slots then server sends a string back to the client with "FULL" if
there are no slots left or a number if there are available slots to use as the clients ID. now my problem lies with sending packets from the server to the client.
for some reason i cant figure out how to send data to the client from the server.

On the server side i have tried to use these functions

IPaddress *address;
int chan;
 address =  SDLNet_UDP_GetPeerAddress(udpSocket, -1);

followed by the       	chan = SDLNet_UDP_Bind(udpSocket, -1, IPaddress *address);

I'm not quite sure what I'm supposed to be doing. am i supposed to SDLNet_UDP_GetPeerAddress first then use the
bind function afterwards and then SDLNet_UDP_Send. do i need to resolvehost at any point on the server side ? 


There is no documentation on the correct way of doing this. i mean there is the sdlnet wiki but its doesn't help me much.
maybe someone can send some pseudo code in SDLNet SYNTAX with the correct set up for a server using UDP or an example?
Also, I'm not looking to be flamed, i have looked into the faq and imo the answers are more generalized and not geared towards what I'm specifically looking for.

PARTNERS