Multiplayer RTS Tutorial

Hello all,

I’m new here. Looks like this is a really good forum to be hanging out at. Anyway, on to my question…
I’m wondering if any of you guys know where I could find a tutorial on how to create a Multiplayer RTS (Real Time Strategy) game in Java. It needs to be played over the Internet, and preferably using Sockets (which I have some expirience with, but I tried to make an RTS but I had problems: lag and out-of-sync problems).

All I really need is how to make a Pong game for example. Once I know how to get everything working without lag and synchronization problems, I can make my own multiplayer game with the network code provided or described in the tutorial.

I’ve scoured the web for tutorials on this subject, but can’t find a single thing on this specific topic. I’ve only found tutorials on turn-based games (which is how I learn how to use Sockets in Java), and I tried changing the code into a Multiplayer Pong game, but one problem I had was lag then I fixed that and had a problem with synchronization (both the client and server, or host, were both seeing completely differant things).

Your support is greatly appreciated,
Jamison

for start, I apologize for not being able to help you directly
I don’t think pong game is quite comparable with RTS. Pong is very simple and predictible, RTSes are much, much more… Don’t know why you had sync problems, maybe you shouldn’t give up and first finish that. For RTS you need a real server, not just something that responds when message is sent to them like in most tutorials. I suggest you first try to make smaller real time multiplayer game where you have basic elements of RTSes, like sync moving of objects. I’m now working on a extreamly simple soccer game with same reason as you, to learn networking and move on to bigger projects. You’re right about lack of tutorials, couldn’t find any myself so I’m learning by myself, which is very slow and I spam forum :wink: Hope someone will be able to help you more…

Pong is an RTS. An RTS game is anything that allows both players to move and react simultaneously (at the same time) without waiting for the other player to first make his/her move. Well, I guess for pong, the S should be removed from RTS. Since Pong isn’t really a strategy game, so it’s really a real-time game than.

I think I can pin point the problem I had. I think it was because I used Thread.sleep() in order to limit the frames per second. But I can’t find any code on how to make an FPS limiter that uses the current time.

I feel like I’ve talked to you before:wink:

I haven’t quite looked through that entire code posting in the other thread. perhaps you could strip it down to just the networking so i can understand what you are doing.

how have you structured your network? Does the server constantly send messages to the client? or is the client querying the server? I see you made the switch to NIO… but still have lag troubles? maybe we should troubleshoot the structure of the networking…

pong… real time arcade I would say
again sorry for straying from your desired path of finding RTS tutorial…

So you’re using thread.sleep(). You need to calculate how much ms you need to sleep. Before game update and render (and anything else) at the start, you get the time. After all of that you again get the time and you sleep(desired_sleep_time - (after_time - before_time)). So if you want to sleep 25 ms every time and your updates and render lasted 5 ms, you’ll sleep 20 ms. You have a really detailed explaination and much more complicated formula in “Killer Game Programming”, it’s free, find it.

Haha, yup we have. Anywho, it’s kind of hard to strip it down to only my network code as it’s kind of scattered around. But I’ll try. Oh and both the client and the server (host) are always sending and recieving bytes. Every frame update (33 seconds).

Okay, here’s a stripped down version of just my network code:

	.....

	// Sockets
	SocketChannel client;
	ServerSocketChannel server;

	int port = 4789;

	.....

	// ByteBuffer for reading/writing
	ByteBuffer bb;

	.....

	public void run() {
		while (true) {
			// Waiting for an opponent
			if (client == null && server != null && host && !looking) {
				try {
					if (server.socket().isBound()) {
						client = server.accept();
					}

					if (client != null) {
						client.configureBlocking(false);
						client.socket().setTcpNoDelay(false);

						System.out.println("A client has connected.");
					}
				} catch(IOException e){}
			}

			// Server
			else if (client != null && host && !looking) {
				try {
					// Write
					bb = ByteBuffer.allocate(20);
					bb.putInt(0, paddle1Diry);
					bb.putDouble(4, ballX);
					bb.putDouble(12, ballY);
					client.write(bb);

					// Read
					bb = ByteBuffer.allocate(4);
					client.read(bb);
					paddle2Diry = bb.getInt(0);
				} catch(IOException e) {}
			}

			// Client
			else if (client != null && !looking) {
				try {
					// Write
					bb = ByteBuffer.allocate(4);
					bb.putInt(0, paddle2Diry);
					client.write(bb);

					// Read
					bb = ByteBuffer.allocate(20);
					client.read(bb);
					paddle1Diry = bb.getInt(0);
					ballX = bb.getDouble(4);
					ballY = bb.getDouble(12);
				} catch(IOException e){}
			}

			// Refresh and sleep
			try {
				repaint();
				t.sleep(1000/fps);
			} catch(InterruptedException e){}
		}
	}

	.....

	public void stop() {
		t.stop();
		try {
			/*if (out != null) {
				out.close();
			}
			if (in != null) {
				in.close();
			}*/
			if (client != null) {
				client.close();
			}
			if (server != null) {
				server.close();

				String gameLine = EndGame();
				if (gameLine == "CANT_DELETE") {
					error = "Unable to delete game session.";
				}
			}
			System.out.println("All open streams have been closed.");
		} catch(IOException e){}
	}

	.....

	public void JoinGame(int id) {
		if (player_name.length() > 0) {
			try {
				client = SocketChannel.open(new InetSocketAddress(gameIPs[id], port));
				client.configureBlocking(false);
				client.socket().setTcpNoDelay(false);

				SetupGame();

				System.out.println("Joined game session "+(id+1)+".");
			} catch(IOException e) {
				error = "Unable to join game session "+(id+1)+".";
				System.out.println(error);
				System.out.println(e);
			}
			repaint();
		}
	}

	.....

	public void HostGame() {
		if (player_name.length() > 0) {
			host = true;
			looking = false;
			repaint();

			// Create the server
			try {
				String gameLine = UpdateGame();
				if (gameLine.equals("OKAY")) {
					server = ServerSocketChannel.open();
					server.configureBlocking(false);
					server.socket().bind(new InetSocketAddress(port));

					SetupGame();

					System.out.println("Hosting game on port "+port+" was successful.");
				}
				else if (gameLine.equals("CANT_CREATE")) {
					error = "Unable to create game session. Please try again later.";
				}
				else if (gameLine.equals("CANT_UPDATE")) {
					error = "Unable to update game session. Please try again later.";
				} else {
					error = "An unknown error has occurred. Please try again later.";
				}
			} catch(IOException e) {
				error = "Unable to host game. Port "+port+" may already be in use.";
			}
		}
	}

	.....

