Moja gra jest tworzona przy użyciu Phasera, ale samo pytanie jest niezależne od silnika.
W mojej grze mam kilka środowisk, głównie wielokątne obszary, do których mogą się poruszać postacie graczy. Na przykład lód, ogień, trucizna itp. Elementem graficznym tych obszarów jest sam obszar wielokąta wypełniony kolorem oraz cząstki odpowiedniego typu (w tym przykładzie odłamki lodu). Tak właśnie to obecnie wdrażam - z maską wielokątów pokrywającą kafelek wzorem cząstek:
Twarda krawędź wygląda źle. Chciałbym poprawić, wykonując dwie rzeczy: 1. Spraw, aby obszar wypełnienia wielokąta miał miękką krawędź i wtopił się w tło. 2. Niech niektóre odłamki wychodzą z obszaru wielokąta, aby nie zostały wycięte na środku i obszar nie miał linii prostej
na przykład (makieta):
Myślę, że 1 można osiągnąć poprzez rozmycie wielokąta, ale nie jestem pewien, jak poradzić sobie z 2.
Jak poszedłbyś na wdrożenie tego?
Odpowiedzi:
1.Jeśli chcesz czegoś zbliżonego do makiety, użyłbym cząstek (nie musi to być w pełni rozdmuchany układ cząstek).
Renderuj swoje cząstki w postaci wielokąta na RenderTexture. Upewnij się, że używasz mieszania dodatków do cząstek. Cząsteczki wewnątrz wielokąta płynnie się ze sobą łączą, a cząsteczki na zewnątrz zapewniają miękką krawędź, której chcesz. (Przykład efektu można obejrzeć w tym filmie na youtube: Wideo cząstek addycyjnych Teraz wyrenderuj RenderTexture na ekranie głównym i gotowe. RenderTexture jest konieczny, aby cząstki nie zlewały się z tłem.
Możesz spróbować umieścić trójkąty bezpośrednio na teksturze cząstek i zobaczyć, jak to działa. W przeciwnym razie renderuj je na „zupce cząsteczkowej” jako osobną warstwę.
Utworzono szybką makietę w zaktualizowanym jsfiddle, który wygląda tak: Zaktualizowaną wersję demo można znaleźć tutaj
2. Każda cząstka ma prędkość i pochodzenie. Kiedy twój gracz dotknie wielokąta, zmieniasz prędkość każdej cząstki proporcjonalnie do prędkości gracza. Im dalej cząstka znajduje się od gracza, tym mniej na nią wpływa prędkość gracza.
Wzór na obliczenie prędkości cząstek byłby mniej więcej taki:
Aby obliczyć położenie cząstki, umieść to w metodzie aktualizacji:
To powinno dać ci „płyn”, w którym każda cząstka obraca się wokół swojego źródła, gdy gracz miesza płyn. SpringConant zmienia, o ile cząstka odchyla się od swojego źródła, oraz tłumienie Czynnik, jak szybko cząstka zatrzymuje się. Być może będziesz musiał poprawić kod, ponieważ jest to zmodyfikowana wersja symulacji 1d, której używam w swojej grze.
Teraz z wersją demonstracyjną: Demo Ulepsz 3 stałe na górze, aż płyn zachowa się tak, jak chcesz.
źródło
Moje przemyślenia na temat tych dwóch punktów:
Możesz użyć rozmycia cieniowania, ale będzie to bardzo kosztowne. Zamiast tego narysowałbym dodatkową granicę trójkątów, które zanikają od półprzezroczystego w środku do przezroczystego na krawędziach, aby zasymulować „rozmycie”. Zrobiłem to w mojej grze i działa całkiem dobrze. Oto dwa zrzuty ekranu przypominającego tęczowy wzmacniacz w mojej grze.
Zewnętrzna granica ma gradient. W mojej sytuacji granica nie zaczyna się od tego samego zmętnienia co część wewnętrzna, ale jeśli ustawisz te nieprzezroczystości na równe, będziesz miał przyjemny efekt zanikania.
Zaprogramowałbym układ cząstek i sprawiłby, by cząstki podążały za wielokątem. Dzięki temu nie musisz się martwić o to, co stanie się na krawędziach. Dynamika układu cząstek zapewni, że cząstki będą wewnątrz wielokąta i równomiernie rozmieszczone. Możesz spróbować zmusić najbliższe cząstki do odpychania się, ale z dużą ilością „masy”, abyś miał bezwładność i wyglądał gładko. Aby to zrobić szybko, istnieją pewne możliwości, ale dużym problemem będzie złożoność czasowa wzajemnego popychania mechanizmu. Jeśli sprawisz, że każda cząstka pcha każdą inną cząsteczkę, będziesz miał O (n ^ 2), co nie jest dobre, jeśli masz na przykład 100 cząstek w twoim systemie. Dobrym poczytaniem o tym, jak możesz to zoptymalizować, jest ta prezentacja PixelJunk:http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf
Prostszym podejściem byłoby połączenie każdej cząstki z trzema lub czterema innymi cząsteczkami podczas konstruowania układu cząstek. Teraz każda cząstka będzie musiała przepchnąć tylko cztery inne cząstki, z którymi jest połączona. Takie podejście uniemożliwia jednak zawirowania w układzie cząstek. Nie wydaje się to jednak problemem, ponieważ twoja obecna sytuacja używa statycznej tekstury. Podejście to będzie O (n), co jest świetne.
źródło
Pomysł, który miałem podczas czytania twojego postu był następujący:
• zbuduj zestaw kafelków, których będziesz używać w swoich obszarach.
• renderuj wielokąt powierzchniowy na małym tymczasowym kanwie w rozdzielczości kafelków (np. Jeśli kafelki mają format 16X16, renderuj w niższej rozdzielczości (16X, 16X)).
• użyj tego tymczasowego płótna, aby zdecydować, czy renderować kafelki, czy też nie na głównym kanwie:
jeśli punkt jest ustawiony na kanwie o niskiej rozdzielczości, narysuj „losową” płytkę na głównym kanwie. jeśli punkt jest tylko sąsiadem punktu ustawienia, narysuj „losową” płytkę o mniejszym stopniu krycia (w celu przejścia) na głównym obszarze roboczym.
Bałem się, że obniżenie rozdzielczości spowoduje efekt blokowy, ale nawet przy płytkach 20X20 wygląda całkiem dobrze:
Kroki w tym celu: weź swój wielokąt:
Narysuj wielokąt w rozdzielczości kafelków: (!! tak, to czerwona rzecz w centrum handlowym).
Następnie użyj imageData płótna o niskiej rozdzielczości, aby zdecydować, czy narysować płytkę lub notatkę.
Jeśli piksel jest ustawiony na kanwie o niskiej rozdzielczości, oznacza to, że powinniśmy narysować kafelek: wybierz „losowy” indeks kafelków, aby wybrać kafelek do narysowania. Ten losowy indeks powinien być zawsze taki sam dla danego obszaru / płytki.
Jeśli punkt jest pusty, ale znajduje się obok wypełnionego punktu, narysuj również płytkę, ale z półprzezroczystością.
Narysujmy więc płytki:
W przypadku wielokąta rysuję tylko kilkukrotnie wielokąt, zmniejszając go i zwiększając krycie przy każdym losowaniu (można również użyć funkcji globalCompositeOperation „jaśniej”).
Po dodaniu wszystkiego daje:
skrzypce jest tutaj:
http://jsfiddle.net/gamealchemist/T7b4Y/
daj mi znać, jeśli to pomoże.
źródło
Tylko pomysł:
W kawałku „kawałki” mają maksymalnie około 80 pikseli szerokości. Sugerowałbym, tworząc 2 obszary. Rysujesz oryginalny wielokąt i wykonujesz jego makietę w odległości około 80 pikseli od każdej krawędzi. Następnie rysujesz płytki w większym wielokącie.
Następnie wszystkie „kawałki”, które mają piksel poza wewnętrznym wielokątem i bez przecięcia z wewnętrznym wielokątem, możesz zalać je wypełnieniem przezroczystością.
To jest bardzo wysoki poziom, ale pomyślałem, że podzielę się nim z tobą. Jest tu wiele szczegółów do ustalenia.
Surowy obraz do zademonstrowania:
Gdyby wewnętrzny czarny wielokąt był oryginałem, skasowałbyś wszystkie wielokąty czerwoną kropką.
źródło