我不确定该怎么写,因为我实际上不知道到底是什么导致了此错误。我正在尝试组装一个简单的小行星仿冒品。
玩家射击时,会使用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: []
谢谢您的回答。
答案 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;
}
}
}
感谢所有答案。