Client + Server, "Same" code running at different speeds

Ok, so I have a little 2d networked java game I’m working on. Right now I’m trying to synchronize player-side movement “guessing” with server side movement. The short story is: My player-side movement calculation is somehow running slower than my server-side calculation… the clients constantly see themselves moving slower than they are actually moving. I have the server sync the absolute coordinates every 1 second, and at that time the player jumps ahead to their actual position.

Quick overview of my model:

  1. Player changes direction to “up”, sends this to server
  2. Server flags this player as moving “up”
  3. Server - In a section of code called every 10ms by a swing timer, update all player coordinates based on current direction and check to see if any player updated their direction. If so, tell all clients which player updated and what direction.
  4. Client gets player direction update, flags the player as moving “up”
  5. Client - In a section of code called every 10ms by a swing timer, update all player coordinates (locally) based on current direction and re-draw the screen.

Also, every 1 second, the coords of all players are sent to all players to make sure the client and server are in sync. The problem is, they never are.

#3 and #5 should be running just about the same time, the client fairly accurately guessing where they should be based on the last direction from the server.

So I guess now I need some code. Here is a section of my “Area” object which is handling movement and collision for all objects in that “area”. Both the client and server use this exact same code (they each create an instance of the Area)


public boolean updateMoves()
	{
		System.out.println(counter++);
		ArrayList<Entity> ents = entities;
		boolean change = false;
		for(int i = 0;i<ents.size();i++)
		{
			Entity ent = (Entity) ents.get(i);
			int dX = 0;
			int dY = 0;
			if(ent.moveCounter())
			{
				switch(ent.getMoveDirection())
				{
				case 0:
					break;
				case 1://U 
					dY=-2;
					break;
				case 2://UR
					dX=1;
					dY=-1;
					break;
				case 3://R
					dX=2;
					break;
				case 4://RD
					dX=1;
					dY=1;
					break;
				case 5://D
					dY=2;
					break;
				case 6://DL
					dX=-1;
					dY=1;
					break;
				case 7://L
					dX=-2;
					break;
				case 8://LU
					dX=-1;
					dY=-1;
					break;
				}
				if(dX!=0)
				{
					if(noCollide(ent,dX,0))
						getEntity(ent).setX(ent.getX()+dX);
				}
				if(dY!=0)
				{
					if(noCollide(ent,0,dY))
						getEntity(ent).setY(ent.getY()+dY);
				}
				if((dX!=0)||(dY!=0))
				{
					change = true;
				}
			}
		}
		return change;
	}

The “counter” variable is part of a debugging measure I took. Ideally, they should both be counting up at about the same speed. However, the client’s counter increases at about 50% of the server’s counter.

Also, the moveCounter thing… it increments a counter by 1, and if it’s greater than 10 it returns true and resets the counter. Was supposed to be my way of slowing down the player. I thought it might be part of the problem so right noiw it just returns “true” no matter what.

Ok, here’s where I set up the server timer to call that update code:


		ActionListener updateMoveListener = new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e) 
			{
				map.getArea(0, 0).updateMoves();
				try 
				{
					broadcastNewDirs();
				} catch (IOException e1) 
				{
					e1.printStackTrace();
				}
			}
		};
		Timer updateTimer = new Timer(10, updateMoveListener);
		updateTimer.start();
				

And the same thing on the client side:


		ActionListener updateMoveListener = new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e) 
			{
				if(map.getArea(0, 0).updateMoves())
				{
					iDrawListener.redraw();
				}
			}
		};
		Timer displayTimer = new Timer(10, updateMoveListener);
		displayTimer.start();

the iDrawListener.redraw just makes calls to my drawscreen routine telling it to re-paint the screen.
For the client side, I use the updateMoves code return value to make sure I only re-draw the screen when something has changed.

Can anyone make anything of this? I really don’t think it has anything to do with networking, it’s just two programs that should be running pretty much the same code at the same interval but one is going much faster than the other.

Thanks,
Jeremy