Войти
ФлеймФорумПрограммирование

Проверить видимость точки из другой точки в массиве или как-то так

Страницы: 1 2 Следующая »
#0
22:46, 19 фев. 2015

Доброго всем!

Я тут пытаюсь разобраться с освещением в 2Д (примитивным, очень, очень примитивным), вроде всё просто, но тут немного залип, если кто поможет - буду крайне признателен.

Суть проблемы в следующем:

Имеется массив 10х10 заполненный точками, где-то в центре стоит "лампочка" (@):

..........
..........
..........
..........
..........
.....@....
..........
..........
..........
..........

От этой лампочки по окружности исходит "свет" ("*"):

..........
..........
.....*....
...*****..
...*****..
..***@***.
...*****..
...*****..
.....*....
..........

"Алгоритм" тащем-то простой:

(x - x0)^2 + (y - y0)^2 == radius^2 - верхушки "окружности"
(x - x0)^2 + (y - y0)^2 < radius^2 - точки внутри неё

Надо каким-то образом проверить доступность/видимость точки внутри "окружности" из начальной точки в массиве, т.е. что бы между точкой внутри окружности и точкой map[y0][x0] (лампочки) не было бы "стенок" или непроницаемых для света объектов. И если для верхушек "окружности" - это в общем-то не сложно, то вот для остальных точек - у меня что-то никаких идей не возникло.

Подскажите как сделать или хоть в какую сторону копать, буду очень благодарен.


#1
22:51, 19 фев. 2015

ну проводишь линию и смотришь чтоб на пути не было объектов

#2
22:56, 19 фев. 2015

А еще можно готовые алгоритмы отсюда
http://www.roguebasin.com/index.php?title=Field_of_Vision
взять. (ну это если то что в #1 не устраивает, какие-нибудь артефакты или ассиметричности).

#3
23:01, 19 фев. 2015

TarasB
>ну проводишь линию и смотришь чтоб на пути не было объектов

Я это как понимаю: проверить диапазон точек находящихся между точкой А и точкой Б и если в этом диапазоне есть препятствие, точка А не рисуется. Это работает на прямых и с диагоналями, но в "окружности" есть точки, которые не находятся на диагонали и прямой от начальной точки. И как вот проверить эти точки, ведь получается что между ними и начальной уже будет от двух и более точек, эм, в общем, я где-то тут теряюсь в своих рассуждениях.

#4
23:05, 19 фев. 2015

kipar
>А еще можно готовые алгоритмы отсюда

Спасибо - посмотрю.

#5
23:07, 19 фев. 2015

Grinvich
линия между точками в 2д проводится так:

1..........
.XXX.......
....XXX....
.......XXX.
..........2
см. Брезенхам (ну или просто сделай цикл с округлением).
#6
23:10, 19 фев. 2015

kipar

Спасибо ещё раз, кажется теперь понятно!

#7
12:30, 20 фев. 2015

я определял область видимости для юнитов, проходя все тайлы (клетки) по спирали от ближних к дальним. каждую клетку проверяем - если она не попадает ни в один из перекрытых секторов - значит она видима. если это препятствие - добавляем соотв сектор в массив перекрытых секторов.

код на сишарпе:

        public List<Tile> GetVisiblePlots(Tile from, int view)
        {
            var ring = new HashSet<Tile>(from.Neightbours); //first circle plots
            HashSet<Tile> newRing = null;                   //next circle plots
            var visiblePlots = new List<Tile>() { from };   //this will be returned in the end
            var processedPlots = new HashSet<Tile>(ring);
            processedPlots.Add(from);
            
            var hiddenView = new List<Sector>();
            var allIsHidden = false;
            var height = from.TerrainType.Height;
            var viewRadius = (int)(view + height);

            for (int r = 1; r <= viewRadius; r++)
            {
                newRing = new HashSet<Tile>();
                foreach (var plot in ring)
                {
                    processedPlots.Add(plot);
                    var a = new Angle(from, plot);  //direction to the plot
                    if (!hiddenView.Any(v => v.Includes(a))
                    {
                        visiblePlots.Add(plot);
                    }
                    if (!allIsHidden && plot.TerrainType.Height > (int)height)  //this is an obstacle, hide some view
                    {
                        var w = Math.Atan(1 / (double)r);   //an angular width of the obstacle
                        var sect = new Sector(a.Rad - w / 2, a.Rad + w / 2);
                        for (int i = hiddenView.Count - 1; i >= 0; i--)
                        {
                            var s = hiddenView[i];
                            var comb = sect.Combine(s);   //try to combine sectors. if they dont overlap null is returned
                            if (comb == Sector.Full)
                            {
                                allIsHidden = true;
                                break;
                            }
                            if (comb != null)
                            {
                                sect = comb;
                                hiddenView.RemoveAt(i); //remove the consumed sector
                            }
                        }
                        hiddenView.Add(sect);
                    }
                    //add neightbours to a new ring
                    foreach (var p in plot.Neightbours)
                    {
                        if (!processedPlots.Contains(p))
                        {
                            newRing.Add(p);
                        }
                    }
                }
                ring = newRing;
            }
            return visiblePlots;
        }

#8
14:18, 20 фев. 2015

Сделать свой z-буфер =) Только одномерный. Вот моя реализация, успешно работает http://habrahabr.ru/post/204782/
Там в конце есть ссылка на исходники, можно конкретные вычисления глянуть.

#9
18:07, 20 фев. 2015

я как-то делал подобное, по результатам понял, что вариант с рисованием тени от каждого объекта или каждого пикселя не очень хорош для простого освещения - медленно и геморно, особенно, если источников несколько. гораздо проще и быстрее такой вариант:

+ Показать

#10
21:22, 20 фев. 2015

Poroh

наверное лучше повернуть изображение и размазывать вправо

прямая ссылка из статьи

#11
22:01, 20 фев. 2015

Допустим x,y координаты лампочки.
x0,y0 координаты объекта.
Тогда (псевдокод):

Если корень((x-x0)^2 + (y-y0)^2) > radius то объект вне источника света.

#12
22:31, 20 фев. 2015

Viaceslav(C)

( (x-x0)^2 + (y-y0)^2 ) > radius^2

ну что же ты

#13
22:38, 20 фев. 2015

clc
> Viaceslav(C)
> ( (x-x0)^2 + (y-y0)^2 ) > radius^2
> ну что же ты
>

Неправильно.

#14
22:48, 20 фев. 2015

Viaceslav(C)
Суть в том что даже если точка в радиусе, там еще непрозрачные стены могут быть.

Страницы: 1 2 Следующая »
ФлеймФорумПрограммирование

Тема в архиве.