Javascript 游戏 - IIFE 之间的废物管理
Javascript Game - Waste Management between IIFEs
概览
大家好! - 我正在创建一个横向卷轴 space 射击游戏(类似于旧游戏,仍在学习!) - 我想知道如何更好地管理我的对象以防止资源浪费!
因此,在我的代码中,我为 Player 创建了一个 IIFE,并为射弹创建了一个构造函数。播放器监听游戏 canvas 上的点击,当它听到点击时,它会创建一个射弹并将其附加到播放器中的一个对象。但是,当射弹到达屏幕的右侧时,我希望将其销毁,以便将其从玩家射弹对象中删除,并结束射弹的所有更新和绘制功能。到目前为止,我已经成功地阻止了它的绘制和更新,但我还无法将它从 Players projectile 对象中移除。希望下面的代码能更好地展示我正在尝试做的事情。
例子
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 中的当前代码 fiddle,因此可以在上下文中查看上面的代码。如果这个问题不清楚,请在评论中告诉我,我会尽力澄清。谢谢大家!
试试这个代码:
var update = function () {
for (var p = arr.length-1; p >= 0; p--) {
projectiles[p].update();
if (projectiles[p].destroyed) projectiles.splice(p, 1);
}
};
这应该是对您的播放器更新功能的一个小修改 function/class。更新弹丸后,它会检查弹丸是否声明自己已被销毁,如果是,则将其移除。 splice
删除索引 p
处的元素。
你可以在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 处的对象将不会被检查。
这里使用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
在您的更新循环中,您可以使用 .splice()
来移除被摧毁的射弹。为了不跳过 projectiles
数组中的项目,您需要反向迭代。
for (p = projectiles.length-1; p >= 0; p--) {
if(projectiles[p].destroyed) {
projectiles.splice(p, 1);
} else {
projectiles[p].update();
}
}
概览
大家好! - 我正在创建一个横向卷轴 space 射击游戏(类似于旧游戏,仍在学习!) - 我想知道如何更好地管理我的对象以防止资源浪费!
因此,在我的代码中,我为 Player 创建了一个 IIFE,并为射弹创建了一个构造函数。播放器监听游戏 canvas 上的点击,当它听到点击时,它会创建一个射弹并将其附加到播放器中的一个对象。但是,当射弹到达屏幕的右侧时,我希望将其销毁,以便将其从玩家射弹对象中删除,并结束射弹的所有更新和绘制功能。到目前为止,我已经成功地阻止了它的绘制和更新,但我还无法将它从 Players projectile 对象中移除。希望下面的代码能更好地展示我正在尝试做的事情。
例子
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 中的当前代码 fiddle,因此可以在上下文中查看上面的代码。如果这个问题不清楚,请在评论中告诉我,我会尽力澄清。谢谢大家!
试试这个代码:
var update = function () {
for (var p = arr.length-1; p >= 0; p--) {
projectiles[p].update();
if (projectiles[p].destroyed) projectiles.splice(p, 1);
}
};
这应该是对您的播放器更新功能的一个小修改 function/class。更新弹丸后,它会检查弹丸是否声明自己已被销毁,如果是,则将其移除。 splice
删除索引 p
处的元素。
你可以在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 处的对象将不会被检查。
这里使用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
在您的更新循环中,您可以使用 .splice()
来移除被摧毁的射弹。为了不跳过 projectiles
数组中的项目,您需要反向迭代。
for (p = projectiles.length-1; p >= 0; p--) {
if(projectiles[p].destroyed) {
projectiles.splice(p, 1);
} else {
projectiles[p].update();
}
}