Frage

I'm trying to create a multiplayer game using websockets, node and JavaScript. What is the best approach for updating the client and keeping track of the clients co-ordinates on the server. My current method works, but it's very inefficient. (I can hear my laptop fan spinning up quite a bit lol!).

So what's happening:

The server is waiting for the client to send a message 'startmove', which also holds the direction. Once the server recieves this message it will start moving the player and broadcasting it's position. If the server recieved the message 'stopmoving', which also holds a direction... it stops moving in that direction.

My Question:

Are there any tweaks that I can use to increase the performance?

Server code snippet

var player =  {     x: 100, 
                    y: 200,
                 left: false,
                right: false,
                 down: false,
                   up: false
              }
var count = 0;

io.sockets.on('connection', function(client){
    ++count;
    io.sockets.emit('player_count', count);
    io.sockets.emit('connect', { "x" : player.x, "y" : player.y });

    client.on('disconnect', function () {  
      --count;
      io.sockets.emit('player_count', count);
    });


    client.on('startmove', function(d){   
      var direction = d.d;
      if (direction == 0) //Left
      {
        player.left = true;  
      } 
      else if (direction == 1) //Up
      {
        player.up = true;
      } 
      else if (direction == 2) //Right
      {
        player.right = true;     
      } 
      else if (direction == 3) //Down
      {
        player.down = true;       
      }
    });    

    client.on('stopmove', function(d){      
      var direction = d.d;
      if (direction == 0) //Left
      {
        player.left = false;  
      } 
      else if (direction == 1) //Up
      {
        player.up = false;
      } 
      else if (direction == 2) //Right
      {
        player.right = false;    
      } 
      else if (direction == 3) //Down
      {
        player.down = false;       
      }      
    });

    setInterval(loop, 15); // 33 milliseconds = ~ 30 frames per sec

    function loop() {
      if(player.left)
      {
        player.x--;
        io.sockets.emit('position', {"x" : player.x, "y" : player.y });                
      } 
      else if (player.right)
      {
        player.x++;
        io.sockets.emit('position', {"x" : player.x, "y" : player.y });                
      }

      if(player.up)
      {
        player.y--;
        io.sockets.emit('position', {"x" : player.x, "y" : player.y });                
      } 
      else if (player.down)
      {      
        player.y++;
        io.sockets.emit('position', {"x" : player.x, "y" : player.y });        
      }                  
    }    
});

Client code snippet

$(document).ready(function(){
  var canvas = document.getElementById('game'),
      ctx    = canvas.getContext('2d'),
      socket = io.connect('http://localhost'); 

  //Only start the game upon receiving the connect message
  socket.on('connect', function(data){      
    var y = data.y;
    var x = data.x;

        //Constants
    var GAME_WIDTH = $('canvas').width(),
        GAME_HEIGHT = $('canvas').height();

    var Player = function(x,y,w,h){
      this.x = x;
      this.y = y;
      this.w = w;
      this.h = h;
    };  

    var Game = new function(){

      var player   = new Player(x, y, 100, 100),   
          left     = false,
          right    = false,
          up       = false,
          down     = false;

      /* Gather player input */      
      $(document).keydown(function(event) 
      {
        if ( event.keyCode == 37) //Left
        { 
          socket.emit('startmove', {"d" : 0});
          return false;
        } 
        else if (event.keyCode == 38) //Up
        { 
          socket.emit('startmove', {"d" : 1});
          return false;
        } 
        else if (event.keyCode == 39) //Right
        {
          socket.emit('startmove', {"d" : 2});
          return false;
        } 
        else if (event.keyCode == 40) //Down
        {
          socket.emit('startmove', {"d" : 3});
          return false;
        }   
      });

      $(document).keyup(function(event)
      {
        if ( event.keyCode == 37)  //Left
        { 
          socket.emit('stopmove', {"d" : 0});
          return false;
        } 
        else if (event.keyCode == 38) //Up
        {
          socket.emit('stopmove', {"d" : 1});
          return false;
        } 
        else if (event.keyCode == 39) //Right
        {
          socket.emit('stopmove', {"d" : 2});
          return false;
        } 
        else if (event.keyCode == 40) //Down
        {
          socket.emit('stopmove', {"d" : 3});
          return false;
        }
      });

      socket.on('position', function(data){
        console.log("x: " + data.x + "\ny: " + data.y);
        player.x = data.x;
        player.y = data.y;
        clear();
        draw();
      });

      /* Clear the canvas */
      function clear(){
        ctx.clearRect(0,0,GAME_WIDTH, GAME_HEIGHT);
      }

      /* Draw to the canvas */
      function draw(){
        ctx.fillRect(player.x, player.y, player.w, player.h);
      }
    }();
  });
});

In the browser:

On screen

http://i.imgur.com/dkfSQ.png

War es hilfreich?

Lösung

Use timestamps to keep track of how long a player has been moving on the server.

This is how I'd do the server side:

var player =  {     x: 100, 
                    y: 200,
            direction: -1,
         moving_since: 0
              }
var count = 0;

io.sockets.on('connection', function(client){
    ++count;
    io.sockets.emit('player_count', count);
    io.sockets.emit('connect', { "x" : player.x, "y" : player.y });

    client.on('disconnect', function () {  
      --count;
      io.sockets.emit('player_count', count);
    });


    client.on('startmove', function(d){
      player.direction = d.d;
      player.moving_since = Date.now();   
    });    

    function adjustCoord(){
      player.direction = -1;
      var now = Date.now();
      if( player.direction == 0){
          player.x = player.x - ((now - player.moving_since) / 33);
      }
      else if( player.direction == 1){
          player.y = player.y + ((now - player.moving_since) / 33);
      }
      else if( player.direction == 2){
          player.x = player.x + ((now - player.moving_since) / 33);
      }
      else if( player.direction == 3){
          player.y = player.y - ((now - player.moving_since) / 33);
      }
    }

    client.on('stopmove', adjustCoord);

    setInterval(loop, 15); // 33 milliseconds = ~ 30 frames per sec

    function loop() {
      if ( player.direction != -1){
          var prevDir = player.direction;
          adjustCoord();
          player.direction = prevDir;
      }

      io.sockets.emit('position', {"x" : player.x, "y" : player.y });
    }    
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top