【问题标题】:Lighting around player in tile based game在基于瓷砖的游戏中围绕玩家照明
【发布时间】:2017-06-10 18:55:01
【问题描述】:

我正在使用 Java 开发一个基于瓷砖的挖掘游戏,我想在玩家周围使用渐变照明,想想 Terraria。我目前只是将图像与一个矩形重叠,其中该矩形上的 alpha 是我希望拥有的亮度(0.01 = 黑色,1 = 明亮),这可以正常工作。这不是我如何设置我需要帮助的照明,而是如何编写一个紧凑而有效的算法,让我的数字越大,方块离玩家越近,数字越小,方块离玩家越远.该数字应在 (1 - 0.01) 范围内。每次玩家移动时,我都会调用以下方法:

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());

            }
        }
    }
}

【问题讨论】:

  • 一个方块可以离玩家多远?我还假设您希望玩家在瓷砖上时它最亮?
  • 这还取决于您希望瓷砖褪色的速度/速度。您想要线性淡入淡出,还是想要不同类型的淡入淡出方案?
  • four_lines:我目前有 100x100 个图块,但我希望只有 5-10 个最近的块受到影响。是的,当玩家在瓷砖上时,它应该是最亮的。
  • pacifier21:我在编程方面还不是很全能,所以我希望改变是即时的。当玩家移动一行或一列时,受影响图块上的亮度变化应该是瞬时的。

标签: java algorithm tile


【解决方案1】:

在这种情况下,分两步计算所需值通常是有益的:

  1. 计算 [0...1] 范围内的插值
  2. 根据插值在最小值和最大值之间进行插值

这里的插值是一个“相对”的距离,用于在最小和最大亮度之间进行插值。

两个图块之间的距离可以计算为

sqrt(rowDifference² + columnDifference²)

(顺便说一句,这可以方便地使用Math#hypot 计算)。

受影响的图块与玩家图块在水平和垂直方向上的最大距离为(affectedBlocks - 1)。对于一对瓦片,即瓦片(row, col)(playerInRow, playerInCol),现在可以计算这些瓦片之间的距离,然后将其除以最大距离,以获得作为[0,1] 中的值的相对距离。该值可用于计算适当的亮度。

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;
}

附注:假设affectedBlocks 是常数,最大距离也是常数,并且可以存储为常数值字段,例如

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

【讨论】:

  • 谢谢 Marco13 这很好用。我不擅长数学或编程,所以我不完全理解你的解决方案。我试图调整它(主要是使用最小和最大亮度变量),但我仍然得到一个“硬边缘”,受影响的块与未受影响的块相遇。我添加了您的方法并将 minBrightness 更改为 0.00;和 maxBrightness 为 0.5;有没有办法不得到这些“硬边”?这是几张游戏的图片,第一张受你的方法影响,第二张没那么大:ibb.co/fnHuhaibb.co/gJiH2a
  • 很难从图片中猜出问题所在。如果您提供了System.out.println 语句的结果(可能还在那里打印distancerelative),这可能会有所帮助。它可能有很多文本,因此最好将其发布在 pastebin 之类的东西上(如果真的没有其他选择,那么您可以在问题中发布输出的摘录)。
猜你喜欢
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多