Autor Wątek: Struktura rzeźby terenu  (Przeczytany 2665 razy)

Offline steckel

  • Użytkownik

# Listopad 08, 2010, 17:50:32
Witam!
Jak najoptymalniej zapisać rzeźbę terenu 2D (taką jak w Worms), aby później małym kosztem ją modyfikować? Myślałem o zwykłej tablicy dwuwymiarowej, ale wydaje mi się to słabe rozwiązanie.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline gmpro

  • Użytkownik

# Listopad 08, 2010, 17:55:02
A w jaki inny sposób? :/
Jeśli jest taki INNY sposób to też się dołączam do pytania..

używając booli albo charów to by niebyło takie złe.. a ewentualnie możesz ustalić większy rozmiar kafla :p np. 4x4px - tak chyba było w pierwszych wersjach wormsów.. a nie sorki tam po prostu wszystko miało pixele tej wielkości :p

Offline Anton Chigurh

  • Użytkownik

# Listopad 08, 2010, 18:17:32
Przychodzi mi do głowy jeszcze rozwiązanie w stylu quad tree tak, żeby duże jednolite prostokątne obszary przedstawiać jako duże prostokąty a tam, gdzie jest dziura, to dzielić na odpowiednio mniejsze. Nie wiem tylko jak rozwiązać kwestie robienia nowych dziur, bo trzebaby w momencie wybuchu zdefiniować obszar, który jest przez wybuch modyfikowany i podzielić go na prostokąty od nowa.

Jak o tym myślę pobieżnie, to nawet nie brzmi specjalnie trudno. Nie umiem jednak a priori stwierdzić, że będzie to na tyle wydajniejsze, żeby opłacało się to robić, jednak widziałem, że w 3d robi się takie rzeczy.

Edit:
Nawet w sumie nie trzeba robić drzewa, tylko kafle o zadanym rozmiarze i jeśli na obszarze jakiegoś powstanie dziura to w nim rysować bitmapę, a w przeciwnym razie pełen "teren" lub pełne "powietrze".

Alternatywnie wyczytałem gdzieś też, że można zapisać teren jako prostokątny klocek natomiast zniszczenia, jako listę "wyrytych" kształtów.
« Ostatnia zmiana: Listopad 08, 2010, 18:27:05 wysłana przez Anton Chigurh »

Offline mwojt

  • Użytkownik

# Listopad 08, 2010, 18:33:35
Chyba najlepiej zrobić mapę kafli jakieś 16x16 pikseli, kilka rodzajów kafli cały, pusty, skos 50/50, skos wypukły, skos wklęsły. Do tego funkcję getpixel, np. k=jaki_kafel_na_pozycji(x,y). getpixel(k, pozycja_x%16, pozycja_y%16);

Offline steckel

  • Użytkownik

# Listopad 08, 2010, 18:41:19
używając booli albo charów to by niebyło takie złe..
Jak będzie duża eksplozja to zmiana tych wszystkich pól będzie niewydajna.
Przychodzi mi do głowy jeszcze rozwiązanie w stylu quad tree tak, żeby duże jednolite prostokątne obszary przedstawiać jako duże prostokąty a tam, gdzie jest dziura, to dzielić na odpowiednio mniejsze. Nie wiem tylko jak rozwiązać kwestie robienia nowych dziur, bo trzebaby w momencie wybuchu zdefiniować obszar, który jest przez wybuch modyfikowany i podzielić go na prostokąty od nowa.
Dobry pomysł.
Cytuj
Nawet w sumie nie trzeba robić drzewa, tylko kafle o zadanym rozmiarze i jeśli na obszarze jakiegoś powstanie dziura to w nim rysować bitmapę, a w przeciwnym razie pełen "teren" lub pełne "powietrze".
A jak kolizje wykrywać GetPixel'em?
Cytuj
Alternatywnie wyczytałem gdzieś też, że można zapisać teren jako prostokątny klocek natomiast zniszczenia, jako listę "wyrytych" kształtów.
Ciężko by było tworzyć taki teren.
Chyba najlepiej zrobić mapę kafli jakieś 16x16 pikseli, kilka rodzajów kafli cały, pusty, skos 50/50, skos wypukły, skos wklęsły. Do tego funkcję getpixel, np. k=jaki_kafel_na_pozycji(x,y). getpixel(k, pozycja_x%16, pozycja_y%16);
Takie rzeźby będą brzydko wyglądać.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Listopad 08, 2010, 18:52:53
Cytuj
Jeśli jest taki INNY sposób to też się dołączam do pytania..
Jest masa innych sposobów - przykładowo można to przechowywać jako mesha z trójkątów i analitycznie wycinać w nich dziury (czy dowolne kształty).

