首页 > 解决方案 > Java Script & Socket IO:无法从客户端向服务器发出值来操作服务器上的变量

问题描述

我正在制作简单的多人贪吃蛇游戏来掌握如何使用 socket.io,而在我的一生中,我无法让客户端向服务器发出值。在客户端的my 下方function advanceSnake(),当蛇在坐标内撞击时,它应该发出一个名为 'tf' 的对象,其值为 'true': socket.emit('makeFood', {tf: true})。在我的服务器端我有它,所以当它接收到它应该设置的数据 var food = true但它不会改变

io.sockets.on('makeFood', function(data) {
    food = data.tf;
});

我定期运行一个函数

function main() {
    setTimeout(function onTick() {
        if (food == true) {
            createFood()};
            main();
    }, 500);
}

看看是否var food == true但它从不调用该函数createFood()

我不相信在服务器端var food设置true。任何帮助将不胜感激。谢谢!

客户:

////// CLIENT //////
var socket = io.connect('http://localhost:8000');

/** CONSTANTS **/
const CANVAS_BORDER_COLOR = 'black';
const CANVAS_BACKGROUND_COLOR = 'white';
const SNAKE_COLOR = 'lightgreen';
const SNAKE_BORDER_COLOR = 'darkgreen';

var myName = prompt("Name","test");
if(myName !== undefined){
  socket.emit('newPlayer',{
    name: myName
  });
}

let snake = [
    {x: 150, y: 150}
];

// Horizontal velocity
let dx = 0;
// Vertical velocity
let dy = 0;
// Score variable
let score = 0;

// Get the canvas element from index.html
var canvas = document.getElementById('gameCanvas');

// Return a two dimensional drawing context
var ctx = canvas.getContext('2d');


// Select the color to fill the canvas
ctx.fillStyle = CANVAS_BACKGROUND_COLOR;

// Select the color to fill border of canvas
ctx.strokeStyle = CANVAS_BORDER_COLOR;

// Draw a 'filled' rectangle to cover the entire canvas
ctx.fillRect(0, 0, gameCanvas.width, gameCanvas.height);

//Draw a border around the entire canvas
ctx.strokeRect(0, 0, gameCanvas.width, gameCanvas.height);

function randomTen(min, max) {
    return Math.round((Math.random() * (max-min) + min ) / 20) * 20;
}

function advanceSnake() {
    // Constant for adding snake head 
    const head = {x: snake[0].x + dx, y: snake[0].y + dy};

    // Add a new head with coordinates of dx, dy
    snake.unshift(head);

    if ((snake[0].x >= bigFoodXNeg && snake[0].x <= bigFoodXPos) && (snake[0].y >= bigFoodYNeg && snake[0].y <= bigFoodYPos)) {
        score += 1;
        document.getElementById('score').innerHTML = score;

        socket.emit('makeFood', {tf: true})

    }  else {
        // Remove the last part of the snake
        snake.pop();
    }
}

function drawSnake() {
    snake.forEach(drawSnakePart);
}

function drawSnakePart(snakePart) {
    // Set the color of the snake part
    ctx.fillStyle = SNAKE_COLOR;

    // Set the border color of the snake part
    ctx.strokestyle = SNAKE_BORDER_COLOR;

    // Draw a 'filled' rectangle to represent the snake part at the coordinates
    // the part is located
    ctx.fillRect(snakePart.x, snakePart.y, 10, 10);

    // Draw a border around the snake part
    ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
}

function clearCanvas(){
    ctx.fillStyle = 'white';
    ctx.strokeStyle = 'black';

    ctx.fillRect(0, 0, gameCanvas.width, gameCanvas.height);
    ctx.strokeRect(0, 0, gameCanvas.width, gameCanvas.height);
}

document.addEventListener('keydown', changeDirection);

function changeDirection(event) {
    const LEFT_KEY = 65;
    const RIGHT_KEY = 68;
    const UP_KEY = 87;
    const DOWN_KEY = 83;

    if (changingDirection) return;
    changingDirection = true;

    const keyPressed = event.keyCode;
    const goingUp = dy === -10;
    const goingDown = dy === 10;
    const goingRight = dx === 10;
    const goingLeft = dx === -10;

    if (keyPressed === LEFT_KEY && !goingRight) {
        dx = -10;
        dy = 0;
    }

    if (keyPressed === RIGHT_KEY && !goingLeft) {
        dx = 10;
        dy = 0;
    }

    if (keyPressed === UP_KEY && !goingDown) {
        dx = 0;
        dy = -10;
    }

    if (keyPressed === DOWN_KEY && !goingUp) {
        dx = 0;
        dy = 10;
    }
}

