Skocz do zawartości

[Artykul] Optymalne rysowanie bg


Rekomendowane odpowiedzi

Witajcie kochani!

Postanowiłem podzielić się z wami kawałkiem własnego doświadczenia, i przedstawić bardzo dobry sposób na odzyskanie kilku klatek z naszej gry, oczywiście jeżeli inne metody (np: dezaktywacja obiektów) już nie wystarczały. :)

 

Zacznijmy od kilku słów wyjaśnień. Sposób ten jest naprawdę banalny i gdybym nie kombinował to nigdy bym się o tym nie dowiedział. Wszystko opiera się na kiepskim działaniu GameMakera. Nasz biedny, kochany GM z niewiadomych mi powodów zawsze rysuje background w room. Widać to gdy ustawicie sam background i będziecie się bawić rozmiarami room. Przy odpowiednich wymiarach (może nawet 10k x 10k?) zaczniecie odczuwać spadek FPS.

Pytanie, po co komu tak wielki room? No, niestety może się zdarzyć że ktoś robiąc RPG będzie czegoś takiego potrzebował. Chociaż bardziej prawdopodobne że będziemy chcieli rysować różne podłoża w różnych rejonach mapy. ;)

 

Przejdźmy już do samego zagadnienia. Wiemy że GM po ustawieniu background rysuje go na całym room. Nie podoba nam się to i chcemy to zmienić. Jeżeli dezaktywujecie obiekty w swojej grze to wiecie że najlepiej jest robić to z obiektami których nie widać, zazwyczaj są to te poza zasięgiem view. Jeżeli jednak nie wiecie co to dezaktywacja i jak to robić to odsyłam was do (niestety skromnego) wpisu w dokumentacji, albo do naszej forumowej szukajki. :P

Obiekty poza view dezaktywujemy w ten sposób:

GML
instance_deactivate_region(view_xview[0], view_yview[0], view_wview[0], view_hview[0], false, true)
Ale nie ma żadnej funkcji która usunie background poza zasięgiem view! Musimy to zrobić w drugą stronę i rysować tylko tę część tła którą widać. Czyli będziemy rysować prostokąt, prawie taki:
GML
draw_rectangle(view_xview[0], view_yview[0], view_xview[0]+view_wview[0], view_yview[0]+view_hview[0], 0)
No dobrze, ale nie ma funkcji która tak narysuje tło! No, nie ma. Dlatego zrobimy swoją.

 

Pierwsza rzecz jaką musimy zrobić, to wyłączyć wszystkie opcje z zakładki background w naszym room, a następnie ustawić view. I oczywiście trzeba dodać nasz background do zasobów! Ale pobawmy się trochę kodem! Całość opierać się będzie na pętli for, oraz na jednej funkcji do rysowania tła, tj. draw_background(). Nie mam zamiaru opisywać działania pętli! Jeżeli nie wiesz jak działają to wróć do podstaw i zapomnij na razie o robieniu MMORPG. ;)

Naszym zadaniem będzie rysowanie n razy zapętlonego tła. A wyglądać ono będzie jak kafelki w salonie na które patrzę. Kafelki są doskonałym przykładem, czy to te w moim salonie, czy te w Windows 8. Jakie są każdy widzi. Możemy je opisać na wiele sposobów, ale nas interesuje tylko kilka ich atrybutów: tekstura, szerokość, wysokość, pozycja w pokoju. Jeżeli nigdy się nie zastanawialiście to powiem wam że kafelka jest oddalona od swojej sąsiadki o jej szerokość albo wysokość. :P Jeżeli do pozycji x jakiejś kafelki dodamy jej szerokość to otrzymamy pozycję x następnej kafelki, to samo gdy odejmiemy. I z tej zależności będziemy korzystać. Oczywiście te zasady odnoszą się tylko w przypadku gdy wszystkie kafelki mają tę samą szerokość i wysokość! No to może najpierw kod, a później wyjaśnienia?

GML
for(yy=view_yview[0]; yy<view_yview[0]+view_hview[0]; yy+=background_get_height(background0))

for(xx=view_xview[0]; xx<view_xview[0]+view_wview[0]; xx+=background_get_width(background0))

