画布使用套接字服务器

时间:2016-10-10 04:06:06

标签: javascript node.js html5 canvas socket.io

我正在尝试如何使用socket.io来学习如何创建多人游戏。我目前有一台服务器存储所有玩家的位置,并向每个玩家发送他们的位置,然后将玩家发送给其他人的位置。据我所知,他知道这些数字是完美的。我已经交叉检查了每个位置,它们都像是应该的。出于某种原因,我注意到在将画面画到画布上时,我得到了一些奇怪的行为。以下是一些发生的事例。左上角是玩家的坐标,其下的数字是其他玩家的坐标: enter image description here 从这张图片中你可以看到我只能看到其中一个玩家。而玩家则在左下方。这本身就没问题。另一个玩家可能在遗嘱中远离屏幕。

enter image description here 在这张图片中你可以看到与第一张图片相同的东西,但还有另一个立方体。现在这没有任何意义。立方体应该是左下方的立方体,并且视图应该向下移动以调整立方体的y值。

enter image description here 现在这张照片是对我来说没有意义的地方。您只能看到最后一个多维数据集,并且当此多维数据集应该是最后一个多维数据集时,蓝色多维数据集仍然显示在最后一个多维数据集的上方和左侧。

这是我正在使用的代码。这可能对你没有任何意义,因为这是我的第一次尝试,需要重大改进。这是服务器的代码:



var express = require('express');
var app = express();
var serv = require('http').Server(app);
var speed = 10

app.get('/', function(req, res) {
  res.sendFile(__dirname + "/client/index.html");
});
app.use('client', express.static(__dirname + '/client'))
app.use(express.static(__dirname + '/client'));
serv.listen(2000);

characterList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", ",", ":", ";", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "[", "]", "(", ")", "<", ">", "|"]
var players = []
var connections = []
var io = require('socket.io')(serv, {});
io.sockets.on('connection', function(socket) {
  var address = socket.request.connection.remoteAddress;
  players.push({
    position: {
      x: Math.round(Math.random() * 1000),
      y: Math.round(Math.random() * 1000)
    }
  })
  connections.push(socket.id)
  socket.on('request', function(data) {
    length = data.length
    if (data.request == 'sessionID') {
      socket.emit('sendSessionID', {
        id: socket.id
      });
    }
    if (data.request == 'players') {
      var otherPlayers = [];
      for (var i = 0; i < players.length; i++) {
        if (connections[i] != data.id) {
          otherPlayers.push(players[i])
        } else {
          socket.emit('packet', {
            packetType: 'self',
            player: players[i]
          });
          console.log[i]
        }
      }
      socket.emit('sendPlayers', {
        Players: otherPlayers
      });
    }

  });

  socket.on('moveEvent', function(data) {
    var player = players[find(connections, data.id)]
    if (data.direction == "x+") {
      player.position.x = player.position.x + speed
    }
    if (data.direction == "y+") {
      player.position.y = player.position.y + speed
    }
    if (data.direction == "x-") {
      player.position.x = player.position.x - speed
    }
    if (data.direction == "y-") {
      player.position.y = player.position.y - speed
    }
  });

  function find(arrayName, string) {
    for (var i = 0; i < arrayName.length; i++) {
      if (string == arrayName[i]) {
        return i;
      }
    }
    return null;
  }

  function findKey(key) {
    for (var i = 0; i < arrayName.length; i++) {
      if (string == arrayName[i].ip) {
        return i;
      }
    }
    return null;
  }
  socket.on('disconnect', function() {
    var address = socket.request.connection.remoteAddress;
    players.splice(find(connections, this.id), 1)
    connections.splice(find(connections, this.id), 1)
  });
});
&#13;
&#13;
&#13;

以下是使用屏幕上的单个画布元素的客户端代码:

