Home > Back-end >  Server - Client communication causing Shapes to not Render on Canvas Node.js
Server - Client communication causing Shapes to not Render on Canvas Node.js

Time:05-01

I'm trying to create an online multiplayer game, but for some reason I can't get the players to be drawn on the screen. I think the problem is related to the server not correctly sending the data to the client, but I've included the whole (commented) code just in case that's not the case.

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>

Pretty straightforward, I define the canvas and the client-side script, 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);

This is the server code, and it handles creating the players and tracking movement. A bit sloppily written

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

The last for loop is the part that is not working. It is supposed to read the data map from the update event and render all the players at respective positions, but it is not.

I've tried debugging it. The move event has no problem, and neither does the canvas. If I hard code ctx.fillRect(x, y, size, size) into the program, it shows up. So I believe it has to do with the data variable not being sent properly. Am I missing something obvious?

UPDATE

So I realized I forgot to emit the update event from index.js and updated some of the script

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

It now emits the event. But when I try to receive it,

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

  }
});

It still doesnt render.

UPDATE 2

All the data now goes through, the only problem is the shapes not rendering. Something to do with canvas

CodePudding user response:

Turns out it was something obvious. The syntax for drawing on the canvas is beginPath not startPath

  • Related