Pygame water ripple effect

Wygooglowałem, ale nie ma gotowych skryptów - w przeciwieństwie do tego samego efektu na Flashu. Sprawdziłem algorytm na efekt wody wyjaśnił, a także przetestowałem implementację szumu Perlina , który zapewnia dobrą symulację końca fal na płaskiej powierzchni. Szukam tej samej implementacji, która znajduje się w kilku efektach Flash, opartych na akcjach mouseover/hover. To jest interaktywna biblioteka podłogowa, a ja chętnie się wyprowadzę od Flasha w tej sprawie, szczególnie, aby uniknąć takiej łatwej inżynierii wstecznej kodu - i tak, Wiem, że może po prostu użyć jakiegoś gotowego kodu flash, ale użyłbym go tylko w ostateczności.

Czy ktoś widział odpowiednią implementację tego efektu dla Pygame(używając OpenGL czy nie)?

Edytuj: Czy ktoś może dostarczyć odpowiednią implementację tego efektu używając OpenCV/OpenGL i Pygame?

Winowajcą jest tutaj interfejs (code) do przekazania lista wartości, które będą wysyłane z zewnętrznego interpretera (tracker - ale nie TUIO) przez Python. Próbowałem przez kilka prostych dni, ale Pygame nie jest w stanie wygenerować niczego tak szybko, jak zwykły kod C/C++ (używany do shaderów w OpenGL), a moja znajomość C/C++ jest zerowa. Więc celem jest przynajmniej to, że pochodzi z kodu Pythona.

Dobrym przykładem, różniącym się od efektu Flasha, ale wciąż dobrym jest Symulacja wody za pomocą apletu Java .

(bounty pokazuje odpowiedzi nie mają wystarczająco dużo szczegółów, ponieważ był to najbliższy do "OP jest niezdolny do tworzenia kodu, który chce, ponieważ brakuje mu podstawowych umiejętności i ta odpowiedź będzie prawdopodobnie przydatna dla kilku osób").

Author: leon, 0000-00-00

2 answers

Po odrabianiu lekcji (a. k. a. research) i próbie bezpośredniej konwersji kodu Java odniesienia zamieszczonego na pytanie do Pythona, i mając bardzo, bardzo smutne doświadczenie podczas próby Python / Numpy aktualizować ogromną tablicę kolorów pikseli w oparciu o ich pozycje dla rippling efektu ripple (przepraszam, mój pierwszy język nie jest angielski), w ten sposób parsowanie kilku (X,y) pozycji dla każdego przebiegu obliczeń efektu i blitting że na wyświetlonej powierzchni na ekranie (surfarray wynika), doszedłem do wniosku - który jest poparty przez innych komentatorów - że Pygame po prostu nie będzie być wystarczająco potężny, aby faktycznie przemierzać całą tablicę pikseli i zastosować wyniki obliczeń na każdym pikselu na ekranie z minimalną szybkością 24 fps (dla mniej niż przeciętne doświadczenie).

Cytując samego twórcę Last Light Productions i byłego projektu Geometrian , Iana Malleta:

PyGame nie jest taki dobry do pchania pikseli. Nic nie jest, poza GPU.

Wyszukiwanie okazało się być poszukiwaniem Alkahest - czegoś, czego nigdy nie można znaleźć - i opierając się na tej samej idei falowania obrazów, ale tym razem za pomocą przezroczystości do przejrzeć przezkilka warstw powierzchni Pygame, zamieściłem pytanie Pygame circular cropping/masks na gamedevie. wybrana odpowiedź faktycznie potwierdza fakt, że już się obawiałem ten Pygame nigdy nie byłby wystarczająco macho do tej roboty.

Dzień później wróciłem do moich wcześniejszych pomysłów na rozwój i natknąłem się na Ogre3D . Okazuje się, że (1) Ogre3D i sample są open-source i (2) jednym z przykładów jest trójwymiarowy model wody, który współdziała z poruszającym się obiektem, dokładnie to samo, co próbowałem osiągnąć w 2-D, ale w znacznie bardziej profesjonalny sposób.

