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

时间:2018-06-06 22:45:27

标签: javascript express socket.io alias phaser-framework

我遇到一个问题,看起来我在拼接后会覆盖数组索引,至少我认为。它用于使用移相器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(数据)函数中,我有一个别名问题,因为我在两个中使用了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);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

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

有多种可能的解决方案。

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

  2. 您可以在for循环中停止修改数组。也许您收集了一组要删除的索引,然后将其从后到前删除。

  3. 您可以使用.filter()创建一个新数组,该数组是原始数组的子集,完成.filter()操作后,只需将新数组赋值给变量并使用它然后开始。

  4. 您可以按照自己的方式保持迭代,但在调用for之后通过将其递减1来更正.splice()循环索引。

  5. 这是反向数组迭代的一个例子:

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