&#13;
&#13;
$(function() {
  var socket = io();
  var sesID = ""
  var players = []
  var player = {}
  var game = document.getElementById('game')
  var gamectx = game.getContext('2d');
  var GameY = 0;
  var GameX = 0;
  var w = false;
  var a = false;
  var s = false;
  var d = false;
  socket.emit('request', {
    request: "sessionID"
  });

  socket.on('sendSessionID', function(data) {
    sesID = data.id
  });

  socket.on('sendPlayers', function(data) {
    players = data.Players
  });
  socket.on('packet', function(data) {
    if (data.packetType == 'self') {
      GameX = data.player.position.x;
      GameY = data.player.position.y;
      player = data.player;
    }
  });
  setInterval(function() {
    console.log(players.length)
    if (w == true) {
      socket.emit('moveEvent', {
        direction: "y+",
        id: sesID
      })
    }
    if (a == true) {
      socket.emit('moveEvent', {
        direction: "x+",
        id: sesID
      })
    }
    if (s == true) {
      socket.emit('moveEvent', {
        direction: "y-",
        id: sesID
      })
    }
    if (d == true) {
      socket.emit('moveEvent', {
        direction: "x-",
        id: sesID
      })
    }
    gamectx.canvas.width = window.innerWidth;
    gamectx.canvas.height = window.innerHeight;
    gamectx.clearRect(0, 0, game.width, game.height);
    socket.emit('request', {
      request: "players",
      id: sesID
    });
    for (var i = 0; i < players.length; i++) {
      gamectx.fillStyle = "#ff0000"
      gamectx.fillRect(players[i].position.x + GameX, players[i].position.y + GameY, 100, 100)
      console.log('drew player at ', players[i].position.x + GameX, players[i].position.y + GameY, 100, 100)
    }
    gamectx.fillStyle = "#0000ff"
    gamectx.fillRect(window.innerWidth / 2 - 50, window.innerHeight / 2 - 50, 100, 100);
    gamectx.font = "48px sans-serif";
    gamectx.strokeText("x: " + GameX + ", y: " + GameY, 10, 50);
    var playersList = ""
    for (var i = 0; i < players.length; i++) {
      playersList += "x: " + players[i].position.x + ", y: " + players[i].position.y + ", "
    }
    gamectx.font = "30px sans-serif";
    gamectx.strokeText(playersList, 10, 100);
  }, 30);

  $(document).keydown(function(e) {
    if (e.which == 65) {
      a = true;
    }
    if (e.which == 68) {
      d = true;
    }
    if (e.which == 87) {
      w = true;
    }
    if (e.which == 83) {
      s = true
    }
  });
  $(document).keyup(function(e) {
    console.log(e.which)
    if (e.which == 65) {
      a = false;
    }
    if (e.which == 68) {
      d = false;
    }
    if (e.which == 87) {
      w = false;
    }
    if (e.which == 83) {
      s = false
    }
  });
});
&#13;
&#13;
&#13;

如果需要,这是html代码:

&#13;
&#13;
<html>
<div id="location-div">
</div>
<canvas id="game"></canvas>

<head>
  <script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
  <script src="js/jquery-3.1.1.min.js"></script>
  <script src="js/game.js"></script>
  <link rel="stylesheet" href="css/index.css">
</head>

<body>
</body>

</html>
&#13;
&#13;
&#13;

如果这对任何人都有意义,请提前感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

一切都是相对的。

在1D x&amp;画布中心cc = 100.

你画出gameX + x你在cc==100画自己的玩家所以如果自己是150并且玩家是200你在150+200=350画一个玩家但是自己被吸引到cc制作玩家{{1自我的像素权利。玩家应该是自我350-cc = 250右侧50像素。

修复画布中心(cc或原点)的绘制玩家加上自我和玩家之间的差异。

canvas.width/2 + 50

<强>顺便说一句

制作角色阵列

ctx.drawRect((canvas.width / 2) + (player.x - self.x), ...

下次需要这样的数组时,可以节省很多输入。

永远不要依赖数据连续性

仅发送移动并依赖每个客户端来维持正确的位置永远不会起作用,在一台机器上错过一个数据包而每个客户端都会有错误的视图。发送绝对位置(带时间戳)加上当前增量。不是字符串,而是编码成您可以发送的最小数据包。

如果下一个数据包迟到,请使用播放器的最后一个增量来更新位置。数据包到达时恢复到实际位置。如果您迟到丢失数据包,则允许交互回滚。即如果位置是从之前的三角洲猜到的,那么就不会杀死玩家,并且新的位置证明命中是一个未命中。

现在意味着什么?

请记住,光速是有限的,你在30ms(3/100秒)更新,这给了光(@ ~300,000,000mps)时间移动9,000,000m或9000km,足够时间移动到一个国家并返回,添加分组交换,客户端处理,响应传输延迟等,对于全世界的游戏来说,最小的ping时间是150ms +(或者只限游戏到低ping(本地))我们都有不同的天数,代码是多人游戏。