添加和删​​除数组

时间:2018-11-05 16:17:21

标签: javascript arrays push splice

我不确定该怎么写,因为我实际上不知道到底是什么导致了此错误。我正在尝试组装一个简单的小行星仿冒品。

玩家射击时,会使用array.push(...)创建一个新物体(子弹)。一旦此项目符号超出画布范围(超出范围),就可以使用array.splice(...);

将其删除

问题在于子弹以不可预测的方式运动。我不知道该怎么写,所以这里是完整的代码(有效,包括html / css):https://pastebin.com/tKiSnDzX 按住空格键几秒钟(拍摄),您将清楚地看到问题。您还可以使用A / D转动,并使用W前进。

这就是我想发生的事情。只要屏幕上(阵列中)只有一个项目符号,代码就可以正常运行。这意味着不正确的元素将被删除,或者进入对象的构造函数的值在整个过程中都会被弄乱。

图A(项目符号构造函数及其方法)

function Bullet(x,y,rot,vel) {
    this.x = x;
    this.y = y;
    this.rot = rot;
    this.vel = (vel+5);

    this.move = function() {
        this.x += this.vel*Math.cos(this.rot-Math.PI/2);
        this.y += this.vel*Math.sin(this.rot-Math.PI/2);
    }

    this.draw = function() {
        engine.circle(this.x, this.y, 4, "black");

        var c = engine.canvas.getContext('2d');
        c.translate(this.x, this.y);
        c.rotate(this.rot);
        c.beginPath();
        c.strokeStyle="#00FF00";
        c.strokeRect(-5, -5, 10, 10);
        c.closePath();
        c.stroke();
    }
}

附件B(创建/删除项目符号的功能):

shoot: function() {
            if(engine.keyDown.sp == true) {
                if(this.fire > 20) {
                    engine.bullets.unshift(new Bullet(this.x, this.y, this.rot, this.velocity));
                    this.fire = 0;
                } else {
                    this.fire++
                }
            }
            for(i = 0; i < engine.bullets.length; i++) {
                engine.bullets[i].move();
                engine.bullets[i].draw();
                if(engine.bullets[i].x > engine.canvas.width+5 || engine.bullets[i].x < -5 
                || engine.bullets[i].y > engine.canvas.height+5  || engine.bullets[i].y < -5) {
                    console.log('bullet gone, '+i);
                    engine.bullets.splice(i, 1);
                }
            }
        }

数组声明如下:bullets: []

谢谢您的回答。

3 个答案:

答案 0 :(得分:1)

如何用engine.bullets[i].dead = true;标记循环中遇到的任何需要死掉的子弹,然后在循环外的最后用engine.bullets = engine.bullets.filter(b => !b.dead);过滤掉死掉的子弹< / p>

答案 1 :(得分:0)

您正在for循环内使用拼接。删除元素索引1时,元素索引2变为索引1,元素索引3变为索引2。但是您的 i 变量已经为1,因此循环的下一次迭代将转到新索引2.但是新索引2是原始索引3,并且跳过了原始索引2。链接列表可能会更好地为您服务:

var bulletList = null;
function bullet(){
  this.next = bulletList;//if there was a list, record that
  if (this.next)//and set that one to point back to this
   this.next.prev = this;
  bulletList = this;//place new bullet at start of list
  this.previous = null;

  this.draw = function(){
    //do stuff here
    this.next && this.next.draw();//call next item in the list, if any
    if (shouldIBeRemoved){//placeholder, obviously
      if (this.next && this.prev){//remove from middle of list
        this.prev.next = this.next;
        this.next.prev = this.prev;
      }
      else if (this.next && !this.prev){//remove from beginning of list
        bulletList = this.next;
        this.next.prev = null;
      }
      else if (this.prev && !this.next){//remove from end of list
        this.prev.next = null;
      }
      else if (!this.prev && !this.next){//remove only item in list
        bulletList = null;
      }
    }
  }
}

然后绘制所有子弹,只需调用:

if (bulletList)
  bulletList.draw();

答案 2 :(得分:0)

问题在于,每次创建新项目符号时,我都会翻译所有项目符号所在的上下文。这意味着每个子弹将比前一个移动x和y。看起来子弹似乎是在原本不应该在的地方制造的。 “不可预测性”是由子弹承担玩家的旋转这一事实造成的,因此,无论何时创建新的子弹,在前一枚子弹的旋转之上,玩家旋转新的子弹之前,玩家旋转的幅度都会增加多少。

context.save();放在子弹的Hitbox的平移/旋转之前,将context.restore();放在完美解决该问题之后:

Bullet.draw = function() {
    engine.circle(this.x, this.y, 4, "black");
    if(hitbox == true) {
        var c = engine.canvas.getContext('2d');
        c.save();
        c.translate(this.x, this.y);
        //c.rotate(this.rot);
        c.beginPath();
        c.strokeStyle="#00FF00";
        c.strokeRect(-5, -5, 10, 10);
        c.closePath();
        c.stroke();
        c.restore();
    }
}

有人提到我在for循环中使用array.splice();。这样就可以删除项目符号(i),将(i + 1)之后的项目符号向后移动一个索引(i)。这样子弹实际上就被跳过了。

有时我在删除子弹时看着子弹时会注意到这一点-它们在前方“跳跃”。

解决方案是将i -= 1放在bullets.splice(i, 1);之后。这样可以使循环的下一次迭代返回一个索引,从而解决了项目符号偶尔出现的卡顿现象:

shoot: function() {
        if(engine.keyDown.sp == true) {
            if(this.fire > 5) {
                engine.bullets.unshift(new Bullet(this.x, this.y, this.rot, this.velocity));
                this.fire = 0;
            }
        }
        if(this.fire<=5) {
            this.fire++
        }
        for(i = 0; i < engine.bullets.length; i++) {
            engine.bullets[i].move();
            engine.bullets[i].draw();
            if(engine.bullets[i].x > engine.canvas.width+5 || engine.bullets[i].x < -5 
            || engine.bullets[i].y > engine.canvas.height+5  || engine.bullets[i].y < -5) {
                engine.bullets.splice(i, 1);
                i-=1;
            }
        }
    }

感谢所有答案。