简体   繁体   English

Socket.io工作异常

[英]Socket.io is working strange

I am using socket.io to create a game with some moving object. 我正在使用socket.io创建带有一些运动对象的游戏。 In my program i have this (very simplified) code: 在我的程序中,我有以下(非常简化的)代码:

socket.on('sync', function(newpos) {
    console.log(countcount + "{ x: " + object.x + " y: " + object.y + "}");
    countcount = 0;

    object.x = newpos.x;
    object.y = newpos.y;
});

function loop() {
    countcount++;
    console.log("loop")
    socket.emit('sync', SOME DATA);
    //A lot of game code
    ...
    //A lot of game code
    window.requestAnim(loop);
}

So i have the loop() where my game stuff is being executed, and i also have an event catcher that catches the 'sync' event sent from the server with the newpos of my object. 所以我有执行我的游戏东西的loop(),还有一个事件捕获器,可以捕获从服务器发送的“ sync”事件与对象的newpos。 But when i run the code my object is twitching. 但是当我运行代码时,我的对象在抽搐。 Not that very much but it's visible. 并不是很多,但是可见。 Here is what my console in Google Tools tells me: 这是我在Google工具中的控制台告诉我的内容:

在此处输入图片说明

If you look at 1) it tells me that the loop run, then my callback is called, then the loop run again, and the callback is called again, but then the loop run and the callback is called TWO times. 如果您看一下1)它告诉我循环运行,那么将调用我的回调,然后再次运行循环,然后再次调用该回调,但是随后循环运行并且该回调被称为两次。 How is that possible? 那怎么可能? I have emitted single event and then i got callback triggered two times? 我发出了单个事件,然后两次触发了回调?

If you look at 2) similar thing happens. 如果您查看2),也会发生类似的情况。 Why? 为什么?

Also would you kindly show me the info about how this event handlers work in javascript on the client side? 还请您向我展示有关此事件处理程序如何在客户端的javascript中工作的信息? Can this callback interfere my loop in the middle of its executing? 此回调能否在执行过程中干扰我的循环? Or this callbacks is stacked somewhere? 还是此回调堆积在某个地方?

Server-side code: 服务器端代码:

socket.on('sync', function(data){
    // Handle player commands
    if (data.left) {socket.speed.x += -1; }
    if (data.right) {socket.speed.x += 1; }
    if (data.up) {socket.speed.y += -1; }
    if (data.down) {socket.speed.y += 1; }

    socket.normSpeed = Controller.norm(socket.speed);//Controller.norm(socket.speed);
    socket.speed = Controller.mult(socket.normSpeed, 3);//Controller.mult(socket.normSpeed, 3);

    socket.pos.x += socket.speed.x;
    socket.pos.y += socket.speed.y;
    socket.emit('sync', socket.pos);

    socket.speed.x = 0;
    socket.speed.y = 0;
});

Your problem is the overall flow of your game. 您的问题是游戏的整体流程。 Request Animation Frame , is described as typically calling 60 times per second. 请求动画帧 ,通常被描述为每秒调用60次。 If you do the math (Divide 1000ms / 60frames/s), then you get approx 16 milliseconds per frame. 如果进行数学运算(除以1000ms / 60frames / s),则每帧可获得约16毫秒的时间。 While it may seem like a little bit of time, that little bit of time can have massive consequences. 尽管看起来似乎有点时间,但那一点点时间可能会带来巨大的后果。

Sockets.io, like any other Websocket connections tend to have a bit of uncertainty on when the packet of data would arrive. 像任何其他Websocket连接一样,Sockets.io在数据包何时到达方面也存在一些不确定性。 The packet might arrive earlier or it might arrive later depending on the network due to latency. 取决于延迟,数据包可能到达的更早,也可能到达的更晚。

The problem is, is that the "rate" at which packets arrive does not match your frame rate of ~60 frames per second. 问题是,数据包到达的“速率”与您每秒〜60帧的帧速率不匹配。 There are two scenarios to this as a result. 结果有两种情况。

In the first scenario, the packet arrives late. 在第一种情况下,数据包到达较晚。 The frame loop, continues anyway at 16ms per frame because it is independent of the packets. 帧循环以每帧16ms的速度继续进行,因为它与数据包无关。 By the time the packet arrived, the frame loop had already been called. 数据包到达时,已经调用了帧循环。 This is why "loop" was called twice above section 1 of your image. 这就是为什么在图片的第1部分上方两次调用“循环”的原因。

In the second scenario, the second packet arrives on time as the first packet arrives late. 在第二种情况下,第二个数据包按时到达,而第一个数据包则迟到。 The main loop is constantly being called every 16ms, independent of the fact whether the return packet has been recieved or not. 主循环每16毫秒不断调用一次,与是否已收到返回包无关。 So, it would ask the server for the return packet continuously (the emitting of sync client-side). 因此,它将连续不断地向服务器请求返回数据包(同步客户端的发出)。 Both packets would be sent, but both packets will be received by the client in the same "frame". 两个数据包都将被发送,但是客户端将在同一“帧”中接收这两个数据包。 This is why you see two of the "sync" calls. 这就是为什么您看到两个“同步”调用的原因。

An example is what happened right before section 1 of your image. 一个例子就是图像第1部分之前发生的情况。 The loop was called twice, but data was not received. 该循环被调用了两次,但是没有收到数据。 Where did that return data go? 那个返回数据去了哪里? It went to the next frame, and on and on until the double response at the middle of section 1. 它转到下一帧,一直持续到第1节中间的双重响应。

This is the flaw of your game. 这是您游戏的缺点。 Never let the client ask the server for data. 切勿让客户端向服务器询问数据。 Always have a timed loop both sides independent from each other. 双方始终要有一个定时循环。

However, this is not the reason why your game is jerky. 但是,这不是您的游戏变得生涩的原因。 The reason is because you directly move the object to a location as soon as the packet was received. 原因是因为您在收到数据包后立即将对象直接移动到某个位置。 The correct way to do this would be to interpolate the new position with the old one to smoothen out movement. 正确的方法是将新位置与旧位置进行插值 ,以平滑运动。

(I know this as I was a game developer. PS, if you are going to make an Agar.io implementation, check out https://github.com/huytd/agar.io-clone for inspiration. They use socket.io too) (我知道我是游戏开发者。PS,如果要进行Agar.io实现,请查看https://github.com/huytd/agar.io-clone以获得灵感。他们使用socket.io太)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM