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

时间:2015-05-04 17:07:08

标签: java lighting

我目前正致力于2D Java游戏,目前正在实施动态照明,例如火把,灯泡和太阳。然而,我遇到了一个问题。对于不同实现的大量尝试尚未提供期望的结果,或者不是我正在看的,不是按预期工作或者落后于整个游戏。我尝试了以下实现:

  • 使用RadialGradientPaint创建的(BufferedImage)蒙版
  • Asynchronous flood-fill
  • 同步洪水填充

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更亮的光源(增加半径)将冻结游戏。

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

如果有什么不清楚请告诉我!谢谢

1 个答案:

答案 0 :(得分:1)

我已回答了自上而下的问题... ......但是我也有同样的问题...

使用光线跟踪......

Efficient 2D Tile based lighting system