Sorry, but the code was over 500 lines of code. I just didn't think it would be relevant to post that much code. But if you want me to, than here is my non-blocking code for my game:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
import java.nio.channels.*;
import java.nio.ByteBuffer;
public class MultiPong extends Applet implements Runnable {
Thread t;
int width;
int height;
int fps = 20;
Graphics screen;
Image backBuffer;
boolean host = false;
boolean looking = true;
// Fonts
Font font_big = new Font("Helvetica", Font.BOLD, 24);
Font font_plain = new Font("Helvetica", Font.PLAIN, 12);
// Host Button, Position
int hostButtonX = 0;
int hostButtonY = 0;
int hostButtonW = 166;
int hostButtonH = 35;
// Sockets
SocketChannel client;
ServerSocketChannel server;
int port = 4789;
String error = "";
String player_name = "";
int totalGames = 0;
int roomX = 10;
int roomY = 10;
int roomW = 0;
int roomH = 20;
String gameIPs[] = new String[100];
// Actual game information
int angle = 0;
int speed = 8;
int ballW = 10;
int ballH = 10;
double ballX = 0;
double ballY = 0;
int paddle1X = 0;
int paddle1Y = 0;
int paddle2X = 0;
int paddle2Y = 0;
int paddleW = 14;
int paddleH = 60;
int paddle1Diry = 0;
int paddle2Diry = 0;
int paddleSpeed = 4;
double rad = Math.PI/180;
int score1 = 0;
int score2 = 0;
String message = "";
String lastMessage = "";
boolean sendMsg = false;
// ByteBuffer for reading/writing
ByteBuffer bb;
public boolean mouseDown(Event e, int x, int y) {
if (looking) {
// Host Game
boolean collX = ((x >= hostButtonX) && (x <= hostButtonX+hostButtonW));
boolean collY = ((y >= hostButtonY) && (y <= hostButtonY+hostButtonH));
if (collX && collY) HostGame();
// Join Game
for (int i=0; i<totalGames; i++) {
int roomy = roomY+(22*i);
collX = ((x >= roomX) && (x <= roomX+roomW));
collY = ((y >= roomy) && (y <= roomy+roomH));
if (collX && collY) JoinGame(i);
}
}
return true;
}
public boolean keyDown(Event e, int key) {
if (looking) {
if (key == 8 && player_name.length() > 0) {
repaint();
player_name = player_name.substring(0, player_name.length()-1);
}
else if (player_name.length() < 50) {
if ( (key >= ((int)'a') && key <= ((int)'z')) || (key >= ((int)'A') && key <= ((int)'Z')) || key == ((int)'-') || key == ((int)'_')){
player_name += (char)key;
repaint();
}
}
}
else {
if (client != null) {
if (key == 8 && message.length() > 0) {
message = message.substring(0, message.length()-1);
}
else if (key == e.ENTER && message.length() > 0) {
sendMsg = true;
}
else {
if ( (key >= (int)'a' && key <= (int)'z') || (key >= (int)'A' && key <= (int)'Z') || (key >= (int)'1' && key <= (int)'9') || key == (int)' ' || key == (int)'-' || key == (int)'_' ) message += (char)key;
}
// Move server paddle
if (key == e.UP) {
if (host) {
paddle1Diry = -1;
}
else {
paddle2Diry = -1;
}
}
// Move client paddle
if (key == e.DOWN) {
if (host) {
paddle1Diry = 1;
}
else {
paddle2Diry = 1;
}
}
}
}
return true;
}
public boolean keyUp(Event e, int key) {
if (!looking && client != null) {
if (key == e.UP) {
if (host) {
paddle1Diry = 0;
}
else {
paddle2Diry = 0;
}
}
if (key == e.DOWN) {
if (host) {
paddle1Diry = 0;
}
else {
paddle2Diry = 0;
}
}
}
return true;
}
public void init() {
t = new Thread(this);
t.start();
width = size().width;
height = size().height;
hostButtonY = height-36;
roomW = width-21;
backBuffer = createImage(width, height);
screen = backBuffer.getGraphics();
}
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 update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
screen.setColor(Color.black);
screen.fillRect(0, 0, width, height);
if (looking) Lobby();
else {
if (error != "") {
screen.setColor(Color.white);
screen.drawString(error, 10, 15);
}
else {
PlayGame();
}
}
g.drawImage(backBuffer, 0, 0, this);
}
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 SetupGame() {
// Initialize some variables
angle = 180;
ballX = (width/2)-(ballW/2);
ballY = (height/2)-(ballH/2);
paddle1X = 10;
paddle1Y = (height/2)-(paddleH/2);
paddle2X = (width-paddleW)-10;
paddle2Y = (height/2)-(paddleH/2);
looking = false;
}
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 String UpdateGame() {
String gameLine = "";
try {
String encodedName = URLEncoder.encode(player_name);
URL url = new URL(getCodeBase(), "updateGame.php?host="+player_name);
URLConnection conn = url.openConnection();
BufferedReader url_in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
gameLine = url_in.readLine();
url_in.close();
} catch(IOException e){}
return gameLine;
}
public String EndGame() {
String gameLine = "";
try {
URL url = new URL(getCodeBase(), "endGame.php");
URLConnection conn = url.openConnection();
BufferedReader url_in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
gameLine = url_in.readLine();
url_in.close();
} catch(IOException e){}
return gameLine;
}
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.";
}
}
}
public void drawGameRoom(String line, int y) {
screen.setColor(new Color(0, 80, 0));
screen.fillRect(10, 10+(22*(y-1)), width-21, 20);
screen.setColor(Color.green);
screen.drawRect(10, 10+(22*(y-1)), width-21, 20);
// Format the line
int s1 = line.indexOf("+");
int s2 = line.indexOf("+", s1);
String host = line.substring(0, s1);
String serverIP = line.substring(s2+1);
gameIPs[y-1] = serverIP;
int strY = 25+(22*(y-1));
screen.setColor(Color.white);
screen.drawString("Host: "+host+"", 15, strY);
String join = "Join this game now.";
FontMetrics fm = screen.getFontMetrics(screen.getFont());
int strWidth = fm.stringWidth(join);
screen.drawString(join, (width-15)-strWidth, strY);
}
public void Lobby() {
screen.setColor(Color.white);
try {
URL url = new URL(getCodeBase(), "getGames.php");
URLConnection conn = url.openConnection();
BufferedReader url_in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String gameLine = url_in.readLine();
if (gameLine.equals("NO ROWS")) {
screen.drawString("No game sessions where found, but you can host your own game.", 10, 15);
}
else if (gameLine.equals("OKAY")) {
int i = 1;
totalGames = 0;
while((gameLine = url_in.readLine()) != null) {
drawGameRoom(gameLine, i++);
totalGames++;
}
} else {
screen.drawString("An unknown error occurred. Please try again later.", 10, 15);
}
url_in.close();
screen.setColor(new Color(0, 80, 0));
screen.fillRect(hostButtonX, hostButtonY, hostButtonW, hostButtonH);
screen.setColor(Color.green);
screen.drawRect(hostButtonX, hostButtonY, hostButtonW, hostButtonH);
screen.setFont(font_big);
screen.setColor(Color.white);
screen.drawString("Host a Game", 10, height-10);
screen.setFont(font_plain);
screen.drawString("Player Name: "+player_name, hostButtonX+hostButtonW+10, hostButtonY+(hostButtonH/2)+4);
} catch(IOException e){}
}
public void MoveGame() {
// Move the ball
double dx = speed*Math.cos(angle*rad);
double dy = speed*Math.sin(angle*rad);
ballX += dx;
ballY += dy;
// Bounce against the top edge
if (ballY <= 0) {
ballY = 0;
angle *= -1;
}
// Bounce against the bottom edge
if (ballY >= (height-ballH)) {
ballY = height-ballH;
angle *= -1;
}
// Score 1 for the client
if (ballX <= -ballW) {
score2++;
ResetBall(0);
}
// Score 1 for the server
if (ballX >= width) {
score1++;
ResetBall(180);
}
// Bounce against the server's paddle
boolean collX = ((ballX+ballW >= paddle1X) && (ballX <= paddle1X+paddleW));
boolean collY = ((ballY+ballH >= paddle1Y) && (ballY <= paddle1Y+paddleH));
if (collX && collY) {
double cangle = ((ballY+(ballH/2))-(paddle1Y+(paddleH/2)))*1.2;
angle = 0 + (int)cangle;
}
// Bounce against the client's paddle
collX = ((ballX+ballW >= paddle2X) && (ballX <= paddle2X+paddleW));
collY = ((ballY+ballH >= paddle2Y) && (ballY <= paddle2Y+paddleH));
if (collX && collY) {
double cangle = ((ballY+(ballH/2))-(paddle2Y+(paddleH/2)))*1.2;
angle = 180 - (int)cangle;
}
// Move the paddles
paddle1Y += paddleSpeed*paddle1Diry;
paddle2Y += paddleSpeed*paddle2Diry;
if (paddle1Y < 0) paddle1Y = 0;
if (paddle1Y > height-paddleH) paddle1Y = height-paddleH;
if (paddle2Y < 0) paddle2Y = 0;
if (paddle2Y > height-paddleH) paddle2Y = height-paddleH;
}
public void DrawGame() {
// Draw the game
String scoreString = score1 + " - " + score2;
FontMetrics fm = screen.getFontMetrics();
int strW = fm.stringWidth(scoreString);
screen.drawString(scoreString, (width/2)-(strW/2), 15);
screen.fillOval((int)ballX, (int)ballY, ballW, ballH);
screen.fillRect(paddle1X, paddle1Y, paddleW, paddleH);
screen.fillRect(paddle2X, paddle2Y, paddleW, paddleH);
screen.drawString(lastMessage, 5, height-6);
screen.drawString("Message: "+message, 5, height-21);
}
public void ResetBall(int newAngle) {
angle = newAngle;
ballX = (width/2)-(ballW/2);
ballY = (height/2)-(ballH/2);
}
public void PlayGame() {
screen.setColor(Color.white);
if (host) {
if (client == null) {
UpdateGame();
screen.drawString("Waiting for an opponent to join...", 10, 15);
}
else {
// Server
MoveGame();
DrawGame();
}
}
else {
// Client
MoveGame();
DrawGame();
}
}
}
559 Total Lines of Code
As you may notice, I've changed a few things aound (like temporarily removed the chat system) and made the paddles move smoothly by keyboard events. Hoping it would effect the out-of-sync problem but of course, it made no differance.
I think one problem is that I'm using Thread.sleep() to limit the frames, and well this works good on my slow PC, if I were to play it on a fast PC, it would go at light-speed.
I hope you guys can still help me out. I'd really appreciate it.
Oh and I've looked all over the net for tutorials on a Multiplayer Real Time Strategy game in Java, but I cannot find a single thing. Only tutorials on turn-based games, which the logic doesn't apply to RTS games.
Thank you,
Jamison