Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming

Zrób Splash z Dynamicznymi 2D Efektami Wody

by
Difficulty:IntermediateLength:LongLanguages:

Polish (Polski) translation by Władysław Łucyszyn (you can also view the original English article)

Sploosh! Wtym samouczku pokażę Wam, jak korzystać z prostej matematyki,fizyki i efektów cząsteczkowych, aby symulować świetnie wyglądające wodne fale i kropelki 2D.



Uwaga:Chociaż ten samouczek jest napisany przy użyciu C # i XNA,powinieneś być w stanie używać tych samych technik i koncepcji wprawie każdym środowisku programowania gier.


Końcowy podgląd wyników

Jeśli masz XNA, możesz pobrać pliki źródłowe i samemu skompilować demo. Wprzeciwnym razie sprawdź film demonstracyjny poniżej:

Istnieją dwie w większości niezależne części do symulacji wody. Najpierw zrobimy fale za pomocą modelu sprężynowego. Podrugie, użyjemy efektów cząsteczkowych, aby dodać plamy.


Tworzenie fal

Aby stworzyć fale, modelujemy powierzchnię wody jako serię pionowych sprężyn, jak pokazano na tym schemacie:

To pozwoli falom podskakiwać w górę iw dół. Następnie doprowadzimy cząstki wody do przyciągania sąsiednich cząstek, aby umożliwić rozprzestrzenienie się fal.

Springs and Hooke's Law

Wielką zaletą sprężyn jest to, że można je łatwo symulować. Sprężyny mają określoną naturalną długość; jeśli rozciągniesz lub ściśnie sprężynę, spróbujesz powrócić do tej naturalnej długości.

Siła dostarczona przez sprężynę jest podana przez prawo Hooke'a:

\[
F = -kx
\]

F jest siłą wytwarzaną przez sprężynę, k jest stałą sprężyny, a x jest przesunięciem sprężyny od jej naturalnej długości. Znak ujemny wskazuje, że siła jest w przeciwnym kierunku, w którym sprężyna jest przemieszczana; jeśli popchniesz sprężynę, popchnie ją z powrotem i na odwrót.

Stała sprężyny, k, określa sztywność sprężyny.

Aby symulować sprężyny, musimy dowiedzieć się, jak przesuwać cząstki w oparciu o prawo Hooke'a. Aby to zrobić, potrzebujemy jeszcze kilku formuł z fizyki.  Po pierwsze, drugie prawo ruchu Newtona:

