32 votos

Efecto de ondulación del agua de Pygame

He buscado en Google pero no existen secuencias de comandos - en comparación con el mismo efecto en Flash. He comprobado que el algoritmo sobre El Efecto del Agua Explicado y probado también una implementación del Ruido Perlin, que proporciona una buena simulación de la final de ondas sobre una superficie plana. Yo estoy buscando la misma implementación que se encuentran en varios Efectos de Flash, basado en mouseover/hover acciones. Este es targetting interactivo piso de la biblioteca, y me gustaría disfrutar de moverse lejos de la Flash para este asunto, particularmente para evitar tales fácil de ingeniería inversa del código - y sí, sé que sólo podría utilizar algunos de los ready-made de código flash, pero yo sólo lo utilice como último recurso.

Alguien ha visto a una adecuada implementación de este efecto para Pygame (usando OpenGL o no)?

EDIT: ¿alguien Puede proporcionar una adecuada implementación de este efecto mediante OpenCV/OpenGL y Pygame?

El culpable aquí es el código de la interfaz para pasar una lista de valores que van a ser enviados desde un intérprete (tracker - no TUIO aunque) a través de Python. He intentado durante algunos días seguidos, pero Pygame no es capaz de generar nada tan rápido como pura C/C++ de código (como el utilizado para los shaders de OpenGL), y mis conocimientos de C/C++ es nulo. Así que el objetivo es que al menos tienen que venir de código de Python.

Un buen ejemplo, diferente de la que el efecto de Flash, pero que aún es buena es el Agua de Simulación utilizando el applet de Java.

(recompensa se muestran respuestas no tienen suficiente detalle, ya que esta era la más cercana a 'el OP es incapaz de crear el código que él quiere, como él carece de habilidades fundamentales y esta respuesta probablemente será de uso para varias personas').

8voto

leon Puntos 2108

Después de hacer la tarea (un.k.una. de investigación) y tratando de convertir directamente el código Java de referencia publicados en la pregunta en Python, y de tener una muy, muy triste la experiencia, mientras que tratando de tener Python/Numpy actualización de una gigantesca gama de colores de los píxeles basado en sus cargos por el murmullo del efecto de la ondulación (lo siento, mi primer idioma no es el inglés), por lo tanto el análisis de varios (x,y) posiciones para cada paso de el efecto de los cálculos y la fusión que en la superficie mostrada en la pantalla (surfarray sobreviene), He llegado a la conclusión - que está respaldado por otros comentaristas - que Pygame simplemente no ser lo suficientemente potente como para atravesar realmente que toda la matriz de píxeles y aplicar los resultados de los cálculos en cada pixel de la pantalla a una tasa mínima de 24 fps (una menos que la media de la experiencia).

Citando el muy desarrollador detrás de la Última Luz de las Producciones y el antiguo Proyecto Geometrian, Ian Mazo:

PyGame no es tan bueno para pixel empujando. Nada es, aparte de la GPU.

La búsqueda y luego resultó ser una búsqueda de Alkahest - algo que resultaría nunca ser hallado - y basado en la misma idea de ondulación de las imágenes, pero esta vez mediante el uso de la transparencia para ver a través de varias capas de Pygame superficies, he publicado la pregunta Pygame circular coropping/máscaras en Gamedev. La respuesta en realidad corrobora el hecho de que yo ya temía que Pygame nunca sería machista suficiente para el trabajo.

Un día después, regresé a mis ideas previas sobre el desarrollo y el vino a través de Ogre3D. Resulta que (1) Ogre3D y las muestras son de código abierto y (2) uno de los ejemplos es un 3-D modelo de agua que interactúa con un objeto en movimiento, exactamente la misma cosa que he tratado de alcanzar en 2-D, pero de una forma mucho más profesional.

Dado que mis conocimientos en C/C++ es nil, me decidí a preguntar acerca de cómo personalizar la Ogre3D agua de demostración para tener una idea de por dónde empezar a buscar, y una de las respuestas me señaló software de Touchscape donde un SDK (ver esta respuesta).

Ogre3D bastante envolvió. Agua efecto dominó, OpenGL (que puede , opcionalmente, usar basado en hardware), el Motor de Juego y Python contenedores a través de Python-Ogro - así que mi respuesta a mi propia pregunta,

¿Alguien puede proporcionar una adecuada implementación de este efecto mediante OpenCV/OpenGL y Pygame?

es, básicamente,

Sí. Compruebe Ogre3D de agua de la demo, siempre con el SDK y conéctelo en Python a través de Python-Ogro.

5voto

spam_eggs Puntos 847

El siguiente uso de numpy podría empezar. Debe ser lo suficientemente rápido como lo es aunque usted podría conseguir mucho más rápido incluso en python (echa un vistazo aquí para ver cómo http://www.scipy.org/PerformancePython).

Por el camino hay varios inconvenientes en el método descrito :

  1. usted no puede controlar la velocidad de las ondas - para eso tendría que modificar las ecuaciones que se utilizan en la ondulación de la función (si usted averiguar cómo se relaciona con la ecuación de onda http://en.wikipedia.org/wiki/Wave_equation entonces usted está listo)
  2. la "profundidad" de la "piscina" es fijo (y probablemente de poca profundidad). He añadido un parámetro profundidad para magnificar el efecto
  3. en el artículo se lee entero de píxeles compensaciones desea obtener un mucho mejor resultado con los valores interpolados (supongo que se puede hacer eso con opengl, pero mis conocimientos en esa área es igual a cero)

código:

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 e y deben ser cuadrículas de una colección.meshgrid llamada : aquí se muestra un ejemplo de uso:

    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) # 

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X