我正在尝试如何使用socket.io来学习如何创建多人游戏。我目前有一台服务器存储所有玩家的位置,并向每个玩家发送他们的位置,然后将玩家发送给其他人的位置。据我所知,他知道这些数字是完美的。我已经交叉检查了每个位置,它们都像是应该的。出于某种原因,我注意到在将画面画到画布上时,我得到了一些奇怪的行为。以下是一些发生的事例。左上角是玩家的坐标,其下的数字是其他玩家的坐标:
从这张图片中你可以看到我只能看到其中一个玩家。而玩家则在左下方。这本身就没问题。另一个玩家可能在遗嘱中远离屏幕。
在这张图片中你可以看到与第一张图片相同的东西,但还有另一个立方体。现在这没有任何意义。立方体应该是左下方的立方体,并且视图应该向下移动以调整立方体的y值。
现在这张照片是对我来说没有意义的地方。您只能看到最后一个多维数据集,并且当此多维数据集应该是最后一个多维数据集时,蓝色多维数据集仍然显示在最后一个多维数据集的上方和左侧。
这是我正在使用的代码。这可能对你没有任何意义,因为这是我的第一次尝试,需要重大改进。这是服务器的代码:
var express = require('express');
var app = express();
var serv = require('http').Server(app);
var speed = 10
app.get('/', function(req, res) {
res.sendFile(__dirname + "/client/index.html");
});
app.use('client', express.static(__dirname + '/client'))
app.use(express.static(__dirname + '/client'));
serv.listen(2000);
characterList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", ",", ":", ";", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "[", "]", "(", ")", "<", ">", "|"]
var players = []
var connections = []
var io = require('socket.io')(serv, {});
io.sockets.on('connection', function(socket) {
var address = socket.request.connection.remoteAddress;
players.push({
position: {
x: Math.round(Math.random() * 1000),
y: Math.round(Math.random() * 1000)
}
})
connections.push(socket.id)
socket.on('request', function(data) {
length = data.length
if (data.request == 'sessionID') {
socket.emit('sendSessionID', {
id: socket.id
});
}
if (data.request == 'players') {
var otherPlayers = [];
for (var i = 0; i < players.length; i++) {
if (connections[i] != data.id) {
otherPlayers.push(players[i])
} else {
socket.emit('packet', {
packetType: 'self',
player: players[i]
});
console.log[i]
}
}
socket.emit('sendPlayers', {
Players: otherPlayers
});
}
});
socket.on('moveEvent', function(data) {
var player = players[find(connections, data.id)]
if (data.direction == "x+") {
player.position.x = player.position.x + speed
}
if (data.direction == "y+") {
player.position.y = player.position.y + speed
}
if (data.direction == "x-") {
player.position.x = player.position.x - speed
}
if (data.direction == "y-") {
player.position.y = player.position.y - speed
}
});
function find(arrayName, string) {
for (var i = 0; i < arrayName.length; i++) {
if (string == arrayName[i]) {
return i;
}
}
return null;
}
function findKey(key) {
for (var i = 0; i < arrayName.length; i++) {
if (string == arrayName[i].ip) {
return i;
}
}
return null;
}
socket.on('disconnect', function() {
var address = socket.request.connection.remoteAddress;
players.splice(find(connections, this.id), 1)
connections.splice(find(connections, this.id), 1)
});
});
&#13;
以下是使用屏幕上的单个画布元素的客户端代码:
$(function() {
var socket = io();
var sesID = ""
var players = []
var player = {}
var game = document.getElementById('game')
var gamectx = game.getContext('2d');
var GameY = 0;
var GameX = 0;
var w = false;
var a = false;
var s = false;
var d = false;
socket.emit('request', {
request: "sessionID"
});
socket.on('sendSessionID', function(data) {
sesID = data.id
});
socket.on('sendPlayers', function(data) {
players = data.Players
});
socket.on('packet', function(data) {
if (data.packetType == 'self') {
GameX = data.player.position.x;
GameY = data.player.position.y;
player = data.player;
}
});
setInterval(function() {
console.log(players.length)
if (w == true) {
socket.emit('moveEvent', {
direction: "y+",
id: sesID
})
}
if (a == true) {
socket.emit('moveEvent', {
direction: "x+",
id: sesID
})
}
if (s == true) {
socket.emit('moveEvent', {
direction: "y-",
id: sesID
})
}
if (d == true) {
socket.emit('moveEvent', {
direction: "x-",
id: sesID
})
}
gamectx.canvas.width = window.innerWidth;
gamectx.canvas.height = window.innerHeight;
gamectx.clearRect(0, 0, game.width, game.height);
socket.emit('request', {
request: "players",
id: sesID
});
for (var i = 0; i < players.length; i++) {
gamectx.fillStyle = "#ff0000"
gamectx.fillRect(players[i].position.x + GameX, players[i].position.y + GameY, 100, 100)
console.log('drew player at ', players[i].position.x + GameX, players[i].position.y + GameY, 100, 100)
}
gamectx.fillStyle = "#0000ff"
gamectx.fillRect(window.innerWidth / 2 - 50, window.innerHeight / 2 - 50, 100, 100);
gamectx.font = "48px sans-serif";
gamectx.strokeText("x: " + GameX + ", y: " + GameY, 10, 50);
var playersList = ""
for (var i = 0; i < players.length; i++) {
playersList += "x: " + players[i].position.x + ", y: " + players[i].position.y + ", "
}
gamectx.font = "30px sans-serif";
gamectx.strokeText(playersList, 10, 100);
}, 30);
$(document).keydown(function(e) {
if (e.which == 65) {
a = true;
}
if (e.which == 68) {
d = true;
}
if (e.which == 87) {
w = true;
}
if (e.which == 83) {
s = true
}
});
$(document).keyup(function(e) {
console.log(e.which)
if (e.which == 65) {
a = false;
}
if (e.which == 68) {
d = false;
}
if (e.which == 87) {
w = false;
}
if (e.which == 83) {
s = false
}
});
});
&#13;
如果需要,这是html代码:
<html>
<div id="location-div">
</div>
<canvas id="game"></canvas>
<head>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script src="js/jquery-3.1.1.min.js"></script>
<script src="js/game.js"></script>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
</body>
</html>
&#13;
如果这对任何人都有意义,请提前感谢您的帮助!
答案 0 :(得分:0)
在1D x&amp;画布中心cc = 100.
你画出gameX + x
你在cc==100
画自己的玩家所以如果自己是150并且玩家是200你在150+200=350
画一个玩家但是自己被吸引到cc制作玩家{{1自我的像素权利。玩家应该是自我350-cc = 250
右侧50像素。
修复画布中心(cc或原点)的绘制玩家加上自我和玩家之间的差异。
canvas.width/2 + 50
<强>顺便说一句强>
制作角色阵列
ctx.drawRect((canvas.width / 2) + (player.x - self.x), ...
下次需要这样的数组时,可以节省很多输入。
永远不要依赖数据连续性
仅发送移动并依赖每个客户端来维持正确的位置永远不会起作用,在一台机器上错过一个数据包而每个客户端都会有错误的视图。发送绝对位置(带时间戳)加上当前增量。不是字符串,而是编码成您可以发送的最小数据包。
如果下一个数据包迟到,请使用播放器的最后一个增量来更新位置。数据包到达时恢复到实际位置。如果您迟到丢失数据包,则允许交互回滚。即如果位置是从之前的三角洲猜到的,那么就不会杀死玩家,并且新的位置证明命中是一个未命中。
现在意味着什么?
请记住,光速是有限的,你在30ms(3/100秒)更新,这给了光(@ ~300,000,000mps)时间移动9,000,000m或9000km,足够时间移动到一个国家并返回,添加分组交换,客户端处理,响应传输延迟等,对于全世界的游戏来说,最小的ping时间是150ms +(或者只限游戏到低ping(本地))我们都有不同的天数,代码是多人游戏。