badboy24
badboy24

Reputation: 223

Reduce lags on a nodejs game

I have created a nodejs game. i have a setInterval function on the server which sends all the objects near the player. but it doesnt seem to be as smooth as i get when i run it locally. the data package has about 60 objects. here's the server code for sending objects and receiving them on the client. any way to compress the package or reduce the lags? pinka.herokuapp.com

server:

setInterval(function() {
    server.update();

    for(var key in sockets) {
        var socket = sockets[key];
        var player = server.players.filter(function(p) {
            return p.id == socket.id
        })[0];


        var package = [];
        var blobs = server.getNodesInRange(player.centerX, player.centerY);

        for(var i = 0; i < blobs.length; i++) {
            var b = blobs[i];
            package.push({
                x: b.x, 
                y: b.y,
                nick: b.nick,
                size: Math.sqrt(b._mass) * 10,
                hue: b.hue
            });
        };

        socket.emit("update blobs", package);
        socket.emit("leaders", server.getLeaders());

        if(player.blobs.length == 0) {
            socket.emit("dead");
            continue;
        }

        var translateX = player._centerX * player._drawZoom - player.screenWidth / 2;
        var translateY = player._centerY * player._drawZoom - player.screenHeight / 2;


        socket.emit("center and zoom", {
            centerX: translateX,
            centerY: translateY,
            zoom: player._drawZoom
        });
    }
}, 1000/60); 

client:

socket.on("update blobs", function(data) {
   blobs = data;
});

this is the whole communication part.

Upvotes: 0

Views: 670

Answers (1)

Enric A.
Enric A.

Reputation: 923

As Jonas W. said, the problem is in the server-client communication. To be efficient a realtime system with socket.io should be based on events and not in interval checks.

I'd suggest you to have something like this:

  • On the client, emit a 'user:move' event when the user moves. Prevent too many events to relief the server with unnecessary updates.
  • On the server, react to a specific 'player:move' event. If the events needs to be broadcasted to the other players, a filter with the ones that can actually "see" the action will avoid unnecessary information for the client too.

An example with pseudo code:

Client

let updating = false;
let timeout = 0;

// Assuming this function is triggered everytime the user moves (i.e. presses a key)
onUserMove (data) {
    if ('same press as before' && updating) {
        // ignore move if it's the same that has just been done    
        return;
    } else {
        socket.emit('user:move', data);

        // 'Block' the emit for same movement for 20ms
        updating = true;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            updating = false;
        }, 20);
    }
}

Server

socket.on('user:move', (data) => {
    const dataForTheUser = processingYouAreAlreadyDoing(data);
    socket.emit('data:for:user', dataForTheUser);

    // In case there's information to be sent to every user
    const dataToBroadcast = getDataToBroadcast(data);
    const usersToBroadcast = getCloseUsers(data);

    for (let user in usersToBroadcast) {
        user.socket.emit('whatever:event', dataToBroadcast);
    }
})

Upvotes: 2

Related Questions