It’s okay. As long as I can atleast get this multiplayer pong game working, than I can make other real-time arcade/strategy games.

I’ve seen and read some of that “Killer Game Programming” book, but I didn’t know it had anything on timed steps. I’ll have to look and read through it more thoroughly. Thanks!

I also feel like I talked with you before: http://www.gamedev.net/community/forums/topic.asp?topic_id=381609 , good to see you made it in these forums :wink:

As for your pong game I haven’t anything else to comment than I did on your post at gamedev, however for a RTS game this might be of interest for you: http://www.btinternet.com/~duncan.jauncey/old/javagame/

They provide full source for the game as well as a small description on how the different parts are designed.

Also, again the article at gamasutra ( http://www.gamasutra.com/features/20010322/terrano_01.htm ) is an excelent read on this subject.

Thijs

Thanks very much, thijs! I almost forgot about those links you gave me. I will certainly download the source for that game and take a look at that article on AOE’s network code. Hopefully that’l help me.

Oh yeah, thijs, that YARTS game doesn’t have multiplayer capability. I can create an RTS, so I’m sure that game won’t fit my need since I just need to know how to code the network end.

Argh, I’ve even changed my code (well, a differant test) to use UDP sockets and I’m still having the same problems! thijs, on GameDev.net, you said something about predicting the next move of the paddles and ball. How am I supposed to predict movements?

I do believe YARTS has networking support (maybe that demo applet doesn’t):
http://www.btinternet.com/~duncan.jauncey/old/javagame/arch_network.html

Contrary to popular believe, UDP ain’t faster than TCP (for the transmission time). It has some properties that can be taken advantage of in some games. ( see http://www.java-gaming.org/forums/index.php?topic=608.0 and http://www.java-gaming.org/forums/index.php?topic=12452.0 )

Now you use non-blocking sockets your game is out-of-sync because it goes on. Updates from the other player are always received later, no way around that (network latency). It was perfectly synchronized when you used a blocking socket, because the game wouldn’t proceed with the gameloop until it got another network update… but that means the game update rate is determined by the network lag and you really don’t want that for a networked game :wink:

Predicting motion for the ball is straightforward assuming its just a linear motion (y = ax + c). Based on the previous location you can calculate the pos for this step. For the bats it would be a little more difficult, as their movement is very unpredictable. Try changing the network updates / sec to see what gives a high enough resolution to capture their movement. Then use a technique called linear interpolation (lerp) to smooth their motion between these points (or else you’d see the game run at 30fps fx but the bats run at 10fps assuming 10 network updates / sec).

I can’t really tell you all aspects invloved in create a networked game in a forum post, try browsing this forum and see if you see relevant topics, browse gamasutra (they have some nice articles on this), and do a google on “dead reckoning multiplayer” and “interpolation multiplayer”.

Thijs

Thanks again for the info, thijs. I’ll try googling for those topics.

And by the way, I tried to download the JAR of YARTS and it still doesn’t have network play. They must’ve forgotten that?

I downloaded the source for YARTS and it clearly has some classes for networking support, dunno if it’s enabled in the compiled version…
http://www.btinternet.com/~duncan.jauncey/old/javagame/files/YARTS-sourcecode.zip

Oh yeah. I see now. It does have networking code in the source but they must not have enabled it in the last release.

Okay, yes, old topic - I know… But I have FINALLY fixed my lag and out-of-synchronization problem! What I did was used blocking Sockets, and instead of using a PrintWriter that flushed the output stream every print command, I ONLY flushed it after ALL the print commands have been done. Before, I was using multiple println(String x) commands to send data to the client/server, but since it was flushing the data after every command, it waited for each command. But flushing only once, made it wait only once!

Well anyway, I have to go to work now. That’s why I haven’t been on the forums much lately; too much work and school. See yall later!

There are 2 nice books for Java Game Programming on Amazon. They can give you a lot of information. Then you need to work yourself up to the ability to make a RTS. RTS is like Pong, players are controlling entities in realtime. But an RTS has a shitload more stuff like AI, Pathfinding, complicated multiplayer communication, etc. I would not say if you can make Pong, you can make Starcraft or something like that. But the basics are similar. Process player input, move entities, process events and collisions, display graphics, play sound, maybe send network data. The RTS has just a little more other stuff.

-JAW

If you read my last post, you would have known that I have already fixed my problem. And btw, a java game programming book wouldn’t do much - I already know how to program games in Java. I’ve been programming games for six years, Java for about a year and a half.

I read some articles about network multiplayer in the book Game Programming Gems 3. There are a lot of other interesting articles. If you are interested, maybe have a look into that book. But I cannot say if it can teach you something you dont yet know.

-JAW

I’ve had no luck trying to find that book. Could you please provide a link?