服务器 - 导致形状无法在 Canvas Node.js 上呈现的客户端通信

Server - Client communication causing Shapes to not Render on Canvas Node.js

我正在尝试创建在线多人游戏,但出于某种原因,我无法在屏幕上绘制玩家。我认为问题与服务器没有正确地将数据发送到客户端有关,但我已经包含了整个(注释的)代码以防万一不是这种情况。

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Online Game</title>

    <link href="style.css" rel="stylesheet" type="text/css" />
  </head>

  <body>
      <canvas id="myCanvas" width="600" height="600"></canvas
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.sound.min.js"></script>

    <script src="/socket.io/socket.io.js"></script>
    <script src="script.js"></script>
  </body>
</html>

非常简单,我定义 canvas 和客户端脚本 script.js

index.js:

const express = require('express');
const app = express();
const http = require("http").createServer(app);
const io = require("socket.io")(http);

app.get('/',function(req, res) {
    res.sendFile(__dirname + '/index.html');
});

app.use('/',express.static(__dirname));

/* Server */
// Movement keys
const W = 87;
const A = 65;
const S = 83;
const D = 68;

// The data
let data = {players:{}} ;

let width = 600;
let height = 600;

io.on("connection", socket => {
  // New player connected
  console.log("player connected");

  // Create new player
  data.players[socket.id] = {
    pos:{x:300, y:300},
    speed:10,
    size:30,
    color:{r:255, g:0, b:0}
  };

console.log(data);

  socket.on("disconnect", () => {
    // Player  disconnected
    console.log("player disconnected");
    // Delete player
    delete data.players[socket.id];
  });

  // Movement event
  socket.on("move", key => {
    // Get the current player
    let player = data.players[socket.id];
    console.log(player.pos)
    // Check which movement key was pressed, and move accordingly
    if(key == W) {
        player.pos.y -= player.speed;
        console.log('up')
    }
    if(key == A) {
        player.pos.x -= player.speed;
        console.log('left')
    }
    if(key == S) {
        player.pos.y += player.speed;
        console.log('down')
    }
    if(key == D) {
        player.pos.x += player.speed;
        console.log('right')
    }

    // Check if player is touching the boundry, if so stop them from moving past it
    if(player.pos.x > width - player.size) {
        player.pos.x = width - player.size;
    }
    if(player.pos.x < 0) {
        player.pos.x = 0;
    }
    if(player.pos.y > height - player.size) {
        player.pos.y = height - player.size;
    }
    if(player.pos.y < 0) {
        player.pos.y = 0;
    }
  });
  
});


http.listen(4141);

这是服务器代码,它负责创建玩家和跟踪运动。写得有点草率

script.js:

const socket = io();

/* Setup */
let canvas = document.getElementById('myCanvas');
let ctx = canvas.getContext('2d');

/* Update & Events */
// Create the movement keys
const W = 87;
const A = 65;
const S = 83;
const D = 68;

// Get the update from the server
socket.on("update", data => {});

//receive input to move player
document.addEventListener('keydown', function (event) {
  if (event.key === 'w') {
    socket.emit("move", W);
  }
  if (event.key === 'a') {
    socket.emit("move", A);
  }
    if (event.key === 's') {
    socket.emit("move", S);
  }
  if (event.key === 'd') {
    socket.emit("move", D);
  }
});

function draw(){
    // Draw each player
  for(let playerID of Object.keys(data.players)) {
    // Get the the player from the player's id
    let player = data.players[playerID];

    // Draw the player
      ctx.startPath();
    ctx.arc(player.pos.x, player.pos.y, player.size, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();

  }
}
draw();

最后一个 for 循环是不起作用的部分。它应该从 update 事件中读取 data 地图并在各自的位置渲染所有玩家,但事实并非如此。

我试过调试它。移动事件没有问题,canvas也没有。如果我将 ctx.fillRect(x, y, size, size) 硬编码到程序中,它就会显示出来。所以我认为这与未正确发送 data 变量有关。我是否遗漏了一些明显的东西?

更新

所以我意识到我忘记从 index.js 发出更新事件并更新了一些脚本

index.js:

socket.on("move", key => {
    // Get the current player
    let player = data.players[socket.id];
    console.log(player.pos)
    // Check which movement key was pressed, and move accordingly
    if(key == W) {
        player.pos.y -= player.speed;
        console.log('up')
    }
    if(key == A) {
        player.pos.x -= player.speed;
        console.log('left')
    }
    if(key == S) {
        player.pos.y += player.speed;
        console.log('down')
    }
    if(key == D) {
        player.pos.x += player.speed;
        console.log('right')
    }

    // Check if player is touching the boundry, if so stop them from moving past it
    if(player.pos.x > width - player.size) {
        player.pos.x = width - player.size;
    }
    if(player.pos.x < 0) {
        player.pos.x = 0;
    }
    if(player.pos.y > height - player.size) {
        player.pos.y = height - player.size;
    }
    if(player.pos.y < 0) {
        player.pos.y = 0;
    }

      socket.emit('update', data);
  });

它现在发出事件。但是当我尝试接收它时,

script.js:

socket.on("update", data => {
    // Draw each player
  for(let playerID of Object.keys(data.players)) {
    // Get the the player from the player's id
    let player = data.players[playerID];

    // Draw the player
      ctx.startPath();
    ctx.arc(player.pos.x, player.pos.y, player.size, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();

  }
});

它仍然没有呈现。

更新 2

现在所有数据都通过了,唯一的问题是形状没有渲染。与 canvas

有关

事实证明这是显而易见的。在 canvas 上绘图的语法是 beginPath 而不是 startPath