Skocz do zawartości

Oświetlenie oparte o ds_grid


Rekomendowane odpowiedzi

Cześć, myślę zrobić w grze oświetlenie oparte o ds_grid, tj. jedna komórka odpowiadała by np kwadratowi 64x64px. Przypuśćmy, że grid jest 5x5, a w środku jest źródło światła o mocy 3. Sąsiednie komórki będą miały moc oświetlenia już 2, a jeszcze dalej 1. Coś takiego funkcjonowało w minecrafcie, tylko w trójwymiarze. Chyba wiem jak to zrobić na milion pętl, ale zastanawiam się nad wydajniejszym rozwiązaniem. Nakieruje mnie ktoś w jaki sposób coś takiego osiągnąć?

Odnośnik do komentarza
Udostępnij na innych stronach

Rozwiązań zapewne jest kilka w zależności od potrzeb, ale jeżeli chcesz mieć punktowe źródło oświetlenia, to można to rozwiązać dość prostą metodą liczenia odległości komórki od źródła światła. np. stosując taki pseudokod:

grid = new int[32][32]

light_x = 10
light_y = 10
light_pow = 3

for(y = -light_pow; y <= light_pow; y += 1) {
  for (x = -light_pow; x <= light_pow; x += 1) {
    distance = sqrt(x*x + y*y)
    luminance = max(0, light_pow - distance)
    grid[y + light_y][x + light_x] = luminance
  }
}

Jednak nie polecam wykonywać tego kodu co step, może jedynie gdy światło się przemieści (no i oczywiście trzeba wyczyścić poprzedni stan oświetlenia)
PS. Złożoność takiego algorytmu to O(n^2), tzn. im większy zasięg oświetlenia, tym wolniejsze jest jego obliczanie (aż do kwadratu).
Edit: Możesz też zoptymalizować pętlę tak jak jest to opisane tutaj - https://www.redblobgames.com/grids/circle-drawing/

Dodatkowo polecam przejrzeć ten "tutorial" opisujący inne algorytmy, ale ostatecznie można pobawić się też wielordzeniowością:
https://www.youtube.com/watch?v=NEHMJwt7oUI

 

Odnośnik do komentarza
Udostępnij na innych stronach

/// @function iluminate_grid(grid, lightPosX, lightPosY, lightPower);
function iluminate_grid(_grid, _lightX, _lightY, _pwr )
{
	for ( var i = 0; i < _pwr; i++ )
		ds_grid_add_disk(_grid, _lightX, _lightY, i, 1);
}

A może tak? Ale nie wiem jak wydajna jest to funkcja

Odnośnik do komentarza
Udostępnij na innych stronach

@Konrad-GM dał całkiem ok rozwiązanie. Ja bym jedynie wyeliminował 

distance = sqrt(x*x + y*y)

i zamiast tego light_pow podnosił do potęgi.

 

Ale to i tak zapisanie tych świateł jest najmniejszym problemem. Rysowanie ich będzie o wiele bardziej obciążać zasoby. I o ile nie będzie zrobione dobrze (zapisane na surface raz) to będzie zbytnio spowalniać grę. Been there done that

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Jeśli to są kwadraciki i nie mają 255 odcieni alphy, to pewnie nawet można by się pokusić o tileset, aktualizowany tylko przy okazji ruchu i tylko w prostokącie o wysokości "średnica koła + wysokość dwóch kratek" i środku tam gdzie gracz. To by był taki fog of war, ale nie wiem, czy taki efekt jest właśnie porządany.

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki za odpowiedzi, nawet wyszło, aktualizuje mapę światła za każdym razem gdy gracz przejdzie z jednej komórki do drugiej, więc dość rzadko. Max FPS mało spadł, więc wydajność super, a używałem draw_rectangle() na surface. Chciałem jeszcze dodać żeby światło było ograniczone przez bloki, ale koniec końców zrezygnowałem, bo nie wygląda to aż tak dobrze jak sobie wyobrażałem.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...