{

draw_background(background0,xx,yy)

}

background0 jest naszym tłem.

background_get_width() i background_get_height() są funkcjami które zwracają nam szerokość i wysokość naszego tła.

yy i xx to zmienne które w każdym kroku będą posiadały współrzędne każdej kafelki, a w środku naszych pętli rysujemy nasze tło na odpowiedniej pozycji.

Reszta powinna być dobrze znana. Jeżeli nie... to polecam podstawowe tutoriale do GM.

Oczywiście to możemy zapisać jako script, albo wrzucić w DRAW. A teraz odpalamy! I jest błąd! Coś jest nie tak! Kafelki zaczynają się zawsze od lewego górnego rogu, a gdy gracz chodzi to się nie przesuwają! Tak nie może być! Jak to naprawić? xoxoxo

 

Tak. To jest błąd ale za moment go rozwiążemy... z pomocą matematyki. A że pisząc ten tekst jest u mnie 22:30 to mogą być problemy. :P Cały problem polega na tym że nasza pętla zaczyna się w pozycji view. Gdyby zaczynała się w (0,0) czyli na początku room (tak jak to robi podstawowo GM) to wszystko byłoby ok. I tu znów odwołamy się do właściwości naszych kafelek. I znów pora na kod!

GML
for(yy=view_yview[0]-(view_yview[0] mod background_get_height(background0)); yy<view_yview[0]+view_hview[0]; yy+=background_get_height(background0))

for(xx=view_xview[0]-(view_xview[0] mod background_get_width(background0)); xx<view_xview[0]+view_wview[0]; xx+=background_get_width(background0))

{

draw_background(background0,xx,yy)

}

Naszym rozwiązaniem okazała się reszta z dzielenia! Jeżeli podzielimy view_xview[0] przez szerokość kafelki to otrzymamy liczbę która oznacza numer naszej kafelki. Ale nas interesuje reszta z dzielenia, bo to o jej wartość przesuniemy wszystkie kafelki, aby były wyrównane względem punktu (0,0). Pytanie jeszcze czemu minus, a nie plus? Aby kafelka zaczynała się poza naszym view. Poza tym możecie to sami sprawdzić.

 

I tak na prawdę to wszytko! Może to nie jest jakiś magiczny algorytm który dokona cudów, ale przy ogromnych mapach i słabym sprzęcie widać katastrofalną różnicę. Na koniec mam coś na co wpadłem dopiero teraz podczas pisania tego tekstu. Nie próbowałem tego, więc nie jestem pewien czy będzie działać, ale powinno. Chodzi mi o rysowanie gdy mamy więcej niż jeden view.

GML
for(v=0;v<=7;v+=1)if(view_visible[v])

for(yy=view_yview[v]-(view_yview[v] mod background_get_height(background0)); yy<view_yview[v]+view_hview[v]; yy+=background_get_height(background0))

for(xx=view_xview[v]-(view_xview[v] mod background_get_width(background0)); xx<view_xview[v]+view_wview[v]; xx+=background_get_width(background0))

{

draw_background(background0,xx,yy)

}

Tak więc dzięki wszystkim którym chciało się to czytać, ale także tym którzy po prostu skopiowali kod, bo zawsze lepiej jak gra działa wydajniej. :P Zastanawiałem się nad dodaniem rysunków, ale najnormalniej mi się nie chce!

 

Pozdrawiam

Threef

Odnośnik do komentarza
Udostępnij na innych stronach

Warto sprawdzać, które działania matematyczne są stałe podczas działania pętli i je wyciągać przed nią. Tak można zaoszczędzić trochę wysiłku procka.

GML
W = background_get_width(background0);

H = background_get_height(background0);

Y = view_yview[0] mod H;

X = view_xview[0] mod W;

 

for ( yy=view_yview[0]-Y; yy < view_yview[0]+view_hview[0]; yy += H )

for ( xx=view_xview[0]-X; xx < view_xview[0]+view_wview[0]; xx += W )

{

draw_background(background0,xx,yy);

}

Poza tym kod staje się wtedy czytelniejszy.

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ę...