Obecnie pracuję nad układem cząstek w naszej grze i opracowuję kształty emitera.
Mój jednolity losowy rozkład wzdłuż linii lub prostokąta działa dobrze - nie ma problemu.
Ale teraz chciałbym mieć coś w rodzaju 1 wymiarowego gradientu w tym rozkładzie. Oznaczałoby to na przykład, że niższe wartości są częstsze niż wyższe wartości.
Nie wiem, jakie byłyby odpowiednie matematyczne terminy dla tego problemu, więc moje umiejętności wyszukiwania są w tym przypadku raczej bezużyteczne. Potrzebuję czegoś, co jest obliczeniowo proste, ponieważ system cząstek musi być wydajny.
mathematics
random
distribution
didito
źródło
źródło
Odpowiedzi:
Spójrz na to zdjęcie:
Pokazuje proces mapowania (losowej) wartości na krzywą. Załóżmy, że generujesz równomiernie rozłożoną losową wartość X, od 0 do 1. Odwzorowując tę wartość na krzywą - lub innymi słowy, używając f (X) zamiast X - możesz przekrzywić rozkład w dowolny sposób .
Na tym zdjęciu pierwsza krzywa zwiększa prawdopodobieństwo, że wyższe wartości; drugi zwiększa prawdopodobieństwo, że niższe wartości; a trzeci sprawia, że wartości skupiają się w środku. Dokładna formuła krzywej nie jest tak naprawdę ważna i można ją wybrać według własnego uznania.
Na przykład pierwsza krzywa wygląda trochę jak pierwiastek kwadratowy, a druga - kwadrat. Trzeci jest trochę jak kostka, tylko przetłumaczony. Jeśli uważasz, że pierwiastek kwadratowy jest zbyt wolny, pierwsza krzywa również wygląda jak f (X) = 1- (1-X) ^ 2 - odwrócenie kwadratu. Lub hiperbola: f (X) = 2X / (1 + X).
Jak pokazuje czwarta krzywa, możesz po prostu użyć wstępnie obliczonej tabeli odnośników. Wygląda brzydko jak krzywa, ale prawdopodobnie będzie wystarczająco dobry dla układu cząstek.
Ta ogólna technika jest bardzo prosta i potężna. Niezależnie od potrzebnego rozkładu wyobraź sobie odwzorowanie krzywej, a szybko opracujesz formułę. Lub, jeśli twój silnik ma edytor, po prostu stwórz edytor wizualny dla krzywej!
źródło
Dłuższe wyjaśnienie:
Jeśli masz pożądany rozkład prawdopodobieństwa, taki jak żądany gradient @didito, możesz opisać to jako funkcję. Powiedzmy, że chcesz rozkładu trójkątnego, w którym prawdopodobieństwo przy 0 wynosi 0,0, i chcesz wybrać liczbę losową od 0 do 1. Możemy zapisać ją jako y = x.
Następnym krokiem jest obliczenie całki tej funkcji. W tym przypadku jest to . Ocena od 0 do 1, to jest ½. Ma to sens - jest to trójkąt o podstawie 1 i wysokości 1, więc jego powierzchnia wynosi ½.∫x = 1x2)
Następnie wybierasz losowo punkt równomiernie od 0 do obszaru (½ w naszym przykładzie). Nazwijmy to z. (Wybieramy równomiernie z rozkładu skumulowanego ).
Następnym krokiem jest cofnięcie się, aby dowiedzieć się, która wartość x (nazwiemy to x̂) odpowiada obszarowi z. Szukamy , ocenianego od 0 do x̂, równego z. Kiedy rozwiązujesz dla , otrzymujesz .∫x=1x2 1x̂ 2=z x̂ =2z−−√
W tym przykładzie wybierasz z od 0 do ½, a następnie pożądaną liczbą losową jest . Uproszczony, możesz napisać go jako - dokładnie to, co zalecił eBiznes.2z−−√ rand(0,1)−−−−−−−−√
źródło
sqrt(random())
tworzyłem całe życie, ale doszedłem do niego empirycznie. Próbowanie powiązania losowej liczby z krzywą i zadziałało. Teraz, gdy jestem trochę bardziej wykwalifikowany w matematyce, wiedza o tym, dlaczego to działa, jest bardzo cenna!Prawdopodobnie uzyskasz dokładne przybliżenie tego, co chcesz, stosując system wykładniczy.
Ustaw x na podstawie czegoś takiego jak 1- (wartość rnd ^) (Zakładając, że rnd ma wartość od 0 do 1), a otrzymasz kilka różnych zachowań skośnych od lewej do prawej w zależności od tego, czego używasz. Wyższa wartość zapewni bardziej wypaczony rozkład
Możesz użyć internetowego narzędzia do tworzenia wykresów, aby uzyskać ogólne pomysły na zachowania, które dają różne równania przed ich umieszczeniem, lub możesz po prostu bawić się równaniami bezpośrednio w układzie cząsteczek, w zależności od tego, jaki styl bardziej odpowiada Twoim upodobaniom.
EDYTOWAĆ
W przypadku systemu cząstek, w którym czas pracy procesora na cząsteczkę jest bardzo ważny, użycie Math.Pow (lub odpowiednika językowego) może bezpośrednio doprowadzić do spadku wydajności. Jeśli wymagana jest większa wydajność, a wartość nie jest zmieniana w czasie wykonywania, rozważ przejście na równoważną funkcję, taką jak x * x zamiast x ^ 2.
(Wykładniki ułamkowe mogą być większym problemem, ale ktoś z silniejszym zapleczem matematycznym niż ja prawdopodobnie mógłby wymyślić dobry sposób na utworzenie funkcji aproksymacji)
źródło
value
jest to Beta (wartość 1).Termin, którego szukasz, to
Weighted Random Numbers
większość algorytmów, które widziałem, używają funkcji trig, ale myślę, że wymyśliłem sposób, który będzie skuteczny:Utwórz tabelę / tablicę / listę (cokolwiek), która zawiera wartość mnożnika dla funkcji losowej. Wypełnij go ręcznie lub programowo ...
... następnie Pomnóż
random
przez losowo wybranyrandMulti
i na koniec przez maksymalną wartość rozkładu ...Wierzę, że będzie to znacznie szybsze niż korzystanie z
sqrt
innych bardziej złożonych obliczeniowo funkcji i pozwoli na bardziej niestandardowe wzorce grupowania.źródło
Myślę, że to, o co prosisz, to rozkład osiągnięty za pomocą funkcji pierwiastka kwadratowego.
Zapewni to rozkład w polu pojedynczego wymiaru, w
[0, 1]
którym prawdopodobieństwo położenia jest równoważne z tym położeniem, tj. „Rozkład trójkątny”.Alternatywne generowanie bez kwadratów:
Pierwiastek kwadratowy w optymalnej implementacji to tylko kilka poleceń mnożenia i sumowania bez rozgałęzień. (Patrz: http://en.wikipedia.org/wiki/Fast_inverse_square_root ). Która z tych dwóch funkcji jest szybsza, może się różnić w zależności od platformy i generatora losowego. Na przykład na platformie x86 zajęłoby tylko kilka nieprzewidywalnych gałęzi w generatorze losowym, aby spowolnić drugą metodę.
źródło
Wystarczy użyć dystrybucji Beta:
itp.
Te dwa parametry kształtu nie muszą być liczbami całkowitymi.
źródło
uniform_generator()
połączenie nagsl_ran_beta(rng, a, b)
. Zobacz tutaj: gnu.org/software/gsl/manual/html_node/...Jeszcze prościej, w zależności od prędkości generatora losowego, możesz po prostu wygenerować dwie wartości i uśrednić je.
Albo, jeszcze bardziej proste, gdzie X jest wynikiem RNG, pierwszy
double y = double(1/x);
,x = y*[maximum return value of rng];
. To zrównoważy liczby wykładniczo do niższych liczb.Generuj i uśredniaj więcej wartości, aby zwiększyć prawdopodobieństwo zbliżenia wartości do centrum.
Oczywiście działa to tylko w przypadku standardowych rozkładów krzywych dzwonkowych lub ich „złożonych” wersji *, ale w przypadku szybkiego generatora może być szybsze i prostsze niż używanie różnych funkcji matematycznych, takich jak sqrt.
Możesz znaleźć wszelkiego rodzaju badania tego dla krzywych dzwonka do kości. W rzeczywistości Anydice.com to dobra strona, która generuje wykresy dla różnych metod rzucania kostką. Chociaż używasz RNG, założenie jest takie samo, jak wyniki. Jest to więc dobre miejsce, aby zobaczyć rozkład, zanim jeszcze go zakodujesz.
* Ponadto można „złożyć” rozkład wyników wzdłuż osi, biorąc oś i odejmując uśredniony wynik, a następnie dodając oś. Na przykład chcesz, aby niższe wartości były bardziej powszechne, i powiedzmy, że chcesz, aby 15 było wartością minimalną, a 35 wartością maksymalną, w zakresie 20. Tak więc generujesz i uśredniasz razem dwie wartości o zakresie 20 ( dwukrotność żądanego zakresu), co da krzywą dzwonkową wyśrodkowaną na 20 (odejmujemy pięć na końcu, aby zmienić zakres z 20 na 40, na 15 na 35). Weź wygenerowane liczby X i Y.
Ostateczna liczba,
Jeśli zero jest twoim minimum, a nawet lepiej, zrób to zamiast tego,
źródło