Box2dLights:处理灯光时出现致命错误 + ConeLight 不起作用

Box2dLights: Fatal error when disposing lights + ConeLight doesnt work

感谢您的光临。

我遇到了 2 个 Box2DLights 问题。

第一个不是那么重要,但是第二个

#1:布置灯

我有多个点光源跟随一个抛射体。 所以每个弹射体都有一个 ArrayList,其中包含它需要的所有 PointLight。 当弹丸击中一个物体时,所有的灯都应该被处理掉。 显然这是个问题。

if(hit){
      deleted = true;
      for(int i = 0; i<myLight.size();i++){
         myLight.get(i).dispose();
       }
}

这会导致致命异常

A fatal error has been detected by the Java Runtime Environment: EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffc6fc59f58, pid=6944, tid=6676 JRE version: Java(TM) SE Runtime Environment (8.0_45-b15) (build 1.8.0_45-b15) Java VM: Java HotSpot(TM) 64-Bit Server VM (25.45-b02 mixed mode windows-amd64 compressed oops) Problematic frame: C [ntdll.dll+0x39f58] Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

我猜,问题是 ArrayList 无法再以某种方式引用已处置的对象。问题是如何做得更好。

#2 : ConeLight 使我的 JavaTM 崩溃 (?)

在我的游戏中添加 ConeLight 时

playerLight = new ConeLight(this,100,Color.WHITE,100,1920f/2f,1080f/2f,0,60);

//used "this" because I called this method in a class that extends RayHandler

当按下 "Play" 时,我的游戏只是在主菜单中冻结 MainMenu 屏幕只是冻结并出现一点 window,上面写着:

"Java(TM) SE binary doesn't work anymore"

但是,PointLight 可以完美地工作。老实说,我不知道这是我的错还是错误。

回答您的问题 #1 - 在处理光线之前,您应该将其从 rayHandler 中移除。否则,rayHandler 将尝试处理已处理的光,这似乎是您遇到的崩溃。

myLight.get(i).remove();

而不是

myLight.get(i).dispose();

这里的第二点是,您可能不应该每次都创建和处理灯光。出于性能原因(光的实例化非常繁重),您最好使用池化。通过池化,您可以使用 remove(false)(false 阻止处理它)和 add() 方法来执行此操作。

关于问题 #2 - 我没有发现 ConeLight 构造函数参数有任何问题,而且 ConeLight 的测试也没有重现您的崩溃。因此,问题可能出在您的扩展 class (或不在)中。建议大家调试更准确的定位问题所在

我终于解决了。这是一个非常愚蠢的错误:

因为我真的不需要 World 对象,而 RayHandler 构造函数确实需要,所以我创建了一个 World 给它 rayhandler 然后处理它。愚蠢,我知道。 所以而不是

    public void create(){
       ....
       World world = new World(new Vector2(0,0),false);
       rayHandler = new RayHandler(world);
       world.dispose;
    }

您需要将 world.dispose 移动到 dispose 方法并使 world 成为一个字段。

public void create(){
       ....
       world = new World(new Vector2(0,0),false);
       rayHandler = new RayHandler(world);

    }
...
public void dispose(){
      ...
      rayHandler.dispose;
      world.dispose();
}