简单的游戏循环 Socket.io + Node.js + Express

Posted

技术标签:

【中文标题】简单的游戏循环 Socket.io + Node.js + Express【英文标题】:Simple Game Loop Socket.io + Node.js + Express 【发布时间】:2018-11-18 05:08:55 【问题描述】:

我试图用简单的物理原理制作一个游戏,你可以在其中跳来跳去,看看其他玩家使用 node.js、socket.io 和 express。但是,我试图让游戏循环运行,但无法将其绘制到浏览器。如果您可以帮助我使用这种格式,或者您可以为我的项目建议其他更有效的格式,请这样做。我看不出下面的代码有什么问题,谢谢!此外,我对 node.js 和 socket.io 还很陌生,所以请保持温和。谢谢!

game.js

var socket = io.connect('http://IPADRESS/');
var context, controller, rectangle, loop;
context = document.querySelector("canvas").getContext("2d");
canvsize = 
  height:720,
  width:1080

var fps = 60;
var FPS = 1000/fps;
var flooroffset = 64;
context.canvas.height = canvsize.height;
context.canvas.width = canvsize.width;
rectangle = 
  height:64,
  jumping:true,
  width:64,
  x:canvsize.width/2, // center of the canvas
  x_velocity:0,
  y:0,
  y_velocity:0
;

controller = 

  left:false,
  right:false,
  up:false,
  keyListener:function(event) 

    var key_state = (event.type == "keydown")?true:false;

    switch(event.keyCode) 

      case 37:// left key
        controller.left = key_state;
      break;
      case 65: //or key a
        controller.left = key_state;
      break;
      case 38:// space key
        controller.up = key_state;
      break;
      case 32: // or up key
       controller.up = key_state;
      break; 
      case 39:// right key
        controller.right = key_state;
      break;
      case 68:
        controller.right = key_state;
      break; // d key

    

  

;
window.addEventListener("keydown", controller.keyListener)
window.addEventListener("keyup", controller.keyListener);

setInterval(SendUpdate,FPS);
function SendUpdate()
  socket.emit("update",Ctl: controller,Rectangle: rectangle, ID:socket.id)

socket.on("UPDATE",draw)
function draw(data)  
  context.fillStyle = "#202020";
  context.fillRect(0, 0, canvsize.width, canvsize.height);// x, y, width, height
  context.fillStyle = "#ff0000";
  context.beginPath();
  for(var i = 0; i<data.length; i++)
    if (data[i].ID = socket.id)
      rectangle = data;
    
    context.rect(data[i].x, data[i].y, rectangle.width, rectangle.height);
  
  context.fill();
  context.strokeStyle = "#202830";
  context.lineWidth = 4;
  context.beginPath();
  context.moveTo(0, canvsize.height-flooroffset);
  context.lineTo(canvsize.width, canvsize.height-flooroffset);
  context.stroke();

server.js

const hostname = 'IPADRESS';
var canvsize = 
    width : 1080,
    height : 720

