SDL Loop

Started by
8 comments, last by BigBoy 19 years, 4 months ago
Hello. I have been making a game using SDL and SDL_Net. It's a gomoku game if anybody knows what it is but the problem is that it only works when I move the mouse on the server for like 2 secs then it locks up and waits untill I move the mouse on the pc that joins the server which also locks up untill I move it on the server again. Here is the code. I think it has to do with the SDL loop. It is really ugly but whatever :P

// Includes
#include "GomokuNet.h"

// surfaces
SDL_Surface *screen;
SDL_Surface *black;
SDL_Surface *white;
SDL_Surface *selector;
SDL_Surface *board;
SDL_Surface *whiteturn;
SDL_Surface *blackturn;
SDL_Surface *wonbg;
SDL_Surface *blackwon;
SDL_Surface *whitewon;
SDL_Surface *newgame;
SDL_Surface *connectbg;

// Game State vars
int done = 0;
int MouseX;
int MouseY;
int SelectX = 0;
int SelectY = 0;
int SelectX2 = 0;
int SelectY2 = 0;
int Map[19][19];
int Turn = 0;
int GameOver = 0;
int X1 = 0;
int Y1 = 0;


// sdlnet stuff
IPaddress IPHost;
IPaddress IPClient;
TCPsocket TCPHost;
TCPsocket TCPNewHost;
TCPsocket TCPClient;
char ConnectIP[12];
char SendMessages[20];
char RecvMessage[20];
bool Hosting;

bool FirstMsgSend = false;
bool Connected = false;
int sendresult;

// Blit func
void DrawIMG(SDL_Surface *img, int x, int y)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}

