Java 多人游戏中的线性脉冲和错误位置

Java 多人游戏中的线性脉冲和错误位置,java,android,libgdx,game-physics,kryonet,Java,Android,Libgdx,Game Physics,Kryonet,我正在用LibGDX创建一个游戏。起初,我在youtube上观看一个超级马里奥兄弟游戏的教程,但是,我改变了游戏,加入了我自己的角色和图形。我使用Kryonet作为在我的游戏中加入多人游戏功能的一种手段。这就是我遇到几个问题的地方 首先,我使用线性冲动进行移动,所以当我的角色上电时,会应用线性冲动,并赋予他们力量以更快地向前移动。这很好,直到你看到两个屏幕,角色A在一个玩家的屏幕上的位置不同,在另一个玩家的屏幕上的位置不同。我得到的两个角色的线性脉冲值也不同。我正常的右、左、上的动作也是用线性冲

我正在用LibGDX创建一个游戏。起初,我在youtube上观看一个超级马里奥兄弟游戏的教程,但是,我改变了游戏,加入了我自己的角色和图形。我使用Kryonet作为在我的游戏中加入多人游戏功能的一种手段。这就是我遇到几个问题的地方

首先,我使用线性冲动进行移动,所以当我的角色上电时,会应用线性冲动,并赋予他们力量以更快地向前移动。这很好,直到你看到两个屏幕,角色A在一个玩家的屏幕上的位置不同,在另一个玩家的屏幕上的位置不同。我得到的两个角色的线性脉冲值也不同。我正常的右、左、上的动作也是用线性冲动完成的。由于线性脉冲值的随机性,我得到了这个误差,我想说的是,就像滑动冰误差一样,推动冰块穿过表面并不总是保证相同的位置。下面是我的多人客户端类的一些代码

client.addListener(new ThreadedListener(new Listener() {
            // What to do with the packets.
            public void connected(Connection connection) {

            }

            public void received(Connection connection, Object object) {

                if (object instanceof MovementJump) {
                    MovementJump packet = (MovementJump) object;
                    
                    PlayScreen.player.b2body.applyLinearImpulse(new Vector2(0, 4f),
                            PlayScreen.player.b2body.getWorldCenter(), true);
                }

                if (object instanceof MovementRight) {
                    MovementRight packet = (MovementRight) object;
                    
                    PlayScreen.player.b2body.applyLinearImpulse(new Vector2(packet.impulse, 0),
                            PlayScreen.player.b2body.getWorldCenter(), true);
                }

                if (object instanceof MovementLeft) {
                    MovementLeft packet = (MovementLeft) object;
                    
                    PlayScreen.player.b2body.applyLinearImpulse(new Vector2(-packet.impulse, 0),
                            PlayScreen.player.b2body.getWorldCenter(), true);
                }

                if (object instanceof MovementP2Jump) {
                    MovementP2Jump packet = (MovementP2Jump) object;

                    PlayScreen.player2.b2body.applyLinearImpulse(new Vector2(0, 4f),
                            PlayScreen.player2.b2body.getWorldCenter(), true);
                }

                if (object instanceof MovementP2Right) {
                    MovementP2Right packet = (MovementP2Right) object;
                    
                    PlayScreen.player2.b2body.applyLinearImpulse(new Vector2(packet.impulse, 0),
                            PlayScreen.player2.b2body.getWorldCenter(), true);
                }

                if (object instanceof MovementP2Left) {
                    MovementP2Left packet = (MovementP2Left) object;
                    
                    PlayScreen.player2.b2body.applyLinearImpulse(new Vector2(-packet.impulse, 0),
                            PlayScreen.player2.b2body.getWorldCenter(), true);
                }
            }

        }));
    }


这是我的游戏屏幕上的一些代码

            if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)
                        && player.b2body.getLinearVelocity().x <= player.getMinSpeed()) {
                    
                    
                    MovementRight pos = new MovementRight();
                    MPClient.client.sendTCP(pos);
                }

                if (Gdx.input.isKeyPressed(Input.Keys.LEFT)
                        && player.b2body.getLinearVelocity().x >= -player.getMinSpeed()) {
                    
                    MovementLeft pos = new MovementLeft();
                    MPClient.client.sendTCP(pos);
                }

