我目前正在开发一个2D Java游戏,并且正在实现动态照明,例如火把、灯泡和太阳。然而,我遇到了一个问题。多次尝试不同的实现方式都没有提供所需的结果,要么不是我想要的,要么工作不如预期,或者导致整个游戏卡顿。我已经尝试了以下实现方式:
第二种实现方式——异步泛洪填充也无法正常工作。它只渲染了一部分光线,就停止工作了,特别是对于较大的光源。
第三种实现方式——同步泛洪填充做到了我想要的效果,但由于它在主线程上运行,因此在过程中会使其挂起:
用于创建最后一张图片的代码如下:
相对像素(RelativePixel)只是将游戏中的坐标系统转换为屏幕像素以进行正确的定位。
该代码每秒运行两次,以确保游戏不会立即冻结。多个光源或亮度大于1f的光源(以增加半径)将导致游戏冻结。
因此,我的问题是,是否有更有效/更好的实现动态照明的方法?如果没有,是否有任何方法可以改进当前系统?
如果有任何不清楚的地方,请告诉我!谢谢
- 使用RadialGradientPaint创建的(BufferedImage)掩码
- 异步泛洪填充
- 同步泛洪填充
第二种实现方式——异步泛洪填充也无法正常工作。它只渲染了一部分光线,就停止工作了,特别是对于较大的光源。
第三种实现方式——同步泛洪填充做到了我想要的效果,但由于它在主线程上运行,因此在过程中会使其挂起:
![](https://istack.dev59.com/IcUl0.webp)
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的光源(以增加半径)将导致游戏冻结。
因此,我的问题是,是否有更有效/更好的实现动态照明的方法?如果没有,是否有任何方法可以改进当前系统?
如果有任何不清楚的地方,请告诉我!谢谢