Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/416.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript游戏-IIFE之间的废物管理 概述_Javascript_Performance_Canvas_Garbage - Fatal编程技术网

Javascript游戏-IIFE之间的废物管理 概述

Javascript游戏-IIFE之间的废物管理 概述,javascript,performance,canvas,garbage,Javascript,Performance,Canvas,Garbage,大家好我正在创建一个侧卷轴太空射击游戏(类似于旧游戏,仍在学习!)——我想知道如何更好地管理我的对象,以防止浪费资源 因此,在我的代码中,我为玩家创建了一个IIFE,为投射物创建了一个构造函数。玩家监听游戏画布上的点击,当听到点击时,它会创建一个投射物并将其连接到玩家体内的一个对象上。但是,当投射物到达屏幕右侧时,我希望它被销毁,以便将其从玩家投射物对象中删除,并使投射物的所有更新和绘制功能结束。到目前为止,我已经设法停止了它的绘制和更新,但我还没有能够将它从玩家投射物对象中删除。希望下面的代码

大家好我正在创建一个侧卷轴太空射击游戏(类似于旧游戏,仍在学习!)——我想知道如何更好地管理我的对象,以防止浪费资源

因此,在我的代码中,我为玩家创建了一个IIFE,为投射物创建了一个构造函数。玩家监听游戏画布上的点击,当听到点击时,它会创建一个投射物并将其连接到玩家体内的一个对象上。但是,当投射物到达屏幕右侧时,我希望它被销毁,以便将其从玩家投射物对象中删除,并使投射物的所有更新和绘制功能结束。到目前为止,我已经设法停止了它的绘制和更新,但我还没有能够将它从玩家投射物对象中删除。希望下面的代码能够更好地演示我正在尝试做的事情

例子
var Player=(函数(){
var宽度=50;
var高度=50;
var x=0;
var y=0;
var射弹=[];
变量更新=函数(){
对于(var p=0;pCanvas.element.width){
这是真的;
这个.x=0;
console.log('射弹已销毁!');
}
};
this.draw=函数(){
Canvas.context.fillStyle='red';
Canvas.context.fillRect(this.x,this.y,this.w,this.h);
};
};
Js小提琴 这是我目前在一个半工作JS小提琴中的代码,所以上面的代码可以在上下文中查看。如果这个问题不清楚,请在评论中告诉我,我会尽我所能予以澄清。谢谢大家

请尝试以下代码:

var update = function () {
    for (var p = arr.length-1; p >= 0; p--) {
        projectiles[p].update();
        if (projectiles[p].destroyed) projectiles.splice(p, 1);
    }
};

这应该是对玩家函数/类中的更新函数的一个小编辑。更新射弹后,它检查射弹是否声明自己已销毁,如果已销毁,则将其移除<代码>拼接删除索引中的元素
p

您可以在更新方法中删除已销毁的元素,但您需要从数组末尾循环

var update = function () {
    for (var p = projectiles.length - 1; p >= 0; p--) {
        if(!projectiles[p].destroyed)projectiles[p].update();
        else projectiles.splice(p,1);
    }
};
假设您有一个从0到X的基本循环。 如果删除索引0处的元素,数组将移位,这意味着索引1处的对象将位于索引0处。
但是下一个循环将执行i++操作,那么索引为0的对象将不会被检查。

在这里使用splice是对资源的一点浪费。我建议对阵列进行线性扫描。以下算法将在适当位置过滤射弹阵列:

function removeDestroyeds(arr) {
  for (var i=0, j=0; j < arr.length; j++) {
    if (!arr[j].destroyed) {
      arr[i++] = arr[j];
    }
  }
  arr.length = i;
}

....

var update = function () {
    for (var p = 0; p < projectiles.length; p++) {
        projectiles[p].update();
    }
    removeDestroyeds(projectiles);
};

var draw = function () {
    Canvas.context.fillStyle = 'white';
    Canvas.context.fillRect(x, y, width, height);

    for (var p = 0; p < projectiles.length; p++) {
        projectiles[p].draw();
    }
};

....
功能移除的除虫酯(arr){
对于(变量i=0,j=0;j
更新:


@哈克托和我做了一个快速的基准测试:

在更新循环中,你可以使用
.splice()
移除一个被摧毁的投射物。为了避免跳过
投射物
数组中的项目,需要反向迭代

for (p = projectiles.length-1; p >= 0; p--) {
    if(projectiles[p].destroyed) {
        projectiles.splice(p, 1);
    } else {
        projectiles[p].update();
    }
}

嗨,谢谢你的回答我不清楚如果不反向循环,跳过投射物是什么意思?假设数组中有5个投射物,第三个(索引=2)被销毁,所以您希望将其删除。当您使用
.splice(2,1)
将其移除时,紧跟在第三个项目之后的项目(其索引=3)现在将移动以填充移除项目留下的空插槽,其索引将更改为2。在循环的下一次迭代中,
p
将等于3,因此将永远不会检查移动到索引2的项。如果从数组末尾开始,则已检查所有移动的项,因此您无需担心跳过任何项。您好,感谢您的回答!-然而,我不清楚你所说的需要从数组末尾循环是什么意思-你能澄清一下吗?@Lewis我编辑了我的答案,我希望这是可以理解的。@Lewis你应该看到Vincent的答案,关于对数组进行一些优化是很昂贵的。请参阅对Vincent答案的评论。@markE同意“忽略/重用”的说法,我在游戏中的池
已销毁
可以在
更新
函数中设置为true。这是唯一考虑到这一点的答案。@A1rPun是的,这意味着对象在内存中多保留1个刻度,但这个答案不起作用,因为当发生拼接时,它会丢失数组中的某些元素。@A正确的点
for(var p=projectles.length;p--;)
Vincent在使用
splice
时最好向后循环。splice
的成本相当高,通常比手动重建阵列而不销毁元素慢50%。拼接工作正常,但它只是一个“OK”
for (p = projectiles.length-1; p >= 0; p--) {
    if(projectiles[p].destroyed) {
        projectiles.splice(p, 1);
    } else {
        projectiles[p].update();
    }
}