Как реализовать скрытое освещение в 2D-игре на основе блоков?

11

Я хочу иметь 2D освещение, которое может быть заблокировано внутриигровыми объектами. Моя игра имеет вид сверху вниз, и все игровые объекты описываются прямоугольниками.

Допустим, у меня есть мир 10х10, и я помещаю свет в 1х1 и окружаю его светом. Я хочу видеть источник света 1x1, но не где-нибудь еще, потому что он заблокирован стенами.

Я слышал о работе световых лучей, но как это работает?

LiquidFeline
источник
1
Хотелось бы увидеть некоторые языково-независимые ответы на этот вопрос.
Дашто
2
@Dashto: Вам нужен рабочий кусок кода на языке, который вы используете? Это неправильное место, чтобы спросить ..
Кромстер
Что вы пробовали? Когда вы говорите «где-то еще, чтобы не было источника света», что вы имеете в виду? Просто загорелся твой 1,1 квартал и все. Может быть, я не понимаю ваш вопрос, не могли бы вы опубликовать иллюстрацию?
Лоран Кувиду
1
@ Кром Стерн: Я прошу прямо противоположное, на самом деле - концептуальный ответ, который не зависит от языка. Два потока, связанные как дубликаты, не слишком много говорят о концепциях. На самом деле на большинство подобных вопросов на этом сайте просто есть ответы: «Используйте эту библиотеку!» что менее полезно для тех, кто хочет понять, как это работает.
Дашто
@Dashto: Это важная информация, вы должны добавить это к вопросу;)
Kromster

Ответы:

13

Амит Патель написал очень хорошую статью о двухмерном луче.

Это включает в себя наведение лучей на каждую из вершин в пределах диапазона источника света для построения сетки света.

введите описание изображения здесь

Все наглядные примеры интерактивны в посте и очень просты для понимания.

Вам также не нужно ограничивать себя рамкой, периметр, который вы отслеживаете, может быть любой формы, которая вам нравится.

MichaelHouse
источник
1

Вы должны использовать алгоритм лучевого вещания , который означает, что вы должны быть в состоянии вычислить пересечение луча (полулинии) с любым объектом в вашей сцене (линиями, квадратами, кругами, треугольниками ....) и выбрать ближайшее пересечение. Вы излучаете луч во всех направлениях, а затем «рисуете свет» только на ближайший объект.

Вот как это может выглядеть .

Иван Кукир
источник
Я просто спросил, как бы я использовал лучевое литье. Я знаю об этом.
LiquidFeline
0

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

Сначала создайте светоизлучающий объект. Поместите свой свет в координаты х, у.

#include <math.h>
int i = 0;
if ( sqrt( abs( light.x - vertex.x )^2 + abs( light.y - vertex.y )^2 ) <= light.radius)
{
    lightOccludingVertices[i] = vertex;
    i++;
}

//If two or more vertices are both a member of an individual wall,
//illuminate the triangular area between the light, the furthest 
//vertex on the x-axis, and the furthest vertex on the y-axis

Это не гарантируется для вогнутого многоугольника, но оно должно работать нормально для любых выпуклых многоугольников.

Это сработает, если ваши затененные объекты (стены, персонажи, летающие фиолетовые пожиратели людей) будут окрашены на экране после применения освещения. В противном случае половина стены будет выглядеть значительно ярче, чем другая половина. Если ваш точечный источник света находится на одинаковом расстоянии от двух пар вершин одной стены (ровно в два раза меньше высоты вашей стены), примените треугольник к двум ближайшим вершинам, а не к двум, находящимся дальше.

Я должен также упомянуть, что этот метод требует динамически создаваемой точки вершины, где край радиуса света встречается с поверхностью затеняющего объекта. Это создает как минимум 3 вершины для любого перекрывающего объекта и позволит стенам, которые простираются за радиус света (или за пределы экрана), также блокировать любой свет.

Больше информации о вогнутых и выпуклых многоугольниках

| grad
источник