【问题标题】:Efficiently tracking coordinates on client and server有效地跟踪客户端和服务器上的坐标
【发布时间】:2011-09-09 20:33:31
【问题描述】:

我正在尝试使用 websockets、node 和 JavaScript 创建一个多人游戏。更新客户端和跟踪服务器上客户端坐标的最佳方法是什么。我目前的方法有效,但效率很低。 (我可以听到我的笔记本电脑风扇在旋转,哈哈!)。

那么发生了什么:

服务器正在等待客户端发送消息“startmove”,该消息也持有方向。一旦服务器收到此消息,它将开始移动播放器并广播其位置。如果服务器收到消息“停止移动”,它也包含一个方向......它会停止向那个方向移动。

我的问题:

我可以使用任何调整来提高性能吗?

服务器代码 sn-p

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 });        
      }                  
    }    
});

客户端代码sn-p

$(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);
      }
    }();
  });
});

在浏览器中:

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

【问题讨论】:

  • 您意识到startmovestopmove 不会自行修复延迟。所以每个客户看到的输入完全不同
  • @Raynos,我不确定你所说的修复自己是什么意思,但目前游戏几乎是单人游戏。我正在尝试找出一种有效更新我在屏幕上绘制的对象位置的方法,我会上传一张图片到我的问题中。

标签: javascript node.js client-server socket.io express


【解决方案1】:

使用时间戳来跟踪玩家在服务器上移动了多长时间。

这就是我在服务器端的做法:

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 });
    }    
});

【讨论】:

  • 看来你是对的,但显然 Date.now() 确实有效。 robertprice.co.uk/robblog/archive/2011/5/…
  • 我已经尝试过这段代码,并修复了一些小的语法问题。但是,它似乎并没有移动客户端对象。将方向更改为 player.direction,将日期更改为 new Date()。
  • 您是否检查过服务器是否真的在更新坐标并发送它们?尝试找出未更新的细分。
猜你喜欢
  • 1970-01-01
  • 2018-07-24
  • 2016-07-07
  • 1970-01-01
  • 2014-07-04
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
相关资源
最近更新 更多