if(Gdx.input.isKeyPressed(input.Keys.RIGHT)
&&player.b2body.getLinearVelocity().x=-player.getMinSpeed()){
MovementLeft pos=新的MovementLeft();
MPClient.client.sendTCP(pos);
}

您应该发送每个字符的坐标,而不是发送力

为什么??如果应用一个脉冲并发送一个数据包通知其他客户机该脉冲,那么在ping延迟之后,将首先添加他们的脉冲,ping延迟永远不会为0。这意味着他们的脉搏将在之后被添加,因此他们的角色将永远在后面

我可以想出两种方法来实现这一点,但可能还有很多其他方法!第一种是客户端,第二种是服务器端,两者都有优点和缺点。就我个人而言,我推荐服务器端的结构,因为被黑客攻击的MP游戏确实会让玩家感到厌烦

客户端结构:

优点(较少的滞后,对滞后的玩家更灵敏的控制)缺点:(易于破解)

  • 无论何时更改客户角色的位置,都要向服务器发送带有当前坐标的
    PositionUpdatePacket
    。此数据包只需要包含(
    float x,float y,byte characterID
  • 服务器将数据包发送到所有其他连接的客户端
  • 每个客户端根据角色ID更新角色
  • 服务器端结构:

    优点(很难破解)缺点:(对于反应迟钝的玩家,控制的响应性较差)

  • 当播放机进行输入(例如向左移动)时,您将向服务器发送带有所需方向的
    MoveRequestPacket
    。当方向改变或播放器停止时,只需通过TCP发送一次
  • 服务器更新此播放机并向所需方向移动,即更新方法行为。这将应用脉冲。这里的优势是服务器可以进行各种点击框检查,并在玩家想要穿过墙壁时防止移动,以防止黑客攻击
  • 只要角色移动,服务器就会持续向所有连接的客户端(包括发送请求的客户端)发送一个
    PositionUpdatePacket
    ,其中包含当前角色位置
  • 每个客户端更新角色
  • 在这两种结构中,只要字符移动,就必须将
    PositionUpdatePacket
    连续发送到所有连接的客户端,这意味着此数据包将被大量发送。为了降低性能影响,您应该通过UDP发送,并且每秒仅发送x次。地雷船以20吨/秒的速度发送其位置

    如果发送
    PositionUpdatePacket
    的频率低于
    #update
    #step
    方法,则每个字符都会结巴和延迟。为了解决这个问题,可以使用插值来平滑运动


    我希望这有帮助。祝你好运

    您应该发送每个字符的坐标,而不是发送力

    为什么??如果应用一个脉冲并发送一个数据包通知其他客户机该脉冲,那么在ping延迟之后,将首先添加他们的脉冲,ping延迟永远不会为0。这意味着他们的脉搏将在之后被添加,因此他们的角色将永远在后面

    我可以想出两种方法来实现这一点,但可能还有很多其他方法!第一种是客户端,第二种是服务器端,两者都有优点和缺点。就我个人而言,我推荐服务器端的结构,因为被黑客攻击的MP游戏确实会让玩家感到厌烦

    客户端结构:

    优点(较少的滞后,对滞后的玩家更灵敏的控制)缺点:(易于破解)

  • 无论何时更改客户角色的位置,都要向服务器发送带有当前坐标的
    PositionUpdatePacket
    。此数据包只需要包含(
    float x,float y,byte characterID
  • 服务器将数据包发送到所有其他连接的客户端
  • 每个客户端根据角色ID更新角色
  • 服务器端结构:

    优点(很难破解)缺点:(对于反应迟钝的玩家,控制的响应性较差)

  • 当播放机进行输入(例如向左移动)时,您将向服务器发送带有所需方向的
    MoveRequestPacket
    。当方向改变或播放器停止时,只需通过TCP发送一次
  • 服务器更新此播放机并向所需方向移动,即更新方法行为。这将应用脉冲。这里的优势是服务器可以进行各种点击框检查,并在玩家想要穿过墙壁时防止移动,以防止黑客攻击
  • 服务器持续向所有连接的客户端发送
    PositionUpdatePacket
    ,包括