var fps = 60;
var FPS = 1000/fps;
var flooroffset = 64;
var spd = 2;
var jumpForce = 50;
var grav = 1.5;
var friction = 0.9;
var Players = [];
var express = require('express');
var app = express();
var server = app.listen(80);
app.use(express.static('public'));
app.set('port', process.env.HOST || hostname);
var socket = require('socket.io');
var io = socket(server);
console.log("Server working @ " + hostname);
io.sockets.on('connect',newConnection);
function newConnection(socket)
    Players[socket.id] = 
        height:64,
        jumping:true,
        width:64,
        x:canvsize.width/2, // center of the canvas
        x_velocity:0,
        y:0,
        y_velocity:0
    
    console.log("New Connection @ " + socket.id + "\nPlayers: " + Players[socket.id].x);
    socket.on('disconnect',disConnect);
    function disConnect()
        Players.splice(socket.id,1);
        console.log(socket.id + " Has Disconnected \nPlayers: " + Players[socket.id].x);
     
    socket.on("update",update);
    function update(data)
        var player = data;
        if (player.Ctl.up && player.Rectangle.jumping == false) 

            player.Rectangle.y_velocity -= jumpForce;
            player.Rectangle.jumping = true;

          

          if (player.Ctl.left) 

            player.Rectangle.x_velocity -= spd;

          

          if (player.Ctl.right) 

            player.Rectangle.x_velocity += spd;

          

          player.Rectangle.y_velocity += grav;// gravity
          player.Rectangle.x += player.Rectangle.x_velocity;
          player.Rectangle.y += player.Rectangle.y_velocity;
          player.Rectangle.x_velocity *= friction;// friction
          player.Rectangle.y_velocity *= friction;// friction

          // if player.Rectangle is falling below floor line
          if (player.Rectangle.y > canvsize.height - flooroffset - player.Rectangle.height) 

            player.Rectangle.jumping = false;
            player.Rectangle.y = canvsize.height - flooroffset - player.Rectangle.height;
            player.Rectangle.y_velocity = 0;

          

          // if player.Rectangle is going off the left of the screen
          if (player.Rectangle.x < -player.Rectangle.width) 

            player.Rectangle.x = canvsize.width;

           else if (player.Rectangle.x > canvsize.width) // if player.Rectangle goes past right boundary

            player.Rectangle.x = -player.Rectangle.width;
          
        Players[data.ID] = rectangle:player.Rectangle, ID:data.id;
    

setInterval(SEND,FPS);
function SEND()
    io.sockets.emit('UPDATE', Players);

【问题讨论】:

【参考方案1】:

您的服务器代码不正确,无法在端口 80 上侦听。 我在socket.io's doc找到了这段代码:

const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', () =>  /* … */ );
server.listen(3000);

据说

还要确保在server 上调用.listen,而不是app

【讨论】:

但是上面的代码在路由方面运行良好,唯一的问题是实际结果(在多个位置绘制多个玩家并更新它们) 所以你的客户端可以从 websocket 的服务器获取 msg?你的代码有什么问题? 身份证?我认为这是我在代码中遗漏的一个错误,我没有看到或其他什么地方。因为我是新人,所以我不确定我是否正常发送和接收,所以我在 *** 上发布了它 你能试试我的回答,看看是否一切正常吗?【参考方案2】:

是一个小错误,现在已修复。经过大量调试后,我终于修复了它,我做了很多编辑,所以我不打算解释它们,而是向你展示工作代码,如果你愿意的话,让你破译它。 (发送矩形引起了看不见的问题,更新不应该是原来的样子)

沃金 server.js:

const hostname = 'IPADRESS';
var canvsize = 
    width : 1080,
    height : 720

