Networked Synchronized Game

Hey People! I've recently begun programming a game where there's a few tanks that rotate around, but this version is completely from scratch, I haven't used any code from the Game class (haven't really looked into it any way). I'm having a bit of trouble with the networking side of things. Now, i know what your thinking (and this may be true) I don't consider myself rushing into this not knowing anything about what i'm doing. Well, i DO have sort of an idea where i'm going, but that's where you come in, i need a push in the right direction. I understand lots about ServerSockets, Sockets, ObjectInput/ObjectOutput Streams, BufferedStreams, and all that jazz. But, i'm a little confused about the structure.

What i want to do is I want to make it so as the clients connect to my server, their little tank will appear and you can see yours as well as other people that are connected to my server. The problem is keeping them in sync with each other. I've got the moving mechanics all down and stuff i'm just having trouble with how i should transmit (efficiently) the coordinates of everyones tanks to everyone else!

Would a way to possibly do this be to as you move you use the writeObject() method to send your Rectangle object and then your server updates an ArrayList of tanks and sends it back...? something like this? i don't know.

Pseudo-Server Code:

--

publicclass TankServer{

publicstaticvoid main(String[] args){

ServerSocket server =new ServerSocket(PORTNUM);

World w =new World();

while(acceptingConnections)

w.add(server.accept());

}

}

-

-

-

Player Applet Client Class

import javax.swing.JApplet;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.AffineTransform;

import java.util.*;

import java.net.*;

import java.io.*;

publicclass Playerextends JAppletimplements Runnable{

Socket socket;

Soldier soldier;

private ArrayList players;

MediaTracker mt;

World world;

Image medic;

Thread runner;

Soldier currentDraw;

double angle = 0,xMove = 0, yMove = 0;

boolean leftPressed = false, downPressed = false, rightPressed = false, upPressed =false;

Image offscreen;

Graphics2D offGraph;

ArrayList bushes;

publicvoid init(){

bushes =new ArrayList();

bushes.add(new Bush(300, 300, 10, 10));

offscreen = createImage(500, 500);

offGraph = (Graphics2D)offscreen.getGraphics();

setSize(500, 500);

try{

socket =new Socket(hostname, 1800);

}catch(UnknownHostException e){}catch(IOException e){}

currentDraw =new Soldier(100, 100, 100, 100, 5, 0,new AffineTransform());

soldier =new Soldier(100, 100, 50, 50, 5, 0,new AffineTransform());

soldier.getAffine().setToTranslation(soldier.getX(), soldier.getY());

if(soldier.getframe() > 1){

for(int i = 1; i < soldier.getframe(); i++){

soldier.setAffine(soldier.getAffine().rotate(Math.toRadians(15), soldier.width / 2, soldier.height / 2));

}

}

angle = soldier.getframe() * 15 - 15;

medic = getImage(getCodeBase(),"medic.png");

medic = medic.getScaledInstance(soldier.width, soldier.height, Image.SCALE_SMOOTH);

mt =new MediaTracker(this);

mt.addImage(medic, 0);

try{

mt.waitForAll();

}catch(InterruptedException e){}

this.addKeyListener(new Listen());

new Listener();

runner =new Thread(this);

runner.start();

}

publicvoid setWorld(World w){

world = w;

}

publicclass Listenerextends Thread{

public Listener(){

this.start();

}

publicvoid run(){

while(1==1){

try{

ObjectInputStream ois =new ObjectInputStream(new BufferedInputStream(socket.getInputStream(), 1800));

currentDraw = (Soldier)ois.readObject();

}catch(IOException e){}catch(ClassNotFoundException e){}

}

}

}

/*public Player(AlienDaemon a, Socket socket) {

this.socket = socket;

players = new ArrayList();

soldier = new Soldier(100, 100, 50, 50, 5, 0);

}*/

public Rectangle getLocationn(){

return soldier.getSelf();

}

publicvoid updateLocations(ArrayList players){

this.players = players;

}

publicboolean boundsIntersect(double xMov,double yMov){

if(soldier.getX() + soldier.width + xMov > 500)

returntrue;

if(soldier.getX() + xMov < 0)

returntrue;

if(soldier.getY() + yMov < 0)

returntrue;

if(soldier.getY() + soldier.height + yMov > 500)

returntrue;

returnfalse;

}

publicboolean objectIntersect(double xMov,double yMov){

if(soldier.getX() + soldier.width + xMov > 500)

returntrue;

if(soldier.getX() + xMov < 0)

returntrue;

if(soldier.getY() + yMov < 0)

returntrue;

if(soldier.getY() + soldier.height + yMov > 500)

returntrue;

if(bushes.size() > 0){

for(int i = 0; i < bushes.size(); i++){

Bush temp = (Bush)bushes.get(i);

if(new Rectangle((int)soldier.getX() + (int)xMov, (int)soldier.getY() + (int)yMov, soldier.width, soldier.height).intersects(temp))

returntrue;

}

}

returnfalse;

}

publicvoid run(){

while(1 == 1){

if(rightPressed){

angle += 15;

soldier.setframe(soldier.getframe() + 1);

if(soldier.getframe() > 24)

soldier.setframe(1);

angle %= 360;

soldier.getAffine().rotate(Math.toRadians(15), soldier.width / 2, soldier.height / 2);

}

if(leftPressed){

angle -= 15;

soldier.setframe(soldier.getframe() - 1);

if(soldier.getframe() < 1)

soldier.setframe(24);

if(angle < 0)

angle = 350;

soldier.getAffine().rotate(Math.toRadians(-15), soldier.width / 2, soldier.height / 2);

}

if(upPressed){

if(!objectIntersect(soldier.move().getX(), soldier.move().getY())){

Point move = soldier.move();

soldier.setX(soldier.getX() + move.x);

soldier.setY(soldier.getY() + move.y);

soldier.getAffine().setToTranslation(soldier.getX(), soldier.getY());

soldier.getAffine().rotate(Math.toRadians(angle), soldier.width / 2, soldier.height / 2);

}

}

if(downPressed){

if(!objectIntersect(-soldier.move().getX(), -soldier.move().getY())){

double origSpeed = soldier.getSpeed();

soldier.setSpeed(origSpeed * .66);

Point move = soldier.move();

soldier.setSpeed(origSpeed);

soldier.setX(soldier.getX() - move.x);

soldier.setY(soldier.getY() - move.y);

soldier.getAffine().setToTranslation(soldier.getX(), soldier.getY());

soldier.getAffine().rotate(Math.toRadians(angle), soldier.width / 2, soldier.height / 2);

}

}

repaint();

wait(35);

}

}

publicvoid wait(int milliseconds){

try{

Thread.sleep(milliseconds);

}catch(InterruptedException e){}

}

publicclass Listenimplements KeyListener{

publicvoid keyPressed(KeyEvent e){

if(e.getKeyCode() == KeyEvent.VK_RIGHT){

rightPressed =true;

}

if(e.getKeyCode() == KeyEvent.VK_LEFT){

leftPressed =true;

}

if(e.getKeyCode() == KeyEvent.VK_UP){

upPressed =true;

}

if(e.getKeyCode() == KeyEvent.VK_DOWN){

downPressed =true;

}

}

publicvoid keyReleased(KeyEvent e){

if(e.getKeyCode() == KeyEvent.VK_RIGHT){

rightPressed =false;

}

if(e.getKeyCode() == KeyEvent.VK_LEFT){

leftPressed =false;

}

if(e.getKeyCode() == KeyEvent.VK_UP){

upPressed =false;

}

if(e.getKeyCode() == KeyEvent.VK_DOWN){

downPressed =false;

}

}

publicvoid keyTyped(KeyEvent e){}

}

publicvoid update(Graphics g){

paint(g);

}

public AffineTransform getAT(){

return soldier.getAffine();

}

publicvoid paint(Graphics g){

Graphics2D g2 = (Graphics2D)g;

offGraph.clearRect(0, 0, getWidth(), getHeight());

if(currentDraw.getAffine() !=null){

offGraph.drawImage(medic, currentDraw.getAffine(),null);

}

offGraph.drawImage(medic, soldier.getAffine(),null);

offGraph.drawString("" + angle, 20, 10);

offGraph.drawString("" + angle / 360, 20, 30);

offGraph.drawString("xMove: " + soldier.move().getX(), 20, 50);

offGraph.drawString("yMove: " + soldier.move().getY(), 20, 70);

offGraph.drawString("frame: " + soldier.getframe(), 20, 90);

for(int i = 0; i < bushes.size(); i++){

Bush temp = (Bush)bushes.get(i);

temp.drawBush(offGraph);

}

offGraph.drawRect((int)soldier.getX(), (int)soldier.getY(), soldier.width, soldier.height);

offGraph.drawLine((int)soldier.getX() +

soldier.width / 2, (int)soldier.getY() + soldier.height / 2,

(int)soldier.getX() + (int)soldier.move().getX() * 100,

(int)soldier.getY() + (int)soldier.move().getY() * 100);

g2.drawImage(offscreen, 0, 0, getWidth(), getHeight(),null);

}

}

