¿Cómo creo partículas que reaccionan ante el jugador y los enemigos?

38

Actualmente estoy haciendo un juego con mi propio motor de juego que he escrito en C ++ y estoy usando el SDK directx más reciente.

El juego es un tirador espacial de arriba hacia abajo (con un giro bastante interesante) y estoy buscando tener una especie de efecto de nebulosa por el que el jugador volará. Tengo muchas ganas de tratar de lograr esa agradable sensación táctil de cientos de partículas que se mueven fuera del camino de la nave del jugador cuando vuela hacia ellas. Algo así como las partículas se moverían del camino del jugador en Geomtry Wars en XBLA.

Soy un programador experimentado cuando se trata de C ++. Sin embargo, no sé cómo comenzar a implementar este efecto. ¿Alguien tiene alguna idea genial o opciones de diseño que me gustaría considerar? No dude en responder a cualquier grado de profundidad que desee.

Matt McDonald
fuente

Respuestas:

65

Es una buena idea. Necesitarías algún tipo de gradiente de difusión alrededor de tu nave. Hay tres modelos físicos en los que puedo pensar que quizás quieras:

  1. Desea que parezca casi como un medio líquido, donde el gradiente de presión se reequilibra, es decir, una vez que ha pasado algunas partículas, regresan a su estela (como el agua detrás de un bote). En este caso, las posiciones de las partículas son absolutas, y es solo su relación con el jugador la que modifica temporalmente su posición de renderizado . Esto es un poco como cuando pasas una lupa gruesa sobre las cosas, y la difracción parece hacer que se muevan, pero solo hasta que alejas el vidrio. En este caso, tu nave es el cristal.

  2. Si quieres que se alejen del barco y continúen moviéndose una vez que se hayan movido. Esto es como la física estándar en un espacio generalmente vacío donde no hay gradientes de presión (o muy pequeños).

  3. Desea mover las partículas lejos de la nave rápidamente a medida que se acerca, como en (1) y (2), pero una vez que la nave se haya ido, las partículas se reequilibrarán lentamente para ser equidistantes a su paso.

Común a las tres soluciones : necesita tener un campo de difusión que se mueva con su nave. En este ejemplo lo haremos circular. Luego detecta el vector, llámelo v1, entre la nave y cada partícula dentro de esa región. Empuja tu partícula a lo largo de ese vector. La fuerza con la que lo empujará dependerá de su distancia del barco: uso 1 - v1.magnitude. Esta fórmula le dará una fuerza lineal, sin embargo, puede modificarla para usar algo más, como una curva de fuerza circular que disminuye la fuerza hacia los bordes. Esto le daría más un aspecto como si hubiera un gradiente de presión esférico en lugar de circular alrededor del barco.

Para la solución 1 : todo lo que ahora hace es modificar la posición de renderizado de esa partícula (es decir, la posición del sprite) en cada actualización de renderizado , mediante este vector. Debido a que lo está haciendo de esta manera, esto es puramente un efecto de representación y no tiene ningún efecto en la posición mundial real de la partícula. Por lo tanto, agrega la posición mundial al desplazamiento de renderizado (v1) y ahora tiene partículas muy bien desplazadas a medida que avanza hacia o al lado de ellas, y revierte suavemente las partículas a medida que pasa (detrás de usted).

Para la solución 2 : en lugar de simplemente aplicar v1 a la posición de vista, aplíquelo en cada actualización lógica , a la posición de la partícula. Por lo tanto, p1.position += v1. Entonces estás aplicando una fuerza de aceleración a la partícula, que se traduce en velocidad. Probablemente, deseará que se disminuya la velocidad de cada partícula para que disminuyan gradualmente y se detengan una vez que haya pasado. Puede ver cómo esta solución generará partículas agrupadas en su nebulosa, porque nunca se volverán a difundir. No es muy realista, estoy seguro, ya que las nebulosas tienen gradientes de presión dentro de ellas, no importa cuán débil sea en realidad.

Para la solución 3: Igual que (2), pero en este caso tendrá que redistribuir sus partículas. Hacer esto fácilmente es un enfoque de fuerza bruta, pero dado que estas son solo partículas y, por lo tanto, llamativas, probablemente no necesite cubrir un área de gran interés (probablemente solo un radio de playerPosition + maxPlayerSpeedPerTick, o lo que sea área rectangular circunscribe eso, para fines lógicos). Cada partícula aplicará una fuerza sobre cada partícula dentro del área de interés. Aplicarán fuerzas basadas, una vez más, en sus distancias entre sí. Calcule todas las fuerzas interpartículas en un único barrido en el área de interés y luego aplique todas las fuerzas en un único barrido. Por último, asegúrese de realizar este procesamiento de fuerza entre partículas solo en partículas que tengan velocidad cero. Y una vez que una partícula determinada alcanza una velocidad mínima,

Hay todo tipo de fórmulas de difusión, etc., pero creo que en este caso una solución simple funciona mejor.

Ingeniero
fuente
Compañero, desafortunadamente actualmente no tengo la reputación de votar tu respuesta (y solo podría hacerlo una vez, que es menos de lo que merece). Absolutamente clavaste lo que estaba buscando en tu primera solución. Fantástica respuesta. Honestamente. ¡Gracias!
Matt McDonald
¡Un placer total Matt, es una buena pregunta y vale la pena flexionar el cerebro!
Ingeniero
También he decidido que con muy pocos cambios en el código podría hacer que esto se aplique a asteroides más pequeños dentro de un cinturón. Gracias de nuevo.
Matt McDonald