function didGameEnd() {
    for (let i = 4; i <snake.length; i++) {
        const didCollide = snake[i].x ===snake[0].x && snake[i].y === snake[0].y;

        if (didCollide) return true;        
    }

    const hitLeftWall = snake[0].x < 0;
    const hitRightWall = snake[0].x > gameCanvas.width - 10;
    const hitTopWall = snake[0].y < 0;
    const hitBottomWall = snake[0].y > gameCanvas.height - 10;

    return hitLeftWall ||
        hitRightWall ||
        hitTopWall ||
        hitBottomWall;
}

function drawFood() {
    ctx.fillStyle = 'orange';
    ctx.strokestyle = 'orange';
    ctx.fillRect(foodX, foodY, 20, 20);
    ctx.strokeRect(foodX, foodY, 20, 20);
}

socket.on('displayFood', function(food) {
    foodX = food.x;
    foodY = food.y;
    bigFoodXPos = foodX + 10;
    bigFoodXNeg = foodX - 10;
    bigFoodYPos = foodY + 10;
    bigFoodYNeg = foodY - 10;  
})

function main() {
    if (didGameEnd()) return;
    setTimeout(function onTick() {
        changingDirection = false;
        clearCanvas();
        drawFood();
        advanceSnake();
        drawSnake();    
        // Call main again
        main();
    }, 25);
}

main();

服务器:

////// SERVER //////

// io.sockets.emit('subject', content) ## SEND TO CLIENTS

var express = require('express');
var socket = require('socket.io');

var players = [];

// App Setup
var app = express();
var server = app.listen(8000, function() {
    console.log('Listening to requests on port 8000');
});

// Static files
app.use(express.static('public'));

// Socket setup
var io = socket(server);

var food = true;

createFood();

io.on('connection', function(socket) {
    console.log('made socket connection', socket.id);

    socket.on('newPlayer', function(data){
        players.push({
            id: socket.id,
            name: data.name,
            dx: 0,
            dy: 0
        });
        console.log(players[players.length-1].name + " has joined");
        //console.log(create);
        displayFood();

    });
});

io.sockets.on('makeFood', function(data) {
    food = data.tf;
});

function randomTen(min, max) {
    return Math.round((Math.random() * (max-min) + min ) / 20) * 20;
}

function createFood() {
        foodX = randomTen(0, 800 - 40);
        foodY = randomTen(0, 800 - 40);
        console.log("Food created at: " + foodX + ", " + foodY);

        displayFood();
        food = false;
    }

function displayFood() {
    io.sockets.emit('displayFood', {
        x : foodX,
        y : foodY,
    });
}


function main() {
    setTimeout(function onTick() {
        if (food == true) {
        createFood()};
        main();
    }, 500);
}

main();

标签: javascriptsocket.io

解决方案


我终于找到了我自己问题的答案。我在客户端改变了一些东西,即

io.sockets.on('makeFood', function(data) {
    food = data.tf;

至:

socket.emit('makeFood')

这样我就可以只向标记的套接字发出信号,'makefood' 而不是使这个面向对象(我出于绝望而这样做),因为确实没有理由。在服务器端,它没有向播放器调用函数,因为我在函数io.sockets.on的外部使用io.on(我认为它可以工作,但显然不行)所以我将其更改为socket.on并将其移动io.on('connection', function(socket)到结果是:

服务器:

io.on('connection', function(socket) {
    console.log('made socket connection', socket.id);

    socket.on('newPlayer', function(data){
        players.push({
            id: socket.id,
            name: data.name,
            dx: 0,
            dy: 0
        });
        console.log(players[players.length-1].name + " has joined");
        //console.log(create);
        displayFood();   
    });
    socket.on('makeFood', function() {
        createFood();
    });
});

现在食物更新到客户端。顺便说一句,function createFood() {我调用了另一个函数,该函数发出食物的 x、y 坐标。这就是为什么我能够看到客户端更新的食物:

socket.on('displayFood', function(food) {
    foodX = food.x;
    foodY = food.y;
});

希望这对其他人有帮助!:)


推荐阅读