As you can see by my client class

I AM EXTREMELY CONFUSED.

Any help would be EXTREMELY appreciated! thanks!

Message was edited by:

PaRlOaGn

Message was edited by:

PaRlOaGn

Message was edited by:

PaRlOaGn

Message was edited by:

PaRlOaGn

[18413 byte] By [PaRlOaGna] at [2007-11-27 8:12:12]
# 1

Well Arian,

First off, look into Thread Synchronization. It will be a big help to you.

Possibly invest in the book: "Java Threads" (in the O'Reilly series)

It will help you a lot!

Secondly, as far as the game itself goes. When I first started networking games, I thought about it wrong. Make things simple. Its very easy to think of networking as complicated and impossible to do but if you spend enough time thinking, it will become simple. Try to save effort by haaving the clients do most of the work for example: Instead of having the server store objects (tanks or something) have the server store the location of it and have the client add it to his playing feild. Every time the game is updated, have the client send his or her tanks location to the server so the other clients can get it.

Another idea is to have what I call (and other programmers im sure) "flags" in the server class. These flags are basically boolean variables. One might be: "playerOneChangedTankLocation" (I know thats long, but its easier to understand)

for example:

private boolean playerOneChangedTankLocation = false;

The client would constantly ask the server (in the main game loop)

if any new flags have been thrown. If the changed location flag had been thrown then maybe another method would be called to get the location of it and so on.

I hope this helps you!

No matter what, don't give up.

~Matt

OriginalSup3rmana at 2007-7-12 19:56:32 > top of Java-index,Other Topics,Java Game Development...