\[
F = ma
м

Tutaj F jest siłą, m jest masą, a a jest przyspieszeniem. Oznacza to, że im silniejsza siła popycha obiekt, a im lżejszy obiekt, tym bardziej przyspiesza.

ołączenie tych dwóch formuł i rearanżacji daje nam:

\[
a = -\frac{k}{m} x
\]

To daje nam przyspieszenie dla naszych cząstek. Zakładamy, że wszystkie nasze cząstki będą miały tę samą masę, więc możemy połączyć k/m w jedną stałą.

Aby określić pozycję od przyspieszenia, musimy wykonać integrację numeryczną. Użyjemy najprostszej formy integracji numerycznej - każda klatka po prostu wykonuje następujące czynności:

Nazywa się to metodą Eulera. Nie jest to najdokładniejszy typ numerycznej integracji, ale jest szybki, prosty i adekwatny do naszych celów.

Składając to wszystko razem, nasze cząstki powierzchni wody wykonają następujące po sobie klatki:

Tutaj TargetHeight jest naturalną pozycją wierzchołka sprężyny, gdy nie jest ani rozciągnięta, ani skompresowana. Powinieneś ustawić tę wartość w miejscu, w którym chcesz mieć powierzchnię wody. Dla wersji demonstracyjnej ustawiłem go w połowie ekranu, na 240 pikseli.

Napięcie i tłumienie

Wspomniałem wcześniej, że stała sprężyny, k, kontroluje sztywność sprężyny. Możesz dostosować tę wartość, aby zmienić właściwości wody Niska stała sprężyny spowoduje poluzowanie sprężyn.  Oznacza to, że siła spowoduje duże fale, które oscylują powoli.  Odwrotnie, wysoka stała sprężyny zwiększy napięcie sprężyny. Siły stworzą małe fale, które szybko oscylują. Wysoka stała sprężyna sprawi, że woda będzie wyglądać bardziej jak Jello.

Słowo ostrzeżenia: nie ustawiaj stałej sprężyny zbyt wysoko. Bardzo sztywne sprężyny nakładają bardzo silne siły, które zmieniają się bardzo w bardzo krótkim czasie Nie gra to dobrze z integracją numeryczną, która symuluje sprężyny jako serię dyskretnych skoków w regularnych odstępach czasu. Bardzo sztywna sprężyna może mieć nawet okres oscylacji, który jest krótszy niż twój czas. Co gorsza, metoda integracji Eulera ma tendencję do uzyskiwania energii, ponieważ symulacja staje się mniej dokładna, powodując eksplozję sztywnych sprężyn.

Jak dotąd mamy problem z naszym modelem sprężynowym. Gdy wiosna zacznie się oscylować, nigdy się nie zatrzyma.  Aby rozwiązać ten problem musimy zastosować niektóre tłumienia. Chodzi o to, aby zastosować siłę w przeciwnym kierunku, który nas Wiosna jest w ruchu w celu spowolnić go. To wymaga niewielkiej korekty do naszego wzoru wiosna:

\[
a = -\frac{k}{m} x - dv
\]

Tutaj v jest prędkością, a d jest czynnikiem tłumiącym - kolejna stała, którą można poprawić, aby dostosować odczucie wody. Powinien być dość mały, jeśli chcesz, aby fale się oscylowały. Wersja demonstracyjna używa współczynnika tłumienia 0,025. Wysoki współczynnik tłumienia spowoduje, że woda będzie wyglądać gęsto jak melasa, a niska wartość pozwoli falom na długi czas oscylować.

Tworzenie fal propagujących

Teraz, kiedy możemy zrobić wiosnę, użyjmy ich do modelowania wody. Jak pokazano na pierwszym schemacie, modelujemy wodę za pomocą serii równoległych, pionowych sprężyn. Oczywiście, jeśli wszystkie sprężyny są niezależne, fale nigdy się nie rozprzestrzenią, tak jak robią to prawdziwe fale.

Najpierw pokażę kod, a potem przejdę dalej:

Ten kod byłby nazywany każdą klatką z metody Update (). Tutaj sprężyny to zestaw sprężyn ułożonych od lewej do prawej. leftDeltas to zestaw pływaków, który przechowuje różnicę wysokości między każdą sprężyną i jej lewym sąsiadem. rightDeltas jest odpowiednikiem dla właściwych sąsiadów. Przechowujemy wszystkie te różnice wysokości w tablicach, ponieważ ostatnie dwie instrukcje if modyfikują wysokości sprężyn. Musimy zmierzyć różnice wysokości zanim jakiekolwiek wysokości zostaną zmodyfikowane.

Kod zaczyna się od uruchomienia Prawa Hooke'a na każdą sprężynę, jak opisano wcześniej. Następnie analizuje różnicę wysokości między każdą sprężyną i jej sąsiadami, a każda sprężyna przyciąga do siebie sąsiednie sprężyny, zmieniając położenie i prędkość sąsiadów. Krok ciągnięcia sąsiada jest powtarzany osiem razy, aby fale mogły się szybciej rozprzestrzeniać.

Jest jeszcze jedna doskonała wartość o nazwie Spread. Kontroluje szybkość rozprzestrzeniania się fal. Może przyjmować wartości z zakresu od 0 do 0,5, a większe wartości powodują, że fale rozprzestrzeniają się szybciej

Aby rozpocząć ruch fal, dodamy prostą metodę o nazwie Splash().

Za każdym razem, gdy chcesz tworzyć fale, wywołaj Splash (). Parametr index określa, z której wiosny powinien pochodzić splash, a parametr prędkości określa, jak duże będą fale.

Wykonanie

Będziemy używać klasy XNA PrimitiveBatch z XNA PrimitivesSample. Klasa PrimitiveBatch pomaga nam rysować linie i trójkąty bezpośrednio z GPU. Używasz go tak:

Należy pamiętać, że domyślnie należy określić wierzchołki trójkąta w kolejności zgodnej z ruchem wskazówek zegara Jeśli dodasz je w kolejności przeciwnej do ruchu wskazówek zegara, trójkąt zostanie poddany ubojowi, a Ty go nie zobaczysz.

Nie trzeba mieć sprężyny dla każdego piksela szerokości. W wersji demonstracyjnej wykorzystałem 201 sprężyn rozmieszczonych w oknie o szerokości 800 pikseli. Daje to dokładnie 4 piksele między każdą sprężyną, przy czym pierwsza sprężyna ma 0, a ostatnia 800 pikseli. Prawdopodobnie możesz użyć jeszcze mniej sprężyn i nadal mieć gładką wodę.

Chcemy narysować cienkie, wysokie trapezoidy, które rozciągają się od dolnej części ekranu do powierzchni wody i łączą sprężyny, jak pokazano na tym schemacie:

Ponieważ karty graficzne nie pobierają bezpośrednio trapezów, musimy narysować każdy trapez jako dwa trójkąty. Aby wyglądać nieco ładniej, sprawimy, że woda będzie ciemniejsza, gdy się pogłębi, barwiąc dolne wierzchołki ciemnoniebieskie. GPU automatycznie interpoluje kolory między wierzchołkami.

Oto wynik:


Robienie plam

Fale wyglądają całkiem nieźle, ale chciałbym zobaczyć plusk, gdy skała uderzy w wodę. Efekty cząsteczek są do tego idealne.

Efekty cząstek

Efekt cząsteczkowy wykorzystuje dużą liczbę małych cząstek, aby uzyskać pewien efekt wizualny. Czasami są używane do takich rzeczy, jak dym czy iskry. Zamierzamy użyć cząstek do kropel wody w rozpryskach.

Pierwszą rzeczą, której potrzebujemy, jest nasza klasa cząstek:

Ta klasa ma właściwości, które może posiadać cząstka. Następnie tworzymy listę cząstek. Każda klatka, musimy zaktualizować i narysować cząstki

Każda klatka, musimy zaktualizować i narysować cząstki

Aktualizujemy cząstki pod wpływem grawitacji i ustawiamy kierunek cząstek tak, aby pasowały do ​​kierunku, w którym zmierza Następnie pozbywamy się cząstek, które są poza ekranem lub pod wodą, kopiując wszystkie cząsteczki, które chcemy zachować na nową listę i przypisywanie jej do cząstek. Następnie narysujemy cząstki.

Poniżej znajduje się faktura, której użyłem dla cząstek.

eraz, gdy tworzymy splash, tworzymy wiązkę cząstek.

Możesz wywołać tę metodę z metody Splash () używanej do generowania fal. Szybkość parametru to szybkość uderzenia skały w wodę. Jeśli kamień porusza się szybciej, zrobimy większe plamy.

GetRandomVector2(40) zwraca wektor o losowym kierunku i losowej długości od 0 do 40. Chcemy dodać trochę losowości do pozycji, aby cząsteczki nie pojawiały się w jednym punkcie. FromPolar () zwraca wektor2 o danym kierunku i długości.

Oto wynik:

Używanie Metaballs jako cząstek

Nasze plamy wyglądają całkiem przyzwoicie, a niektóre świetne gry, takie jak World of Goo, mają plamy cząstek, które wyglądają podobnie do naszych. Jednak pokażę wam technikę, która sprawi, że plamy będą wyglądać bardziej płynnie. Technika ta wykorzystuje metabolity, organiczne bloby, o których wcześniej pisałem samouczek. Jeśli interesują Cię szczegóły dotyczące metaball i ich działania, przeczytaj ten samouczek. Jeśli chcesz wiedzieć, jak zastosować je do naszych rozprysków, czytaj dalej.

Metaballe wyglądają jak ciecze w sposób, w jaki łączą się ze sobą, dzięki czemu dobrze pasują do naszych płynnych rozprysków. Aby utworzyć metaball, będziemy musieli dodać nowe zmienne klasy:

Które zainicjujemy tak:

Następnie narysujemy metaball:

Efekt metaboliczny zależy od tego, czy tekstura cząstki zanika, gdy oddalamy się od centrum. Oto, co użyłem, ustawić na czarnym tle, aby było widoczne

Oto, jak to wygląda:

Kropelki wody łączą się teraz, gdy są blisko. Jednak nie łączą się one z powierzchnią wody.  Możemy o naprawić, dodając gradient do powierzchni wody. Który sprawia, że ​​stopniowo zanika i oddaje go naszemu celowi metalizacji.

Dodaj następujący kod do powyższej metody przed wierszem GraphicsDevice.SetRendertarget (null):

Teraz cząstki zleją się z powierzchnią wody.

Dodanie efektu Beveling

Cząsteczki wody wyglądają nieco płasko i dobrze byłoby dać im cień Najlepiej byłoby zrobić to w module cieniującym. Jednak ze względu na prostotę tego samouczka, zastosujemy szybką i prostą sztuczkę: po prostu rysujemy trzykrotnie cząstki z różnymi zabarwieniami i przesunięciami, jak pokazano na poniższym schemacie.

Aby to zrobić, chcemy przechwycić cząstki metaball w nowym celu renderowania. Następnie narysujemy ten cel renderowania raz dla każdego odcienia

Najpierw zadeklaruj nowy RenderTarget2D, tak jak zrobiliśmy to dla metaballów:

Następnie, zamiast rysować metaballTarget bezpośrednio do backbuffera, chcemy go narysować na particleTarget Aby to zrobić, przejdź do metody, w której narysuj metrum i po prostu zmień te linie

...do:

Następnie użyj następującego kodu, aby narysować trzykrotnie cząsteczki z różnymi odcieniami i przesunięciami:


Wniosek

To wszystko w przypadku podstawowej wody 2D. Do wersji demo dodałem kamień, który można wpaść do wody. Rysuję wodę z pewną przezroczystością na górze skały, aby wyglądała jak pod wodą i spowolniam ją, gdy jest pod wodą z powodu odporności na wodę.

Aby wyglądało na nieco ładniejsze, poszedłem na opengameart.org i znalazłem obraz dla rocka i tła nieba. Możesz znaleźć kamień i niebo na http://opengameart.org/content/rocks i opengameart.org/content/sky-backdrop odpowiednio.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.