Javascript 多人游戏移动同步

Javascript 多人游戏移动同步,javascript,node.js,Javascript,Node.js,我正在做一个多人游戏,我在同步玩家方面遇到了问题 当玩家按下其中一个移动键(W、a、S、D)时,客户端发送一个关于按下按钮的数据包,服务器根据按下的键设置速度,并将新速度发送回所有附近的玩家 当玩家释放钥匙后,客户端发送一个数据包,服务器将玩家速度设置为0,0,并将位置和速度发送给附近的所有玩家 所以问题是当我松开钥匙时,大部分时间玩家都会跳回来 我怎样才能解决这个问题 我正在使用socket.io 客户端: socket.on('positionEntity', function (da

我正在做一个多人游戏,我在同步玩家方面遇到了问题

当玩家按下其中一个移动键(W、a、S、D)时,客户端发送一个关于按下按钮的数据包,服务器根据按下的键设置速度,并将新速度发送回所有附近的玩家

当玩家释放钥匙后,客户端发送一个数据包,服务器将玩家速度设置为0,0,并将位置和速度发送给附近的所有玩家

所以问题是当我松开钥匙时,大部分时间玩家都会跳回来

我怎样才能解决这个问题

我正在使用socket.io

客户端:

   socket.on('positionEntity', function (data) {
        console.log((data.x - entities[data.id].x)+" "+(data.y - entities[data.id].y));
        entities[data.id].setPosition(data);
    });

    $(document).keyup(function(e) {
        if (e.keyCode == 87) {
            keys.W = false;
            socket.emit("stopMove", {dir: 0, time: Date.now()});
        }

        if (e.keyCode == 65) {
            keys.A = false;
            socket.emit("stopMove", {dir: 1, time: Date.now()});
        }

        if (e.keyCode == 83) {
            keys.S = false;
            socket.emit("stopMove", {dir: 2, time: Date.now()});
        }

        if (e.keyCode == 68) {
            keys.D = false;
            socket.emit("stopMove", {dir: 3, time: Date.now()});
        }
    });

    $(document).keydown(function(e) {
        if (e.keyCode == 87 && !keys.W) {
            keys.W = true;
            socket.emit("startMove", {dir: 0, time: Date.now()});
        }

        if (e.keyCode == 65 && !keys.A) {
            keys.A = true;
            socket.emit("startMove", {dir: 1, time: Date.now()});
        }

        if (e.keyCode == 83 && !keys.S) {
            keys.S = true;
            socket.emit("startMove", {dir: 2, time: Date.now()});
        }

        if (e.keyCode == 68 && !keys.D) {
            keys.D = true;
            socket.emit("startMove", {dir: 3, time: Date.now()});
        }
    });
服务器端:

socket.on('startMove', function(data) {
    if (data.dir == 0) socket.player.setMotionY(-5);
    if (data.dir == 1) socket.player.setMotionX(-5);    
    if (data.dir == 2) socket.player.setMotionY(5);
    if (data.dir == 3) socket.player.setMotionX(5);

    io.sockets.emit("positionEntity", socket.player.serializePosition());
});

socket.on('stopMove', function(dir) {
    socket.player.setMotionX(0);
    socket.player.setMotionY(0);

    io.sockets.emit("positionEntity", socket.player.serializePosition());
});

这是一项非常复杂的任务,您正在处理,而我是作为宠物项目的一部分完成的;)

您正在开发客户机-服务器体系结构游戏,因此服务器是游戏逻辑和决策的最终权威。由于延迟,您当前处理渲染的方式将使速度和方向发生明显的突然变化(正如您所注意到的!)

诀窍是缓冲远程玩家的移动信息,以便始终以稍微延迟的方式渲染玩家。我在我的项目中保持了原始状态,只使用位置数据,而不使用加速度或速度。例如,当玩家A在他的机器上移动时,不会立即发送一个命令来接收确认,他移动,在我的网络发送循环的下一个滴答声(每秒10滴答声)中,他的位置被发送到服务器,服务器用这个新位置更新附近的所有客户端。这些客户端为每个“远程”播放器都有一个缓冲区,在呈现更新之前将每个位置存储一段时间(100毫秒)。通过这种方式,客户端渲染稍微延迟,但我可以在每个位置坐标之间进行插值(平滑精灵/模型的过渡),以实现速度和加速度错觉下的平滑运动

客户端代码的基本插值函数。此系统最多只为每个远程播放机排队两次更新,其中更新数组中的索引0是两次更新中较早的一次。因此,索引0可能是远程播放机位置0ms,索引1是远程播放机位置100ms

interpolate: function() {
  var timeDifference = new Date().getTime() - this.serverUpdates[1].time;
  // Percentage of time passed since update was received (I use 100ms gaps)
  var interPercent = (timeDifference) / 100;

  // Latest updates (index 1 is the newest state)
  var s1 = this.serverUpdates[0],
    s2 = this.serverUpdates[1];

  // Need to lerp between values provided in latest update and older one
  var p = (new Vector3(s2.position)).subtract(new Vector3(s1.position));
  p = p.timesScalar(interPercent);

  // New position is the older lerped toward newer position where lerp 
  //percentage is the time passed 
  this.position = new Vector3(s1.position).add(p);

  // Now update rotation in a smooth manner
  var rotationDifference = (s2.rotation - s1.rotation);
  if (rotationDifference && rotationDifference != 0) {
    this.rotation = s1.rotation + (rotationDifference * interPercent);
  }
},
在这段代码中,我收到的更新间隔约为100ms,因此在时间0时,位置为s1,时间100ms时,位置为s2。因此,如果在我们收到s2后50毫秒已经过去,那么实体在两个位置之间为50%。这对我的需要来说很好,但在其他类型的游戏中可能不起作用,或者可能需要调整

这些资源是解释网络游戏和处理延迟的一个很好的开始,您会惊讶于在远程客户端中实现插值和外推对游戏平滑度的影响


“我怎样才能解决这个问题?”。。。如果没有任何代码,我们如何帮助您呢?对不起,是真的,我要编辑它。作为建议,在jQuery事件处理程序中使用
e.which
——jQuery在将关键代码检索到
e.which
中时规范浏览器不一致。不,玩家不会因为延迟而跳回。客户端移动并将包发送到服务器,100毫秒后,服务器接收此包,然后移动播放器(在服务器端)。因此,客户端的播放器比服务器快100毫秒。当用户停止时,就停在那里。100毫秒后,服务器开始停止。你可以使用两台电脑运行的mmorpg游戏,观看玩家移动。我必须为一个小游戏制作类似的东西,我正在编写:)谢谢!我会尝试一下并给你们反馈(如果效果好的话,我可能会写一篇关于这个的博文)@loicconen你们的实验进行得怎么样?我希望您可以在博客上介绍您的项目,以及如何使其在客户机-服务器体系结构中工作。让玩家顺利移动和互动确实是一个挑战,这不是一个坏主意。也许我应该做些类似的事情。这是一个有趣的话题。