int main(int argc, char* argv[])
{
	if (SDL_Init(SDL_INIT_VIDEO) == -1)
	{
		return 0;
	}

	if (SDLNet_Init() == -1)
	{
		return 0;
	}

	MainMenu();

	if (Quit == true)
	{

		return 0;
	}

	if (Hosting == true)
	{
		SDLNet_ResolveHost(&IPHost, NULL, 27015);
		TCPHost = SDLNet_TCP_Open(&IPHost);

		if (!TCPHost)
		{
			MessageBox(NULL, "Error: Couldn't connect host", "Error:", MB_OK);

			return 0;
		}
	}
	else
	{
		SDLNet_ResolveHost(&IPClient,  ConnectIP, 27015);
		TCPClient = SDLNet_TCP_Open(&IPClient);

		if (!TCPClient)
		{
			MessageBox(NULL, "Error: Couldn't connect to IP Address", "Error:", MB_OK);

			return 0;
		}
		else
		{
			Connected = true;
		}
	}

	strcpy(SendMessages, "  ");

	// Game
	screen = SDL_SetVideoMode(640, 456, 32, SDL_HWSURFACE | SDL_ANYFORMAT | SDL_HWACCEL | SDL_DOUBLEBUF);
	SDL_WM_SetCaption("Gomoku 1.2 MultiPlayer", NULL);

	// Load images
	black = SDL_LoadBMP("Images/black.bmp");
	white = SDL_LoadBMP("Images/white.bmp");
	selector = SDL_LoadBMP("Images/select.bmp");
	board = SDL_LoadBMP("Images/board.bmp");
	whiteturn = SDL_LoadBMP("Images/turnwhite.bmp");
	blackturn = SDL_LoadBMP("Images/turnblack.bmp");
	wonbg = SDL_LoadBMP("Images/gameover.bmp");
	whitewon = SDL_LoadBMP("Images/whitewon.bmp");
	blackwon = SDL_LoadBMP("Images/blackwon.bmp");
	newgame = SDL_LoadBMP("Images/NewGame.bmp");
	connectbg = SDL_LoadBMP("Images/connect.bmp");

	// Set colorkeys
	SDL_SetColorKey(white, SDL_SRCCOLORKEY, SDL_MapRGB(white->format, 0, 0, 255));
	SDL_SetColorKey(black, SDL_SRCCOLORKEY, SDL_MapRGB(black->format, 0, 0, 255));
	SDL_SetColorKey(selector, SDL_SRCCOLORKEY, SDL_MapRGB(selector->format, 0, 0, 255));
	SDL_SetColorKey(newgame, SDL_SRCCOLORKEY, SDL_MapRGB(newgame->format, 0, 0, 255));

	while(done == 0)
	{
		SDL_Event event;

		Sleep(1);

		while ( SDL_PollEvent(&event) )
		{
				if ( event.type == SDL_QUIT )  {  done = 1;  }

				if ( event.type == SDL_KEYDOWN )
				{
					if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
				
					if ( event.key.keysym.sym == SDLK_y ) 
					{
						if (GameOver != 0)
						{
							for (int NewGameX = 0; NewGameX < 19; NewGameX++)
							{
								for(int NewGameY = 0; NewGameY < 19; NewGameY++)
								{
									Map[NewGameX][NewGameY] = 0;
								}
							}
							Turn = 0;
							GameOver = 0;
						}
					}
				}
				
				if (Connected == true)
				{
					if (GameOver == 0)
					{		
						// ALWAYS DRAW BOARD
						DrawIMG(board, 0, 0);

						DrawIMG(newgame, 510, 200);

						if (Turn == 0)
						{
							DrawIMG(blackturn, 464, 11);
						}
						if (Turn == 1)
						{
							DrawIMG(whiteturn, 464, 11);
						}


						if (FirstMsgSend == true)
						{
							if (Hosting == true)
							{
								SDLNet_TCP_Recv(TCPNewHost, RecvMessage, 20);
							}
							else
							{
								SDLNet_TCP_Recv(TCPClient, RecvMessage, 20);
							}

							if (strstr(RecvMessage, "White"))
							{
								Turn = 0;
							}
							if (strstr(RecvMessage, "Black"))
							{
								Turn = 1;
							}
						}


						SDL_GetMouseState(&MouseX, &MouseY);
						SDL_GetMouseState(&SelectX2, &SelectY2);

						SelectX = (SelectX2 / 24) * 24;
						SelectY = (SelectY2 / 24) * 24;

						if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
						{
							// New Game
							if ((MouseX >= 510) && (MouseX <= 586))
							{
								if ((MouseY >= 200) && (MouseY <= 212))
								{
									for (int NewGameX = 0; NewGameX < 19; NewGameX++)
									{
										for(int NewGameY = 0; NewGameY < 19; NewGameY++)
										{
											Map[NewGameX][NewGameY] = 0;
										}
									}
									GameOver = 0;
									Turn = 0;
								}
							}
							// Insert any other commands here, not added yet hehe :P
							SDL_GetMouseState(&SelectX2, &SelectY2);
						}

						DoMove();

						// Draw everything
						for (int I = 0; I < 19; I ++)
						{
							for (int J = 0; J < 19; J ++)
							{
								if (Map[J] == 1)
								{
									DrawIMG(white, J * 24, I * 24);
								}
								if (Map[J] == 2)
								{
									DrawIMG(black, J * 24, I * 24);
								}
							}
						}

						DrawIMG(selector, SelectX, SelectY);
					}
					else
					{
						DrawIMG(wonbg, 0, 0);

						if(GameOver == 1)
						{
							DrawIMG(whitewon, 232, 103);
						}
						if (GameOver == 2)
						{
							DrawIMG(blackwon, 232, 103);
						}
					}

					if (Hosting == true)
					{
						sendresult = SDLNet_TCP_Send(TCPNewHost, SendMessages, 21);
						
						//if (sendresult <= strlen(SendMessages) + 1)
						//{
						//	SDLNet_TCP_Close(TCPNewHost);
						//}
						
						strcpy(SendMessages, "  ");
						FirstMsgSend = true;
					}
					else
					{
						sendresult = SDLNet_TCP_Send(TCPClient, SendMessages, 21);

						//if (sendresult <= strlen(SendMessages) + 1)
						///{
						//	SDLNet_TCP_Close(TCPClient);
						//}

						strcpy(SendMessages, "  ");	
						FirstMsgSend = true;
					}
				}
				else
				{
					DrawIMG(connectbg, 0, 0);
					
					TCPNewHost = SDLNet_TCP_Accept(TCPHost);	

					if(!TCPNewHost)
					{
					
					}
					else
					{
						Connected = true;
					}
				}

			SDL_Flip(screen);
		}
	}

	SDLNet_TCP_Close(TCPHost);
	SDLNet_TCP_Close(TCPNewHost);
	SDLNet_TCP_Close(TCPClient);

	SDLNet_Quit();
	SDL_Quit();

	return 0;
}