var ind;
var fps = 60;
var FPS = 1000/fps;
var flooroffset = 64;
var spd = 2;
var jumpForce = 50;
var grav = 1.5;
var friction = 0.9;
var Players = [];
const express = require('express');
const app = express();
const server = app.listen(80);
app.use(express.static('public'));
app.set('port', process.env.HOST || hostname);
const socket = require('socket.io');
const io = socket(server);
console.log("Server working @ " + hostname);
io.sockets.on('connect',newConnection);
function newConnection(socket)
    Players.push(
        ID:socket.id,
        frame:0,
        height:64,
        jumping:true,
        width:64,
        x:canvsize.width/2, // center of the canvas
        x_velocity:0,
        y:0,
        y_velocity:0);

    console.log("New Connection @ " + socket.id + "\nPlayers: " + JSON.stringify(Players));
    socket.on('disconnect',disConnect);
    function disConnect()
        for(var i = 0; i<Players.length; i++)
          if(Players[i].ID == socket.id)
            Players.splice(i,1);
            break;
          
        
        console.log(socket.id + " Has Disconnected \nPlayers: " + Players[socket.id].x);
     
    socket.on("update",update);
    function update(data)
          for(var i = 0; i<Players.length; i++)
            if(Players[i].ID == data.ID)
              ind = i;
              break;
            
          
          if (data.Ctl.up && Players[ind].jumping == false) 

            Players[ind].y_velocity -= jumpForce;
            Players[ind].jumping = true;

          

          if (data.Ctl.left) 

            Players[ind].x_velocity -= spd;

          

          if (data.Ctl.right) 

            Players[ind].x_velocity += spd;

          
          Players[ind].y_velocity += grav;// gravity
          Players[ind].x += Players[ind].x_velocity;
          Players[ind].y += Players[ind].y_velocity;
          Players[ind].x_velocity *= friction;// friction
          Players[ind].y_velocity *= friction;// friction

          // if Players[ind].Rectangle is falling below floor line
          if (Players[ind].y > canvsize.height - flooroffset - Players[ind].height) 

            Players[ind].jumping = false;
            Players[ind].y = canvsize.height - flooroffset - Players[ind].height;
            Players[ind].y_velocity = 0;

          

          // if Players[ind].Rectangle is going off the left of the screen
          if (Players[ind].x < -Players[ind].width) 

            Players[ind].x = canvsize.width;

           else if (Players[ind].x > canvsize.width) // if Players[ind].Rectangle goes past right boundary

            Players[ind].x = -Players[ind].width;
          
    

setInterval(SEND,FPS);
function SEND()
    io.sockets.emit('UPDATE', Players);

工作游戏.js:

var socket = io.connect('http://IPADRESS/');
var context, controller, rectangle, loop;
context = document.querySelector("canvas").getContext("2d");
canvsize = 
  height:720,
  width:1080

var fps = 60;
var FPS = 1000/fps;
var flooroffset = 64;
context.canvas.height = canvsize.height;
context.canvas.width = canvsize.width;

controller = 

  left:false,
  right:false,
  up:false,
  keyListener:function(event) 

    var key_state = (event.type == "keydown")?true:false;

    switch(event.keyCode) 

      case 37:// left key
        controller.left = key_state;
      break;
      case 65: //or key a
        controller.left = key_state;
      break;
      case 38:// space key
        controller.up = key_state;
      break;
      case 32: // or up key
       controller.up = key_state;
      break; 
      case 87: // or w key
        controller.up = key_state;
      break;
      case 39:// right key
        controller.right = key_state;
      break;
      case 68:
        controller.right = key_state;
      break; // d key

    

  

;
window.addEventListener("keydown", controller.keyListener)
window.addEventListener("keyup", controller.keyListener);

setInterval(SendUpdate,FPS);
function SendUpdate()
  socket.emit("update",Ctl: controller, ID:socket.id)

socket.on("UPDATE",draw)
function draw(data)
  context.clearRect(0,0,canvsize.width,canvsize.height);  
  context.fillStyle = "#202020";
  context.fillRect(0, 0, canvsize.width, canvsize.height);// x, y, width, height
  context.fillStyle = "#ff0000";
  for(var i = 0; i<data.length; i++)
    context.fillRect(data[i].x, data[i].y, data[i].width, data[i].height);
  
  context.strokeStyle = "#202830";
  context.lineWidth = 4;
  context.beginPath();
  context.moveTo(0, canvsize.height-flooroffset);
  context.lineTo(canvsize.width, canvsize.height-flooroffset);
  context.stroke();

【讨论】:

以上是关于简单的游戏循环 Socket.io + Node.js + Express的主要内容,如果未能解决你的问题,请参考以下文章

基于 socket.io 实现实时你画我猜游戏

Node JS、Socket.io、异步和阻塞事件循环

javascript Barebones游戏服务器与移动跟踪和使用Node和Socket.io的房间

带有 Node.js 和 socket.io 的 WebSockets

Phaser.js 中的 Node.js 和 Socket.io 未连接 socket.io/?EIO=3&transport=polling

在 node.js 上的 socket.io 上发送消息 client->server->client