0
votes

I'm working on a tile based digger-game in java where i would like to use gradual lighting around the player, think Terraria. I'm currently just overlapping an image with a rectangle where the alpha on that rectangle is the brightness i wish to have (0.01=black, 1=bright), which works OK. It's not how I set the lighting that i need help with, it's how to write a compact and efficient algorithm that gets me a bigger number the closer the block is to the player, and a smaller number the further away the block is from the player. The number should be in the range (1 - 0.01). I call the following method every time the player moves:

public void calculateBlockBrightness(int playerInRow, int playerInCol) {

    int affectedBlocks = 5;
    float brightness;

    // Loops through all blocks within (affectedBlocks) blocks of the player
    for (int row = playerInRow - affectedBlocks; row <= playerInRow + affectedBlocks; row++) {
        for (int col = playerInCol - affectedBlocks; col <= playerInCol + affectedBlocks; col++) {

            // Not all blocks should be affected by this method
            if (blockNotRelevantForBrightness(row, col))
                continue;

            // If the block is within (affectedBlocks - 1) blocks of the player
            if (row >= playerInRow - (affectedBlocks - 1) && row <= playerInRow + (affectedBlocks - 1)
                    && col >= playerInCol - (affectedBlocks - 1) && col <= playerInCol + (affectedBlocks - 1)) {

                /*
                 * Algorithm
                 */

                blocks[row][col].setBrightnessPercentage(brightness);

            // Reset the "outer layer" blocks to default brightness.
            } else {
                blocks[row][col].setBrightnessPercentage(blocks[row][col].getBrightnessDefault());

            }
        }
    }
}
1
How far can a block be from a player? Also I assume you want it to be brightest when the player is on the tile? - four_lines
It also depends on how fast/slow you want the tiles to fade. Do you want a linear fade, or do you want a different kind of fade scheme? - pacifier21
four_lines: I currently have 100x100 tiles but I'd like if only the 5-10 nearest blocks are affected. And yes, it should be brightest when the player is on the tile. - SunkenSwe
pacifier21: I'm not that versatile in programming yet so I'd like the change to be instantaneous. When the player moves one row or column then the change in brightness on the affected tiles should be instantaneous. - SunkenSwe

1 Answers

0
votes

In cases like this, it is often beneficial to compute the desired value in two steps:

  1. Compute an interpolation value in the range [0...1]
  2. Interpolate between the minimum and maximum, based on the interpolation value

The interpolation value here is a "relative" distance, and it is used for interpolating between the minimum and maximum brightness.

The distance between two tiles can be computed as

sqrt(rowDifference² + columnDifference²)

(This can conveniently be computed using Math#hypot, by the way).

The maximum distance that an affected tile may have to the player tile, in horizontal and vertical direction, is (affectedBlocks - 1). For a pair of tiles, namely the tiles (row, col) and (playerInRow, playerInCol), one can now compute the distance between these tiles, and divide it by the maximum distance, to obtain the relative distance as a value in [0,1]. This value can be used to compute the appropriate brightness.

private float computeBrightness(
    int row, int col, int playerRow, int playerCol, int affectedBlocks)
{
    // Compute the distance of the tile (row, col) to the player tile
    double distance = Math.hypot(row - playerRow, col - playerCol);

    // Compute the maximum possible distance of a tile
    double maxDistance = Math.hypot(affectedBlocks - 1, affectedBlocks -1);

    // Compute the relative distance, as a value in [0,1]
    double relative = distance / maxDistance;

    // Compute the brightness for the relative distance
    double minBrightness = 0.01;
    double maxBrightness = 1.0;
    double brightness = 
        maxBrightness - relative * (maxBrightness - minBrightness);

    System.out.println(
        "For " + row + " " + col + " brightness is " + brightness);

    return (float)brightness;
}

A side note: Assuming that affectedBlocks is constant, the maximum distance would also be a constant, and could be stored as a constant value field, e.g.

private static final int AFFECTED_BLOCKS = 5;
private static final double MAX_DISTANCE = 
    Math.hypot(AFFECTED_BLOCKS - 1, AFFECTED_BLOCKS - 1);