http://sourceforge.net/projects/pingux/ <-- you know you wanna see my 2D Engine which supports DirectX and OpenGL or insert your renderer here :)
Advertisement
Okay. So after some playing around I noticed that it is the SDLNet_TCP_Recv function which is or really slow or I am using it wrong.
http://sourceforge.net/projects/pingux/ <-- you know you wanna see my 2D Engine which supports DirectX and OpenGL or insert your renderer here :)
I never used SDL_net before, but, if I am guessing right and SDLNet_TCP_Recv() is a wrapper for recv(), then thats your problem.

recv, if the socket is blocking, does not return until it receives some data, which may take a while to happen, so your app will get locked until there is inbound data.

There are 2 solutions to this either:

Create the socket as non blocking and then place the call to SDLNet_TCP_Recv() in a loop (the game main loop where you do the networking part would do), check the return value to see if there was any data retrieved and process it of so.

OR create a new thread whose only task is to run the recv loop and alert the main thread whenever there is new data, and pass it over.

Hope it helps.
Yes that helps me a bit :) Any info on how I could create that thread or how I do that multithreading stuff or how I can create the socket that it works teh way I want it to work ?

[Edited by - PinguinDude on November 23, 2004 11:48:09 AM]
http://sourceforge.net/projects/pingux/ <-- you know you wanna see my 2D Engine which supports DirectX and OpenGL or insert your renderer here :)
BUMPING :D
http://sourceforge.net/projects/pingux/ <-- you know you wanna see my 2D Engine which supports DirectX and OpenGL or insert your renderer here :)
The code for creating the thread in SDL works a little like:
SDL_Thread * thread;
thread = SDL_CreateThread(int (*fn)(void *), void *data);
//that's it
In CreateThread(), the first parameter is a function the thread will run in, like:
int Rec( void * unused )
{
while( game_running ) { /*receive msgs*/ } return 1;
}

so your call to create thread could look like:
thread = SDL_CreateThread( Rec, NULL );
Ok so what I have now is.

// threadsSDL_Thread *NetThread;int NetRecv(void *data){	if (FirstMsgSend == true)	{		if (Hosting == true)		{			if (SDLNet_TCP_Recv(TCPNewHost, RecvMessage, 21) == 0)			{			}		}		else		{			if (SDLNet_TCP_Recv(TCPClient, RecvMessage, 21) == 0)			{			}		}		if (strstr(RecvMessage, "White"))		{			Turn = 0;		}		if (strstr(RecvMessage, "Black"))		{			Turn = 1;		}	}	return 0;}and somewhere at the beginning of the main function	NetThread = SDL_CreateThread(NetRecv, NULL);

So how do I run it :o ?

I also checked the SDL Docs but I don't see any function for how to run that or anything. Actually I know what multithreading is supposed to do but I don't know how to use it :)
http://sourceforge.net/projects/pingux/ <-- you know you wanna see my 2D Engine which supports DirectX and OpenGL or insert your renderer here :)
PinguinDude,

I played around with a 2 player networked game earlier this year. It has a thread that listens for messages, and then acts on them.

[Sorry, source code has been removed. Needed the space]

The executable is not ready for networking, but the code can be compiled and I think it should work. You'll need to set the address of the opponent PC in the makeNetworkConnection function of links.cpp. The place has been commented so it won't compile without you changing it.

Note however, that there is a bug when playing networked whereby after a while the messages read are incorrect and the counters are placed in the wrong position on the screen. I think the message queue is overwriting some position variables, but I haven't been able to figure it out yet.

Hopefully is readable enough for you to work out how to get your game working.

The game was written using Dev-C++, and has the .dev project file. It is expecting the files to be under c:\Development\links.

Hope this is of some use to you.


To anyone else reading this, the source contains sprites, fonts and a particle system. All fairly basic, but if you want to use it go ahead. I don't guarantee the routines/classes, but I've used them in a couple of games already and haven't had any probs as yet.

[Edited by - BigBoy on December 18, 2004 2:01:10 AM]
Cheers,Jeroen
Come on, guys... don't post over here if you seriously want questions answered...
HxRender | Cornerstone SDL TutorialsCurrently picking on: Hedos, Programmer One
What are you on about, PnP Bios?
Cheers,Jeroen

This topic is closed to new replies.

Advertisement