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

时间:2016-03-23 13:29:04

标签: javascript performance canvas garbage

概述

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

所以,在我的代码中,我为玩家创建了一个IIFE,并为投射器创建了一个构造函数。玩家听取游戏画布上的点击,当它听到一个时,它会创建一个射弹并将其附加到玩家内的一个物体上。然而,当一个射弹到达屏幕的右侧时,我希望它被摧毁,因为它可以从玩家的射弹物体中移除,并且用于射弹的所有更新和绘制功能结束。到目前为止,我已经设法阻止它的绘制和更新,但我还没能将它从Players射弹对象中删除。希望下面的代码能够更好地展示我正在尝试做的事情。

实施例

var Player = (function () {
    var width = 50;
    var height = 50;
    var x = 0;
    var y = 0;
    var projectiles = [];

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

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

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

    Canvas.bindEvent('mousemove', function (e) {
        //x = e.pageX - Canvas.element.getBoundingClientRect().left;
        y = e.pageY - Canvas.element.getBoundingClientRect().top;
    });

    Canvas.bindEvent('click', function () {
        projectiles.push(new Projectile(width, y + (height / 2)));
    });

    return {
        draw: draw,
        update: update
    }
})();

var Projectile = function (x, y) {
    this.w = 10;
    this.h = 10;
    this.x = x;
    this.y = y;
    this.speed = 5;
    this.destroyed = false;

    this.update = function () {
        this.x += this.speed;

        if(this.x > Canvas.element.width){
            this.destroyed = true;
            this.x = 0;
            console.log('Projectile Destroyed!');
        }
    };

    this.draw = function(){
        Canvas.context.fillStyle = 'red';
        Canvas.context.fillRect(this.x, this.y, this.w, this.h);
    };
};

Js Fiddle

这是我在半工作JS小提琴中的当前代码,因此上面的代码可以在上下文中查看。如果这个问题不明确,请在评论中告诉我,我会尽力澄清。谢谢大家!

  

https://jsfiddle.net/tzzgwr1w/

4 个答案:

答案 0 :(得分:3)

试试这段代码:

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

这应该是玩家功能/类中更新功能的次要编辑。在更新射弹后,它会检查射弹是否宣告自己被摧毁,如果射弹则将其移除。 splice删除索引为p的元素。

答案 1 :(得分:3)

你可以在update方法中删除被破坏的那个,但是你需要从数组的末尾循环。

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处的对象。

答案 2 :(得分:3)

在这里使用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();
    }
};

....

<强>更新

@Hacketo和我做了一个快速的基准:http://jsperf.com/splice-nosplice/11

答案 3 :(得分:1)

在更新循环中,您可以使用.splice()删除已销毁的弹丸。为了使其不跳过projectiles数组中的项目,您需要反向迭代。

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