159 lines
4.4 KiB
Java
159 lines
4.4 KiB
Java
package shootergame.display.lighting;
|
|
|
|
import shootergame.Main;
|
|
import shootergame.display.Camera;
|
|
import shootergame.entity.Entity;
|
|
import shootergame.entity.player.EntityPlayer;
|
|
import shootergame.util.math.MathHelpers;
|
|
import shootergame.util.math.TileState;
|
|
import shootergame.util.math.vec.Vec2i;
|
|
import shootergame.world.chunk.Chunk;
|
|
import shootergame.world.chunk.ChunkEventHandler;
|
|
import shootergame.world.layer.Layer;
|
|
|
|
public class LightingManager
|
|
{
|
|
public static void update()
|
|
{
|
|
if(!ChunkEventHandler.loaded) return;
|
|
int r = Camera.camera.renderDistance;
|
|
Layer layer = Main.world.getLayer();
|
|
double light_clear = layer.layergen.getLightLevel();
|
|
EntityPlayer player = Main.player;
|
|
|
|
// Clear every light source
|
|
for(int cx=-r;cx<=r;cx++) {
|
|
for(int cy=-r;cy<=r;cy++)
|
|
{
|
|
// Get the chunk position and the chunk
|
|
Chunk chunk = layer.chunks.get(new Vec2i(
|
|
MathHelpers.floor(player.pos.x / 16) + cx,
|
|
MathHelpers.floor(player.pos.y / 16) + cy));
|
|
|
|
// Loop over all the tiles
|
|
for(int x=0;x<16;x++) {
|
|
for(int y=0;y<16;y++)
|
|
{
|
|
// Clear the tiles light
|
|
chunk.setLightLevel(light_clear, new Vec2i(x, y));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Loop over every entity and every block to scan for light sources
|
|
for(int cx=-r;cx<=r;cx++) {
|
|
for(int cy=-r;cy<=r;cy++)
|
|
{
|
|
// Loop over all the entities
|
|
Vec2i cpos = new Vec2i(
|
|
cx + MathHelpers.floor(player.pos.x / 16),
|
|
cy + MathHelpers.floor(player.pos.y / 16));
|
|
Chunk chunk = layer.chunks.get(cpos);
|
|
|
|
// Create all the entity light sources
|
|
for(Entity e : chunk.entities)
|
|
{
|
|
// Does this entity emit light
|
|
if(e.emitsLight)
|
|
{
|
|
// Create some light
|
|
addLightToTiles(layer, new Vec2i(
|
|
MathHelpers.floor(e.pos.x),
|
|
MathHelpers.floor(e.pos.y)),
|
|
e.getLightLevel(), true);
|
|
}
|
|
}
|
|
|
|
// Create all the tile light sources
|
|
for(int x=0;x<16;x++) {
|
|
for(int y=0;y<16;y++)
|
|
{
|
|
// Get the tile position
|
|
Vec2i tpos = new Vec2i(x + cpos.x * 16, y + cpos.y * 16);
|
|
int tid = tpos.getId(Chunk.CHUNK_SIZE);
|
|
|
|
// Get the front and back tiles
|
|
TileState fts = chunk.getFrontTile(tid);
|
|
TileState bts = chunk.getBackTile(tid);
|
|
|
|
// Do any of these emit light
|
|
if(fts.tile.emitsLight || bts.tile.emitsLight)
|
|
{
|
|
// Calculate the light given off by the tile
|
|
double light_tile = chunk.getLightLevel(tid);
|
|
double light_tile_old = light_tile;
|
|
light_tile = MathHelpers.biggest(light_tile, fts.tile.getLightLevel(fts, tpos));
|
|
light_tile = MathHelpers.biggest(light_tile, fts.tile.getLightLevel(bts, tpos));
|
|
|
|
// Has the light level changed; add light to this tile
|
|
if(light_tile != light_tile_old) {
|
|
addLightToTiles(layer, tpos, light_tile, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Does the player emit light
|
|
if(player.emitsLight) {
|
|
addLightToTiles(layer, new Vec2i(
|
|
MathHelpers.floor(player.pos.x),
|
|
MathHelpers.floor(player.pos.y)),
|
|
player.getLightLevel(), true);
|
|
}
|
|
}
|
|
|
|
private static void addLightToTiles(Layer layer, Vec2i lpos, double light, boolean ignoreDissipation)
|
|
{
|
|
if(
|
|
MathHelpers.floor(lpos.squareDistance(new Vec2i(
|
|
MathHelpers.floor(Main.player.pos.x),
|
|
MathHelpers.floor(Main.player.pos.y))) / 16)
|
|
> Camera.camera.renderDistance) {
|
|
return;
|
|
}
|
|
|
|
// Get the light pos id
|
|
int lid = lpos.getId(Chunk.CHUNK_SIZE);
|
|
|
|
// Get the light dissipation amount
|
|
Chunk chunk = layer.getChunk(lpos);
|
|
TileState bt = chunk.getBackTile(lid);
|
|
TileState ft = chunk.getFrontTile(lid);
|
|
double light_dissipation = 0;
|
|
|
|
if(!ignoreDissipation) {
|
|
light_dissipation = MathHelpers.biggest(
|
|
bt.tile.getLightDissipation(bt),
|
|
ft.tile.getLightDissipation(ft));
|
|
}
|
|
|
|
// Calculate the light level
|
|
double light_tile = chunk.getLightLevel(lid);
|
|
if(light <= light_tile) {
|
|
return;
|
|
}
|
|
|
|
// Merge the light and the light tile values
|
|
chunk.setLightLevel(light, lid);
|
|
|
|
// Set the light dissipation
|
|
light = light - light_dissipation;
|
|
|
|
// Get all the adjacent positions of the light tiles to flow onto
|
|
Vec2i positions[] = {
|
|
new Vec2i(lpos.x+1, lpos.y),
|
|
new Vec2i(lpos.x-1, lpos.y),
|
|
new Vec2i(lpos.x, lpos.y+1),
|
|
new Vec2i(lpos.x, lpos.y-1)
|
|
};
|
|
|
|
// Add the light to all the adjacent positions
|
|
for(Vec2i position : positions) {
|
|
addLightToTiles(layer, position, light, false);
|
|
}
|
|
}
|
|
}
|