Ponieważ moja wiedza w C / C++ jest zerowa, postanowiłem zapytać o jak dostosować Demo ogre3d water aby zobaczyć, gdzie zacząć szukać, a jedna z odpowiedzi wskazała mi oprogramowanie z Touchscape, w którym znajduje się SDK(zobacz ta ODPOWIEDŹ ).

Ogre3D Water ripple effect, OpenGL (które może opcjonalnie używać w oparciu o sprzęt), silnik gry i wrappery Pythona poprzez Python-Ogre - więc moja odpowiedź na moje własne pytanie,

czy ktoś może zapewnić odpowiednią realizację tego efektu używając OpenCV/OpenGL i Pygame?

Jest w zasadzie

Tak. Sprawdź demo wody Ogre3D, dostarczone wraz z SDK - i podłącz go do Pythona przez Python-Ogre .

 8
Author: leon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:18:41

Poniższe użycie numpy może Ci pomóc. Powinien być wystarczająco szybki, chociaż możesz uzyskać znacznie szybciej nawet w Pythonie (spójrz tutaj, aby zobaczyć, jak http://www.scipy.org/PerformancePython).

Przy okazji jest kilka wad w opisywanej metodzie:

  1. nie możesz kontrolować prędkości fal-aby to zrobić, musisz zmodyfikować równania używane w funkcji ripple (jeśli dowiesz się, jak to odnosi się do równania falowego http://en.wikipedia.org/wiki/Wave_equation then you are done)
  2. "głębokość ""basenu" jest stała (i prawdopodobnie zbyt płytka). Dodałem parametr głębokości, aby powiększyć efekt
  3. artykuł czyta przesunięcia pikseli całkowitych - uzyskałbyś o wiele lepszy wynik z wartości interpolowanych (myślę, że możesz to zrobić z opengl, ale moja wiedza w tej dziedzinie jest zerowa)

Kod:

import numpy

def ripple(w1, w2, damp, n = 1):
    for _ in xrange(n):
        w2 *= -2
        w2[1:-1,1:-1] += w1[0:-2, 1: -1]
        w2[1:-1,1:-1] += w1[2:  , 1: -1]
        w2[1:-1,1:-1] += w1[1:-1, 0: -2]
        w2[1:-1,1:-1] += w1[1:-1, 2:   ]
        w2 *= .5 * (1. - 1./damp)
        w1, w2 = w2, w1

def refract(x, y, w, rindex, depth = 10):
    sx = x[0,1] - x[0,0]
    sy = y[1,0] - y[0,0]

    dw_dx = (w[2: ,1:-1] - w[:-2,1:-1]) / sx * .5
    dw_dy = (w[1:-1,2: ] - w[1:-1,:-2]) / sy * .5

    xang = numpy.arctan(dw_dx)
    xrefract = numpy.arcsin(sin(xang) / rindex)
    dx = numpy.tan(xrefract) * dw_dx * depth

    yang = numpy.arctan(dw_dy)
    yrefract = numpy.arcsin(sin(yang) / rindex)
    dy = numpy.tan(yrefract) * dw_dy * depth

    dx *= numpy.sign(dw_dx)
    dy *= numpy.sign(dw_dy)

    xmin = x[0,0]
    xmax = x[0,-1]
    x[1:-1,1:-1] += dx
    x[:,:] = numpy.where(x < xmin, xmin, x)
    x[:,:] = numpy.where(x > xmax, xmax, x)

    ymin = y[0,0]
    ymax = y[-1,0]
    y[1:-1,1:-1] += dy
    y[:,:] = numpy.where(y < ymin, ymin, y)
    y[:,:] = numpy.where(y > ymax, ymax, y)

X I y powinny być siatkami z numpy.meshgrid call: oto przykład sposób użycia:

    x,y = meshgrid(x,y)
    w = 10 * exp(- (x*x + y*y))
    w1 = w.copy()
    x1,y1 = meshgrid(r_[0:len(x):1.0], r_[0:len(y):1.0])
    ripple(w, w1, 16) # w1 will be modified
    refract(x1, y1, w1, rindex=2, depth=10) # x1 and y1 will be modified
    numpy.around(x1, out=x1) # but you will get better results with interpolate
    numpy.around(y1, out=y1) # 
 5
Author: spam_eggs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-08 12:46:41