Offline mwojt

  • Użytkownik

# Listopad 08, 2010, 19:43:27
Cytuj
A jak kolizje wykrywać GetPixel'em?
coś takiego:
char mapa[100][100];
char kafel1[16][16];
char kafel2[16][16];
int getkafel(pozycjax,pozycjay) {return mapa[pozycjax/16][pozycjay/16];}
nr=getkafel(x,y);
if (nr==1) pixel=kafel1[x%16][y%16]; // pobieramy pixel z kafla a nie rysowanego tła


Offline ConayR

  • Użytkownik

# Listopad 08, 2010, 19:49:02
Jak będzie duża eksplozja to zmiana tych wszystkich pól będzie niewydajna.
Że co? Grafika w full HD (1920x1080) 1Bpp to 2MB. Zmianę w budowie terenu liczy się raz na pocisk. Wpływ na wydajność praktycznie zerowy. A gdyby się uprzeć - można użyć bitmapy zamiast bajtmapy i zmniejszyć rozmiar do 256kB.

Offline steckel

  • Użytkownik

# Listopad 08, 2010, 19:56:06
Cytuj
A jak kolizje wykrywać GetPixel'em?
coś takiego:
char mapa[100][100];
char kafel1[16][16];
char kafel2[16][16];
int getkafel(pozycjax,pozycjay) {return mapa[pozycjax/16][pozycjay/16];}
nr=getkafel(x,y);
if (nr==1) pixel=kafel1[x%16][y%16]; // pobieramy pixel z kafla a nie rysowanego tła

Jednak znaki interpunkcyjne mają znaczenie... ;) Powinno być: "Jak kolizje wykrywać? GetPixel'em?"
Jak będzie duża eksplozja to zmiana tych wszystkich pól będzie niewydajna.
Że co? Grafika w full HD (1920x1080) 1Bpp to 2MB. Zmianę w budowie terenu liczy się raz na pocisk. Wpływ na wydajność praktycznie zerowy. A gdyby się uprzeć - można użyć bitmapy zamiast bajtmapy i zmniejszyć rozmiar do 256kB.
W sumie masz rację... Niedawno była olimpiada, więc się jakoś tak nauczyłem od razu odrzucać metody Brute-Force, ale jak widać niekiedy nie jest to konieczne :)

Offline t4fun

  • Użytkownik

# Listopad 08, 2010, 21:26:17
Można by po prostu wykorzystać kanał alfa tekstury która wyświetla ten teren.

Offline Anton Chigurh

  • Użytkownik

# Listopad 09, 2010, 10:34:44
Cytuj
Cytuj
Nawet w sumie nie trzeba robić drzewa, tylko kafle o zadanym rozmiarze i jeśli na obszarze jakiegoś powstanie dziura to w nim rysować bitmapę, a w przeciwnym razie pełen "teren" lub pełne "powietrze".
A jak kolizje wykrywać GetPixel'em?

Zrobiłbym abstrakcyjny interfejs na tę strukturę i miałby on funkcję get_pixel(int, int), ale w bebechach robiłby tak:

kolizja_lub_nie rzeźba_terenu::get_pixel(int x, int y) {
    kafel = znajdź_kafel_dla(x, y);
    switch(kafel.typ) {
    case pełen:
        return kolizja;

    case pusty:
        return brak_kolizji;

    case bitmapowy:
    default:
        return kafel.bitmapa.get_pixel(x, y);
        // Tutaj już prawdziwy get pixel, przy założeniu, że ta funkcja zwraca odpowiednio
        // kolizja lub brak_kolizji, gdy na bitmapie jest piksel lub nie
    }
}
« Ostatnia zmiana: Listopad 09, 2010, 10:36:56 wysłana przez Anton Chigurh »