Suivi efficace des coordonnées sur le client et le serveur
-
28-10-2019 - |
Question
J'essaie de créer un jeu multijoueur en utilisant des websockets, des nœuds et du JavaScript. Quelle est la meilleure approche pour mettre à jour le client et garder une trace des coordonnées des clients sur le serveur. Ma méthode actuelle fonctionne, mais elle est très inefficace. (J'entends le ventilateur de mon ordinateur portable tourner un peu lol!).
Alors que se passe-t-il:
Le serveur attend que le client envoie un message 'startmove', qui contient également la direction. Une fois que le serveur a reçu ce message, il commencera à déplacer le lecteur et à diffuser sa position. Si le serveur a reçu le message 'stopmoving', qui contient également une direction ... il arrête de se déplacer dans cette direction.
Ma question:
Y a-t-il des ajustements que je peux utiliser pour augmenter les performances?
Extrait de code du serveur
var player = { x: 100,
y: 200,
left: false,
right: false,
down: false,
up: false
}
var count = 0;
io.sockets.on('connection', function(client){
++count;
io.sockets.emit('player_count', count);
io.sockets.emit('connect', { "x" : player.x, "y" : player.y });
client.on('disconnect', function () {
--count;
io.sockets.emit('player_count', count);
});
client.on('startmove', function(d){
var direction = d.d;
if (direction == 0) //Left
{
player.left = true;
}
else if (direction == 1) //Up
{
player.up = true;
}
else if (direction == 2) //Right
{
player.right = true;
}
else if (direction == 3) //Down
{
player.down = true;
}
});
client.on('stopmove', function(d){
var direction = d.d;
if (direction == 0) //Left
{
player.left = false;
}
else if (direction == 1) //Up
{
player.up = false;
}
else if (direction == 2) //Right
{
player.right = false;
}
else if (direction == 3) //Down
{
player.down = false;
}
});
setInterval(loop, 15); // 33 milliseconds = ~ 30 frames per sec
function loop() {
if(player.left)
{
player.x--;
io.sockets.emit('position', {"x" : player.x, "y" : player.y });
}
else if (player.right)
{
player.x++;
io.sockets.emit('position', {"x" : player.x, "y" : player.y });
}
if(player.up)
{
player.y--;
io.sockets.emit('position', {"x" : player.x, "y" : player.y });
}
else if (player.down)
{
player.y++;
io.sockets.emit('position', {"x" : player.x, "y" : player.y });
}
}
});
Extrait de code client
$(document).ready(function(){
var canvas = document.getElementById('game'),
ctx = canvas.getContext('2d'),
socket = io.connect('http://localhost');
//Only start the game upon receiving the connect message
socket.on('connect', function(data){
var y = data.y;
var x = data.x;
//Constants
var GAME_WIDTH = $('canvas').width(),
GAME_HEIGHT = $('canvas').height();
var Player = function(x,y,w,h){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
};
var Game = new function(){
var player = new Player(x, y, 100, 100),
left = false,
right = false,
up = false,
down = false;
/* Gather player input */
$(document).keydown(function(event)
{
if ( event.keyCode == 37) //Left
{
socket.emit('startmove', {"d" : 0});
return false;
}
else if (event.keyCode == 38) //Up
{
socket.emit('startmove', {"d" : 1});
return false;
}
else if (event.keyCode == 39) //Right
{
socket.emit('startmove', {"d" : 2});
return false;
}
else if (event.keyCode == 40) //Down
{
socket.emit('startmove', {"d" : 3});
return false;
}
});
$(document).keyup(function(event)
{
if ( event.keyCode == 37) //Left
{
socket.emit('stopmove', {"d" : 0});
return false;
}
else if (event.keyCode == 38) //Up
{
socket.emit('stopmove', {"d" : 1});
return false;
}
else if (event.keyCode == 39) //Right
{
socket.emit('stopmove', {"d" : 2});
return false;
}
else if (event.keyCode == 40) //Down
{
socket.emit('stopmove', {"d" : 3});
return false;
}
});
socket.on('position', function(data){
console.log("x: " + data.x + "\ny: " + data.y);
player.x = data.x;
player.y = data.y;
clear();
draw();
});
/* Clear the canvas */
function clear(){
ctx.clearRect(0,0,GAME_WIDTH, GAME_HEIGHT);
}
/* Draw to the canvas */
function draw(){
ctx.fillRect(player.x, player.y, player.w, player.h);
}
}();
});
});
Dans le navigateur:
La solution
Utilisez des horodatages pour suivre depuis combien de temps un joueur se déplace sur le serveur.
Voici comment je procéderais côté serveur:
var player = { x: 100,
y: 200,
direction: -1,
moving_since: 0
}
var count = 0;
io.sockets.on('connection', function(client){
++count;
io.sockets.emit('player_count', count);
io.sockets.emit('connect', { "x" : player.x, "y" : player.y });
client.on('disconnect', function () {
--count;
io.sockets.emit('player_count', count);
});
client.on('startmove', function(d){
player.direction = d.d;
player.moving_since = Date.now();
});
function adjustCoord(){
player.direction = -1;
var now = Date.now();
if( player.direction == 0){
player.x = player.x - ((now - player.moving_since) / 33);
}
else if( player.direction == 1){
player.y = player.y + ((now - player.moving_since) / 33);
}
else if( player.direction == 2){
player.x = player.x + ((now - player.moving_since) / 33);
}
else if( player.direction == 3){
player.y = player.y - ((now - player.moving_since) / 33);
}
}
client.on('stopmove', adjustCoord);
setInterval(loop, 15); // 33 milliseconds = ~ 30 frames per sec
function loop() {
if ( player.direction != -1){
var prevDir = player.direction;
adjustCoord();
player.direction = prevDir;
}
io.sockets.emit('position', {"x" : player.x, "y" : player.y });
}
});