Создание круга в массиве (карта игрового освещения на основе плитки)

Я делаю мозаичную игру на java и хочу сделать световую карту.

У меня есть некоторые проблемы. У меня есть массив карт освещения, на котором размещены источники света, влияющие на массив. Свет излучает в форме круга. Пока вроде нормально, но это не совсем то, что я хотел.

Вот мой код:

for(float i = 0; i < strength + 1; i++){
    for(double u = 0.0f; u < 360; u += 0.5){
        double angle = u * Math.PI / 180;
        int x2 = (int)(x + i * Math.cos(angle));
        int y2 = (int)(y + i * Math.sin(angle));
        if(map[y2][x2] > 1 - 1 / i)
            map[y2][x2] = 1 - 1 / i;
    }
}

Результат:

Результат

Как вы можете видеть в результате, кажется, что свет слишком сильно расширяется в нижней левой части (красные крестики). Как я могу это исправить?

Справочная информация:

Сила:
радиус распространения света. Это также определяет, насколько ярким будет свет на каждой плитке массива.

«Карта» массива представляет собой двумерный массив с плавающей запятой. Используемый мной движок использует значения с плавающей запятой для альфа-канала. Диапазон от 0 (полностью прозрачный) до 1 (полностью непрозрачный).

Решение (спасибо Джину):

for(int x2 = -strength; x2 <= strength; x2++){
    for (int y2 = -strength; y2 <= strength; y2++) {
        double r = Math.sqrt(x2 * x2 + y2 * y2);
        double inv_rad = r <= strength + 1 ? 1 / r : 0;
        if(map[y + y2][x + x2] > 1 - (float) inv_rad)
            map[y + y2][x + x2] = 1 - (float) inv_rad;
    }
}

person vedi0boy    schedule 26.07.2015    source источник
comment
Можете ли вы добавить еще одно изображение, показывающее ожидаемый результат? И желательно иметь только один источник света, как для вашего текущего результата, так и для ожидаемого результата.   -  person almightyGOSU    schedule 26.07.2015


Ответы (2)


Ваш алгоритм страдает от целочисленного усечения индексов карты. Попробуй с другой стороны. Вычислите расстояние от каждого пикселя в квадрате, окружающем центр, до центра. Исходя из этого расстояния рассчитайте, какой должна быть интенсивность. Это будет примерно так:

for (x = -R; x <= R; x++)
  for (y = -R; y <= R; y++) {
    double r = Math.sqrt(x * x + y * y);
    double inv_rad = r <= R ? 1 / r : 0; // truncate outside radius R
    map[yc + y][xc + x] = 1 - inv_rad;
  }

Здесь xc и yc — целые координаты центра. R - половина размера коробки вокруг центра.

person Gene    schedule 26.07.2015
comment
Я несколько запутался в том, какие переменные представляют что. Является ли R радиусом круга, а r радиусом, достигнутым на данный момент? - person vedi0boy; 26.07.2015
comment
R, вероятно, эквивалентно strength - person njzk2; 26.07.2015
comment
Благодарю вас! Теперь это работает намного лучше. Я немного модифицировал его под свои настройки. Я вставил это в свой вопрос. Спасибо еще раз! - person vedi0boy; 26.07.2015

когда я пытаюсь добавить это в свой проект, я получаю только значения, которые я ввел, где 500, 500,50

private float map[][] = new float[1000][1000];

 public void test(int x, int y, float strength){
    public void addLight(int x,int y,int strength ){
    for(int x2 = -strength; x2 <= strength; x2++){
        for (int y2 = -strength; y2 <= strength; y2++) {
            double r = Math.sqrt(x2 * x2 + y2 * y2);
            double inv_rad = r <= strength + 1 ? 1 / r : 0;
            if(map[y + y2][x + x2] > 1 - (float) inv_rad)
                map[y + y2][x + x2] = 1 - (float) inv_rad;
            System.out.println(map[y + y2][x + x2]);
        }
    }
}
person Ian Evenhuis    schedule 11.11.2015
comment
Это должен быть комментарий, когда он говорит «Опубликовать ответ», это означает, а не вопрос. Во-первых, это решение не работает. Проверьте тот, который я разместил в разделе «Решение» (спасибо Джину), а также проверьте ответ Джина. Есть причина, по которой я получил ошибку с этим алгоритмом, его воспроизведение ничего не даст. - person vedi0boy; 12.11.2015
comment
извините, я указал неправильный метод, но когда вы используете новый, я все равно получаю 0 - person Ian Evenhuis; 12.11.2015
comment
@ vedi0boy, но я пока не могу комментировать, и я изменил метод, так что теперь он показывает правильно - person Ian Evenhuis; 12.11.2015
comment
:) У вас не может быть метода внутри метода... В любом случае, это работает. Вы должны внимательно изучить каждую часть кода. Как вы можете видеть, оператор if: if(map[y + y2][x + x2] > 1 - (float) inv_rad) проверяет, является ли то, что есть в данный момент, более темным (более высоким значением), чем раньше. по умолчанию, когда вы создали массив с плавающей запятой, все имеет значение 0,0, что означает, что ничто не может стать светлее, и условие никогда не выполняется. Попробуйте удалить его для проверки. - person vedi0boy; 12.11.2015