Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.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
Java 动态照明的有效实现是什么?_Java_Lighting - Fatal编程技术网

Java 动态照明的有效实现是什么?

Java 动态照明的有效实现是什么?,java,lighting,Java,Lighting,我目前正在开发一个2D Java游戏,并且正在实现动态照明,例如火把、灯泡和太阳。然而,我遇到了一个问题。许多不同实现的尝试都没有达到预期的效果,要么不是我所期待的,要么没有按照预期工作,要么落后于整个游戏。我尝试了以下实现: 使用RadialGradientPaint创建的(缓冲图像)遮罩 异步填洪 同步填洪 RadialGradientPaint遮罩并不是我想要的,我的实现并没有处理屏幕上的任何元素,这意味着光线会“穿透”墙壁 第二个实现是异步泛洪填充,无法正常工作。它只渲染了部分光线,

我目前正在开发一个2D Java游戏,并且正在实现动态照明,例如火把、灯泡和太阳。然而,我遇到了一个问题。许多不同实现的尝试都没有达到预期的效果,要么不是我所期待的,要么没有按照预期工作,要么落后于整个游戏。我尝试了以下实现:

  • 使用RadialGradientPaint创建的(缓冲图像)遮罩
  • 异步填洪
  • 同步填洪
RadialGradientPaint遮罩并不是我想要的,我的实现并没有处理屏幕上的任何元素,这意味着光线会“穿透”墙壁

第二个实现是异步泛洪填充,无法正常工作。它只渲染了部分光线,然后称之为一天,特别是在光线较大的情况下

第三个实现是同步泛洪填充,它实现了我想要的功能,但由于它在主线程上运行,因此在进程中挂起它:

用于创建最后一个图像的代码如下所示:

public void lightQueue(int x, int y, float level, boolean isSun){
    float newLevel;

    Queue<LightData> queue = new LinkedList<LightData>();
    queue.add(new LightData(x,y,level));

    while(!queue.isEmpty()){
        LightData d = queue.remove();

        try{
            newLevel = d.level - Level.getBlock(d.x, d.y).getLightBlockAmount();
        }catch(NullPointerException e){
            continue;
        }

        if(newLevel <= Level.getBlock(d.x, d.y).getLightLevel()) continue;

        if(newLevel > 1f){
            Level.getBlock(d.x, d.y).setLightLevel(1f);
        } else {
            Level.getBlock(d.x, d.y).setLightLevel(newLevel);
        }

        queue.add(new LightData(d.x + 1, d.y, newLevel));
        queue.add(new LightData(d.x - 1, d.y, newLevel));
        queue.add(new LightData(d.x, d.y + 1, newLevel));
        queue.add(new LightData(d.x, d.y - 1, newLevel));
    }
}
public void tick(){
    for(Emitter e:emitters){
        e.tick();
    }
    if(Main.tickCount % 20 == 0){
        for(Emitter e:emitters){
             if(e instanceof Sun){
                lightRec((int) e.getLocation().getX(), (int)e.getLocation().getY(), e.lightLevel, true);
            } else if(Level.shouldRender(e.getLocation(), Level.camera)){
                lightRec((int) e.getLocation().getX(), (int)e.getLocation().getY(), e.lightLevel, false);
            }
        }
    }
}
public void render(Graphics g, Camera c){
    g.drawImage(texture, c.getRelativePixelX(getLocation().getPixelX()), c.getRelativePixelY(getLocation().getPixelY()), null);
    g.setColor(new Color(0f, 0f, 0f, 1f - lightLevel));
    g.fillRect(c.getRelativePixelX(getLocation().getPixelX()), c.getRelativePixelY(getLocation().getPixelY()), getBounds(c).width, getBounds(c).height);
    g.setColor(Color.WHITE);
}
RelativePixel只是一个从游戏坐标系到屏幕像素的转换,用于正确放置

此代码每秒运行两次,以确保游戏不会立即冻结。多个光源或大于1f的光源(增加半径)将冻结游戏

所以我的问题是,有没有更有效/更好的方法来实现动态照明? 如果没有,我有什么办法可以改进当前的系统吗


如果有任何不清楚的地方,请告诉我!谢谢你

我已经回答了这个问题,从上往下看。。。 …但我是同一个问题

使用光线跟踪


老实说,正确的方法是使用别人编写的代码。你可以用3D程序模拟2D,这就是我要走的路线。搜索“java opengl库”并使用其中一个结果。问题是,您将花费与3D程序一样多的时间来编写和调试此2D代码,因此只使用3D是有意义的。您使用Java2D而不是像JOGL或LWJGL这样的OpenGL包装器有什么原因吗?“正确”的方法是使用现有的库。@Kevin这样做有两个原因,第一个原因是这个项目是计算机科学项目(现在已经交了),我们不能使用任何外部库,第二个原因是我从来没有真正想过这一点。在过去的几周里,我已经在考虑实施LWJGL了,但我认为必须有一种方法让它像这样工作。@KevoSoftworks我绝对建议查看LWJGL,或者更好的libGDX。我相信这在Java2D中是可以做到的,但它不会特别快或漂亮。我想我不太确定你的问题是什么,对不起@KevinWorkman感谢您提供的信息,这是对我的问题的正确回答=)。我将看一看libGDX,如果它很好用的话,我将实现它。谢谢分享!我以前看过那篇文章,但忘了试一试。我用这种方法仍然获得了合理的性能,因此优化将使其正常运行。这真的帮了我大忙!非常感谢您接受这个答案!关于如何提高光线跟踪的性能,当然有很多选择,尽管我不认为这是非常糟糕的。。。。(对我来说效果非常好——我甚至在移动设备上也使用了它)