计划
我决定开始尝试使用 Node.js 和 Socket.io 并着手制作一款游戏(或者只是一个将每个玩家绘制并显示为一个 block 的大厅)。每次客户端加入时,服务器都应该使用该类并实例化一个新对象,其中包含服务器提供的玩家详细信息(随机)。
服务器随后将使用 socket.io 并将新对象发送给连接的客户端,这样他们就可以拥有该对象,然后可以使用它做一些事情(在本例中为移动)。
客户端应该做的第一件事是将所有用户绘制到 Canvas 上,然后将当前客户端也绘制到 Canvas 上。
问题
我已经到了工作正常的地步,服务器创建了一个新的播放器对象,然后将其发送给客户端,然后客户端将能够使用属性将自己绘制到 Canvas 上,但我似乎无法拥有客户端被发送到其他用户的 Canvas 上绘制,直到我移动播放器。
当我打开多个浏览器选项卡时,它会按预期方式绘制客户端,如下所示:
但是当我移动其中一个时,一个客户确实成功地吸引了其他客户,但其他客户都失去了那一刻给他们的对象,直到他们移动然后它成功地移动到其他地方,然后是另一个客户都失去了屏幕状态,您可以在其中看到他们的位置。简而言之,他们都在屏幕上,并相应地移动到所有浏览器中的正确位置,但是当它发生时你永远看不到所有玩家它一次只显示一个玩家,那就是那个移动的人(在你第一次加入你的地方之后也只能看到自己,直到有人移动,然后你才能看到所有玩家,只有最后移动,直到有人或你移动)。 查看下面的图片
上面显示我聚焦中间选项卡并移动,日志显示发生了什么(注意其他玩家都消失了,只显示移动的玩家)
代码
我只有 2 个正在使用的文件,它们的填充如下。
服务器 - nodejs
var express = require('express'),
app = express(),
http = require('http').createServer(app),
io = require('socket.io').listen(http);
http.listen(8000);
//server connections and routing
app.use(express.static(__dirname + '/public'), function(request, response){
if(request.url !== '/public') {
response.sendFile( __dirname +'/error/index.html');
console.log('Error 404 request, User tried accessing: ' + __dirname + request.url);
}
});
var players = [];
//Lets create a function which will help us to create multiple players
function newPlayer() {
this.name;
this.id = 1;
this.x = Math.random() * 500;
this.y = Math.random() * 500;
//Random colors
var r = Math.random()*255>>0;
var g = Math.random()*255>>0;
var b = Math.random()*255>>0;
this.color = "rgba(" + r + ", " + g + ", " + b + ", 0.5)";
//Random size
this.radius = Math.random()*20+20;
this.speed = 5;
return {'name' : this.name,"x" : this.x,"y" : this.y,"color" : this.color, "radius" : this.radius,"speed" : this.speed}
}
//calls to the server and tracking connection of each new user
io.sockets.on('connection', function(socket){
var currentPlayer = new newPlayer(); //new player made
players.push(currentPlayer); //push player object into array
//create the player
socket.broadcast.emit('createUsers', players);
socket.emit('currentUser', currentPlayer);
//user moved
socket.on('moved', function(data){
console.log(data);
socket.broadcast.emit('moving', data);
});
//disconnected
socket.on('disconnect', function(){
var i = players.indexOf(currentPlayer);
players.splice(i, 1);
socket.broadcast.emit('user left','User: ' + currentPlayer.name + ' Left');
console.log(players);
});
});
console.log('NodeJS Server started on port 8000...');
客户端 - HTML
<!doctype html>
<html>
<head>
<title>Game Dev JS - 1</title>
<link href="./ui.css" rel="stylesheet">
</head>
<body>
<canvas id="canvas" width="500" height="500">
Your Browser Does Not Support Canvas and HTML5
</canvas>
</body>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="/js/engine.js"></script>
</html>
客户端 - CSS
body{
margin: 0 auto;
width: auto;
background: #fff;
text-align: center;
}
#canvas {
margin: 15px;
background: #000;
}
客户端 - Javascript
var socket = io.connect(); //add socket object
//initializing the canvas
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext('2d'),
W = window.innerWidth,
H = window.innerHeight;
var keys = {};
window.addEventListener('keydown', function(e){
keys[e.keyCode] = true;
}, false);
//check if ke is not being pressed or has lifted up
window.addEventListener('keyup', function(e){
delete keys[e.keyCode];
}, false);
socket.on('currentUser', function(newUser){
ctx.fillStyle = newUser.color;
ctx.fillRect(newUser.x, newUser.y, 25, 25);
function update(){
//moving player
if(keys[38]){
newUser.y -= newUser.speed;
socket.emit('moved', newUser);
console.clear();
console.log('You Moving');
console.log(newUser);
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = newUser.color;
ctx.fillRect(newUser.x, newUser.y, 25, 25);
}
if(keys[40]){
newUser.y += newUser.speed;
socket.emit('moved', newUser);
console.clear();
console.log('You Moving');
console.log(newUser);
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = newUser.color;
ctx.fillRect(newUser.x, newUser.y, 25, 25);
}
if(keys[37]){
newUser.x -= newUser.speed;
socket.emit('moved', newUser);
console.clear();
console.log('You Moving');
console.log(newUser);
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = newUser.color;
ctx.fillRect(newUser.x, newUser.y, 25, 25);
}
if(keys[39]){
newUser.x += newUser.speed;
socket.emit('moved', newUser);
console.clear();
console.log('You Moving');
console.log(newUser);
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = newUser.color;
ctx.fillRect(newUser.x, newUser.y, 25, 25);
}
window.requestAnimationFrame(update);
}
update();
});
//moving player and updating on other clients
socket.on('moving', function(moveTo){
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = moveTo.color;
ctx.fillRect(moveTo.x, moveTo.y, 25, 25);
console.clear();
console.log('A Player Moved');
console.log(moveTo);
});
注意事项
我会把它放在一个 fiddle 的某个地方供你玩,但我不知道有什么可以让我用 node.js 服务器进行测试并让你同时查看代码,比如JS fiddle 。我还是 Node 和 Socket.io 的新手,这是我的第一次尝试,任何帮助对我来说都是奖励。一旦主要功能有序,我将着手重构代码。
如果您安装了 npm 并安装了 socket.io,那么您应该能够复制和粘贴它并且它应该可以工作。我的文件夹结构如下 - 这没有任何问题,因为一切都正确加载
提前致谢
最佳答案
moving
事件的客户端监听器将永远只允许客户端一次绘制一个玩家的位置。您正在清除整个屏幕,删除所有其他位置,但随后只重新绘制移动的玩家。
我会推荐阅读 Robert Nystrom 的优秀游戏编程模式电子书 http://gameprogrammingpatterns.com/contents.html .它不涵盖这种特定情况,但您可以从 Observer、Game Loop 和 Update 部分推断出很多内容。在您的情况下,您可能希望服务器运行权威游戏循环和状态,使用观察者更新客户端/服务器之间的状态,并且客户端使用自己的独立游戏循环向用户显示所述状态。
关于javascript - 将多个套接字实例绘制到 Canvas 上并在移动时更新(多人游戏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34187326/