Javascript 拼接后覆盖数组索引的Java脚本

Javascript 拼接后覆盖数组索引的Java脚本,javascript,express,socket.io,alias,phaser-framework,Javascript,Express,Socket.io,Alias,Phaser Framework,我遇到了一个问题,至少我认为我在拼接之后覆盖了数组索引。这是一个使用Phaser2构建的小游戏。它本质上只是一个多人跳跃游戏,以获得一些客户机/服务器架构的经验。我们正在使用socket.io和express。我的问题似乎是在服务器上,当客户端断开连接时,当它从玩家列表中删除时,仍在游戏中的另一个玩家似乎覆盖了断开连接的玩家的索引。为了调试这个,我主要使用控制台日志,使用For循环迭代列表并打印出播放器的套接字ID。举个例子,如果我加入了一个套接字ID为1的播放器1,然后加入了套接字ID为2的播

我遇到了一个问题,至少我认为我在拼接之后覆盖了数组索引。这是一个使用Phaser2构建的小游戏。它本质上只是一个多人跳跃游戏,以获得一些客户机/服务器架构的经验。我们正在使用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);
        }
    }
}
var玩家[];
//当一个新玩家被创建时,保存它
功能层(数据){
var newPlayer=newPlayer(data.x,data.y,this.id);
var currentInfo={
x:newPlayer.x,
y:新玩家,y,
id:newPlayer.id,
};
对于(i=0;i0){
对于(i=0;i
下面是相关的客户端代码

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);
        }
    }
}
//我们与服务器失去了连接!
函数onSocketDisconnect(){
log(“与服务器的连接断开!”);
};
//当服务器通知客户端敌人已断开连接时,
//在敌人列表中搜索并停止渲染它
功能onEnemyDisconnect(数据){
//待办事项
对于(i=0;i<0.length;i++){
if(敌人[i].id==数据){
//待办事项
控制台日志(“销毁”);
敌人[i].消灭();
3.拼接(i,1);
}
}
}

您正在使用
for
循环正向迭代数组,并使用
.splice()
从数组中删除元素。这将无法正常工作,因为当您调用
.splice()
从数组中删除某个项时,它会将以后的元素从数组中向下复制一个位置。但是,您的
for
循环索引指向数组中的下一个元素。最终的结果是跳过数组中的迭代项

有多种可能的解决方案

  • 可以向后而不是向前迭代数组。当以相反顺序迭代时,尚未迭代的元素不会受到
    .splice()
    的影响,并且工作正常

  • 您可以在
    for
    循环中停止修改数组。也许您收集了一组要删除的索引,然后从后向前删除它们

  • 您可以使用
    .filter()
    创建一个新数组,该数组是原始数组的子集,当使用
    .filter()
    操作时,只需将新数组分配给您的变量,然后再使用它即可

  • 您可以保持迭代的原样,但在调用
    .splice()
    后,可以通过将其递减1来更正
    循环索引

  • 下面是一个反向数组迭代的示例:

    // 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()
    的一个示例,它假设您可以将
    分配给敌人
    ,新数组将永久取代它的位置:

    // 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;
        });
    }
    

    非常感谢你!我永远也不会发现这一点。对JS来说还是很新的,来自C/C++。在for循环结束后,我只是复制了索引并删除了所需的对象。@user406955-如果只有一个匹配项,在执行
    .splice()
    之后,您可以
    中断
    for
    循环,这样应该不会有问题。这些解决方案适用于可以有多个匹配项的情况。我应该一次只处理删除一个播放器的问题,我认为回调应该只针对断开连接的单个套接字进行调用,对吗?