Почему splice удаляет все элементы из массива?

#javascript #arrays #for-loop #splice

#javascript #массивы #for-цикл #соединение

Вопрос:

Итак, я пытаюсь создать эту игру (которую я видел в видео), но я хотел бы сделать ее по-другому, и я застрял. У меня есть этот массив со снарядами. По сути, каждый раз, когда снаряд покидает экран, я хотел бы удалить этот снаряд из массива. Проблема в том, что когда снаряд попадает на экран, все снаряды удаляются.

Код:

 function animate(){

    requestAnimationFrame(animate);
    c.clearRect(0, 0, width, height);
    player.draw();
    
    //shoot on click
    addEventListener('click', function(event){
        mousex = event.clientX;
        mousey = event.clientY;
        let angle = Math.atan2(mousey - player.y, mousex - player.x);
        projectiledx = Math.cos(angle) * 8;
        projectiledy = Math.sin(angle) * 8; 
        projectileArray.push(new Projectile(width/2, height/2, 10, projectiledx, projectiledy, black));

    })
    for(let i = 0; i < projectileArray.length; i  ){
        projectileArray[i].update();
        if(projectileArray[i].x   projectileArray[i].radius < 0 || projectileArray[i].x - projectileArray[i].radius >= width){
            projectileArray[i].splice(i, 1);
         }
         if(projectileArray[i].y   projectileArray[i].radius < 0 || projectileArray[i].y - projectileArray[i].radius >= height){
            projectileArray[i].splice(i, 1);
         }
    }
}
animate();
 

Комментарии:

1. Вы должны поместить requestAnimationFrame() в конец функции и сначала вызвать animate с помощью requestAnimationFrame()

2. Вы получаете какие-либо ошибки при запуске?

3. Вы также должны переместить вызов за addEventListener пределы animate функции.

4. Где projectileArray определено? Есть ли где-нибудь еще в коде, где он может быть сброшен по ошибке?

5. Нет, я не получал никаких сообщений об ошибках, но сейчас он работает нормально. projectileArray определен глобально, но он используется только там, поэтому он не сбрасывается в другом месте. Я также переместил addEventListener за пределы функции animate . Я не знаю, почему я туда поместил, на самом деле это не имеет никакого смысла. Большое спасибо.

Ответ №1:

Я вижу здесь как минимум две проблемы:

  1. раньше не должно быть [i] .splice
  2. Вы повторяете массив с помощью цикла for и в этом цикле хотите изменить длину этого массива — мне это кажется плохой идеей.. Лучше возьмите список элементов для удаления и после этого цикла … удалите их (начиная с последнего) в другом цикле, подобном этому:
      var removalList = [];
     for(let i = 0; i < projectileArray.length; i  ){
         projectileArray[i].update();
         if(
             projectileArray[i].x   projectileArray[i].radius < 0 ||
             projectileArray[i].x - projectileArray[i].radius >= width ||
             projectileArray[i].y   projectileArray[i].radius < 0 ||
             projectileArray[i].y - projectileArray[i].radius >= height
         ){
             removalList.push(i);
          }
     }
    
     for(let i=removalList.length; i>0; i--){
         projectileArray.splice( removalList[i-1], 1 );
     }