在服务器和客户端上同步游戏逻辑

4
我正在使用Java创建一个简单的网络游戏,玩家可以使用键盘按键移动方块。该游戏将在本地服务器上运行,并且具有基本规则:
每个块将以1 FPS的速度自动移动,但是用户可以在这1秒间隔内发送多个移动命令,从而更新块的位置。
代码几乎完成了,但我在服务器和客户端之间同步问题上遇到了麻烦。以下是一些代码/描述,我需要更好地理解它:
基本类
class Server{

    ServerSocket server = new ServerSocket(port);

    while (listening) {
        Socket client = server.accept();
        new Thread(new ClientHandler(client)).start();
    }
}

class Game implements Runnable {

    public void run() { 
        while (! gameOver)
            tick();
    }   
}

现在的问题

class ClientHandler implements Runnable
{
    Game game;
    public ClientHandler(Socket client)
    {   
        this.client = client;

        //start game which runs at 1 FPS
        long FPS = 1000L;
        Timer timer = new Timer();
        timer.schedule(new Game(FPS), 0L, FPS);
    }

    public void run()
    {
        /** Game is already running, needs to:
        *
        * 1 - Take any GameInput object from the user and update the game
        * 2 - Send a GameState object to the user 
        * 3 - Client will receive it and render on screen,
        *     (hopefully in a synch state with the server)
        */ 

        while ( ! game.gameOver)
        {
            //ObjectInputStream ois = ...;

            // Line A
            GameInput command = ois.readObject();

            // Line B
            //GameState state = game.update(command);

            //ObjectOutputStream oos = ...;

           // Line C
            oos.writeObject(state);
        }
    }
}

我需要更好地理解如何处理Line ALine BLine C
更具体地说:
1- 以安全的方式更新游戏线程有什么好方法?
2- 如何处理多个命令?使用队列吗?
3- 如何确保客户端和服务器同步?
我是网络编程新手,感谢任何帮助!
2个回答

2
队列在编写任何类型的服务器时都是你的朋友。假设我们使用基本的客户端-服务器模型,那么游戏服务器的每个循环都应该执行以下操作:
  1. 从命令队列中获取所有命令。
  2. 处理这些命令。
  3. 向所有连接的客户端发送更新,客户端会将它们应用到自己的队列中,执行相同的操作。
同样,客户端也应该有来自服务器的命令队列,允许它们更新自己的状态。在合理的延迟下,服务器和客户端应该保持合理的同步。略微的不同步总是会发生的,而有不同的处理方法。(详见:客户端预测)。
对于游戏的每次循环,游戏应该基本上清空命令队列,并按照需要应用它们。

谢谢,现在队列更有意义了。 - Fernando

0
一种可能的网络同步解决方案:您可以首先使用NTP服务器将所有客户端和服务器同步到相同的日期/时间(如果延迟非常不同,或者如果存在很多抖动,则无法从服务器自己实现它)。然后按照执行时间将数据发送为每秒一帧,客户端等待帧中指定的时间并执行/更新命令。始终存在延迟(在局域网上可能小于几毫秒)。希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接