Java 脚本在拼接后覆盖数组索引
Java Script overwriting array indices after splicing
我遇到了一个问题,似乎我在拼接后覆盖了数组索引,至少我认为是这样。它适用于使用 Phaser 2 构建的小游戏。它本质上只是一个小型多人跳跃游戏,可以获得一些客户端/服务器架构的经验。正在使用 socket.io 和 express。我的问题似乎出在服务器上,当客户端断开连接时,当它从玩家列表中删除时,仍在游戏中的其他玩家似乎覆盖了断开连接的玩家的索引。为了调试这个,我主要使用控制台日志,使用 for 循环遍历列表并打印出玩家的套接字 ID。因此,例如,如果我使用插槽 ID 1 的玩家 1 加入,然后使用插槽 ID 2 的玩家 2 加入,然后玩家 2 离开,for 循环将打印出 1、1。如果使用插槽 ID 3 的新玩家 3 在玩家之后加入2 已经离开,打印出玩家的 ID 将打印出 1、1、3。起初我认为问题是在 onNewPlayer(data) 函数中,我遇到了别名问题,因为我在两个中使用了 var currentInfo不同的地方,所以我将第二个对象更改为 var info。这似乎是某种别名问题,还是我应该在其他地方搜索此问题?如果需要,我可以提供额外的代码,到目前为止,我们所有关于玩家创建和移动的回调都运行良好。谢谢。
下面是相关的服务器端代码
var players[];
//When a new player is made, save it
function onNewPlayer(data) {
var newPlayer = new Player(data.x, data.y, this.id);
var currentInfo = {
x: newPlayer.x,
y: newPlayer.y,
id: newPlayer.id,
};
for(i = 0; i < players.length; i++) {
//broadcast the new player out to all the other players in the list
this.broadcast.emit("newEnemy", currentInfo);
}
//check for if there are already players,
//if so, send the player's who are already in the game to the new player
if(players.length > 0) {
for(i = 0; i < players.length; i++) {
var info = {
x: players[i].x,
y: players[i].y,
id: players[i].id,
};
this.emit("newEnemy", info);
}
}
players.push(newPlayer);
for(i = 0; i < players.length; i++) {
console.log(players[i].id);
}
}
function onDisconnect(){
console.log("User " + this.id + " disconnected");
//find the user in the list of players and remove them, then tell the client
for(i = 0; i < players.length; i++) {
if(players[i].id === this.id) {
console.log("removing this player " + this.id);
//TODO trying a different broadcast
this.broadcast.emit("playerDisconnect", this.id);
console.log(players[i].id);
players.splice(i, 1);
}
}
}
下面是相关的客户端代码
//We've lost connection with the server!
function onSocketDisconnect() {
console.log("Lost connection with server!");
};
//When the server notifies the client an enemy has disconnected,
//search for it in the enemies list and stop rendering it
function onEnemyDisconnect(data) {
//TODO
for(i = 0; i < enemies.length; i++) {
if(enemies[i].id == data) {
//TODO
console.log("destroying");
enemies[i].destroy();
enemies.splice(i, 1);
}
}
}
您正在使用 for
循环正向迭代数组并使用 .splice()
从数组中删除元素。这将无法正常工作,因为当您调用 .splice()
从数组中删除一个项目时,它会将数组中后面的元素复制到一个位置。但是,您的 for
循环索引指向数组中的下一个元素。最终结果是您跳过了数组中的迭代项。
有多种可能的解决方案。
您可以向后而不是向前迭代数组。当以相反的顺序迭代时,您尚未迭代的元素不受您的 .splice()
的影响并且它工作得很好。
您可以在 for
循环中停止修改数组。也许您收集了一组要删除的索引,然后从后向前删除它们。
您可以使用 .filter()
创建一个新数组,它是原始数组的子集,完成 .filter()
操作后,只需将新数组分配给您的变量并从那时起使用它。
您可以按原样保持迭代,但在调用 .splice()
后通过将 for
循环索引减一来更正它。
这是反向数组迭代的示例:
// When the server notifies the client an enemy has disconnected,
// search for it in the enemies list and stop rendering it
function onEnemyDisconnect(data) {
// use reverse iteration to avoid skipping elements when calling .splice()
for (i = enemies.length - 1; i >= 0; i--)
if(enemies[i].id == data) {
console.log("destroying");
enemies[i].destroy();
enemies.splice(i, 1);
}
}
}
这是一个 .filter()
的示例,假设您可以分配给 enemies
并且新数组将永久取代它:
// When the server notifies the client an enemy has disconnected,
// search for it in the enemies list and stop rendering it
function onEnemyDisconnect(data) {
enemies = enemies.filter(item => {
if (item.id === data) {
console.log("destroying");
item.destroy();
return false; // don't keep this one
}
return true;
});
}
我遇到了一个问题,似乎我在拼接后覆盖了数组索引,至少我认为是这样。它适用于使用 Phaser 2 构建的小游戏。它本质上只是一个小型多人跳跃游戏,可以获得一些客户端/服务器架构的经验。正在使用 socket.io 和 express。我的问题似乎出在服务器上,当客户端断开连接时,当它从玩家列表中删除时,仍在游戏中的其他玩家似乎覆盖了断开连接的玩家的索引。为了调试这个,我主要使用控制台日志,使用 for 循环遍历列表并打印出玩家的套接字 ID。因此,例如,如果我使用插槽 ID 1 的玩家 1 加入,然后使用插槽 ID 2 的玩家 2 加入,然后玩家 2 离开,for 循环将打印出 1、1。如果使用插槽 ID 3 的新玩家 3 在玩家之后加入2 已经离开,打印出玩家的 ID 将打印出 1、1、3。起初我认为问题是在 onNewPlayer(data) 函数中,我遇到了别名问题,因为我在两个中使用了 var currentInfo不同的地方,所以我将第二个对象更改为 var info。这似乎是某种别名问题,还是我应该在其他地方搜索此问题?如果需要,我可以提供额外的代码,到目前为止,我们所有关于玩家创建和移动的回调都运行良好。谢谢。
下面是相关的服务器端代码
var players[];
//When a new player is made, save it
function onNewPlayer(data) {
var newPlayer = new Player(data.x, data.y, this.id);
var currentInfo = {
x: newPlayer.x,
y: newPlayer.y,
id: newPlayer.id,
};
for(i = 0; i < players.length; i++) {
//broadcast the new player out to all the other players in the list
this.broadcast.emit("newEnemy", currentInfo);
}
//check for if there are already players,
//if so, send the player's who are already in the game to the new player
if(players.length > 0) {
for(i = 0; i < players.length; i++) {
var info = {
x: players[i].x,
y: players[i].y,
id: players[i].id,
};
this.emit("newEnemy", info);
}
}
players.push(newPlayer);
for(i = 0; i < players.length; i++) {
console.log(players[i].id);
}
}
function onDisconnect(){
console.log("User " + this.id + " disconnected");
//find the user in the list of players and remove them, then tell the client
for(i = 0; i < players.length; i++) {
if(players[i].id === this.id) {
console.log("removing this player " + this.id);
//TODO trying a different broadcast
this.broadcast.emit("playerDisconnect", this.id);
console.log(players[i].id);
players.splice(i, 1);
}
}
}
下面是相关的客户端代码
//We've lost connection with the server!
function onSocketDisconnect() {
console.log("Lost connection with server!");
};
//When the server notifies the client an enemy has disconnected,
//search for it in the enemies list and stop rendering it
function onEnemyDisconnect(data) {
//TODO
for(i = 0; i < enemies.length; i++) {
if(enemies[i].id == data) {
//TODO
console.log("destroying");
enemies[i].destroy();
enemies.splice(i, 1);
}
}
}
您正在使用 for
循环正向迭代数组并使用 .splice()
从数组中删除元素。这将无法正常工作,因为当您调用 .splice()
从数组中删除一个项目时,它会将数组中后面的元素复制到一个位置。但是,您的 for
循环索引指向数组中的下一个元素。最终结果是您跳过了数组中的迭代项。
有多种可能的解决方案。
您可以向后而不是向前迭代数组。当以相反的顺序迭代时,您尚未迭代的元素不受您的
.splice()
的影响并且它工作得很好。您可以在
for
循环中停止修改数组。也许您收集了一组要删除的索引,然后从后向前删除它们。您可以使用
.filter()
创建一个新数组,它是原始数组的子集,完成.filter()
操作后,只需将新数组分配给您的变量并从那时起使用它。您可以按原样保持迭代,但在调用
.splice()
后通过将for
循环索引减一来更正它。
这是反向数组迭代的示例:
// When the server notifies the client an enemy has disconnected,
// search for it in the enemies list and stop rendering it
function onEnemyDisconnect(data) {
// use reverse iteration to avoid skipping elements when calling .splice()
for (i = enemies.length - 1; i >= 0; i--)
if(enemies[i].id == data) {
console.log("destroying");
enemies[i].destroy();
enemies.splice(i, 1);
}
}
}
这是一个 .filter()
的示例,假设您可以分配给 enemies
并且新数组将永久取代它:
// When the server notifies the client an enemy has disconnected,
// search for it in the enemies list and stop rendering it
function onEnemyDisconnect(data) {
enemies = enemies.filter(item => {
if (item.id === data) {
console.log("destroying");
item.destroy();
return false; // don't keep this one
}
return true;
});
}