我正在为大学工作做一个小游戏,我不太了解垃圾收集器的工作原理 使用EventListeners,我觉得“preCastTimer”EventListener永远不会删除下面的代码。问题是我不知道如何在完成后删除它。
下面是按下按键时用来施放咒语的代码
这里我有由KeyboardEvents调用的强制转换函数,火球是一个MovieClip
preCast(fireball);
function preCast(spell)
{
var tempSpell:Object = new spell;//create an object for the spell so castTime is accessible.
var preCastTimer:Timer = new Timer(tempSpell.castTime,1);
var spellFunc:Function = cast(spell);
preCastTimer.addEventListener(TimerEvent.TIMER_COMPLETE, spellFunc);
preCastTimer.start();
}
function cast(spell):Function {
return function(e:TimerEvent):void {
parent.addChild(new spell);//For some reason if spell is not created here it never gets a parent
};
}
以下是火球MovieClip的代码:
package {
import flash.display.MovieClip;
public class fireball extends MovieClip {
public var castTime:uint = 1000;
public function fireball() {
// constructor code
}
}
}
以下代码位于火球时间轴中。我理解使用类更好,但是当代码在包中而不是在时间轴框架上时我仍然不理解父母身份
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.Point;
if (parent)//only run if a parent exists, when created as object no parent is defined
{
x = parent.getChildByName("player").x;
y = parent.getChildByName("player").y;
var direction = new Point(parent.mouseX - x,parent.mouseY - y);
rotation = Math.atan2(parent.mouseY - y,parent.mouseX - x) * 180 / Math.PI;
direction.normalize(5);
if (direction.x == 0 && direction.y == 0)
{
parent.removeChild(this);
return;
}
var spellTimer:Timer = new Timer(500,1);
spellTimer.addEventListener(TimerEvent.TIMER_COMPLETE, spellKiller);
this.addEventListener(Event.ENTER_FRAME, motion);
spellTimer.start();
}
function spellKiller(e:TimerEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, motion);
spellTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, spellKiller);
parent.removeChild(this);
}
function motion(e:Event)
{
x += direction.x * 5;
y += direction.y * 5;
}
答案 0 :(得分:0)
请注意addEventListener
具有useWeakReference
参数(第5个参数)。
public function addEventListener(
type:String,
listener:Function,
useCapture:Boolean = false,
priority:int = 0,
useWeakReference:Boolean = false
):void;
来自EventDispatcher
documentation:
如果您不再需要事件侦听器,请通过调用将其删除 removeEventListener(),或者可能导致内存问题。事件 监听器不会自动从内存中删除,因为 垃圾收集器只要没有删除监听器 调度对象存在(除非useWeakReference参数是 设置为true)。
解决方案是在适当的情况下简单地将addEventListener
调用转换为使用弱引用。
foo.addEventListener(type, listener, false, 0, true);
如果您不确定这对您有何帮助,请告诉我。
答案 1 :(得分:0)
所以你的代码有点过于复杂,缺少一些重要的部分,所以我无法真正评论那个父级的东西。据我所知,计时器应该触发一次然后你想要删除它的侦听器,对吗?嗯,这很容易实现:
function cast(spell):Function {
return function(e:TimerEvent):void {
parent.addChild(new spell);
e.target.removeEventListener(TimerEvent.TIMER_COMPLETE, spellFunc);
};
}
为什么你觉得这不是正确的解决方案?只需将TimerEvent.TIMER_COMPLETE更改为TimerEvent.TIMER(并删除传递给计时器构造函数的重复计数),即可测试是否删除了侦听器。它应该添加一次咒语而不再添加。
另请注意,垃圾收集器不会立即拾取它(好吧,很可能不会!)。它可能会在未来的某个地方或从未接受它。实际上,如果您没有将计时器设置为null或者您没有创建另一个计时器对象并将其分配给同一个变量,那么计时器可能永远不会被选中,因为您的引用将保留,因此永远不会有资格进行垃圾回收。