¿Cómo puedo realizar una simulación de física determinista?


43

Estoy creando un juego de física que involucra cuerpos rígidos en el que los jugadores mueven piezas y partes para resolver un rompecabezas / mapa. Un aspecto muy importante del juego es que cuando los jugadores comienzan una simulación, se ejecuta igual en todas partes , independientemente de su sistema operativo, procesador, etc.

Hay espacio para mucha complejidad, y las simulaciones pueden ejecutarse durante mucho tiempo, por lo que es importante que el motor de física sea completamente determinista con respecto a sus operaciones de coma flotante; de ​​lo contrario, puede parecer que una solución se "resuelve" en la máquina de un jugador y "fallar" en otro.

¿Cómo puedo lograr este determinismo en mi juego? Estoy dispuesto a usar una variedad de frameworks y lenguajes, incluidos Javascript, C ++, Java, Python y C #.

Me han tentado Box2D (C ++) y sus equivalentes en otros lenguajes, ya que parece satisfacer mis necesidades, pero carece de determinismo de coma flotante, particularmente con funciones trigonométricas.

La mejor opción que he visto hasta ahora ha sido el equivalente Java de Box2D (JBox2D). Parece hacer un intento de determinismo de coma flotante mediante el uso en StrictMathlugar de Mathmuchas operaciones, pero no está claro si este motor garantizará todo lo que necesito, ya que aún no he construido el juego.

¿Es posible usar o modificar un motor existente para satisfacer mis necesidades? ¿O tendré que construir un motor por mi cuenta?

EDITAR: omita el resto de esta publicación si no le importa por qué alguien necesitaría tanta precisión. Las personas en comentarios y respuestas parecen creer que estoy buscando algo que no debería, y como tal, explicaré más a fondo cómo se supone que funciona el juego.

El jugador recibe un rompecabezas o nivel, que contiene obstáculos y un objetivo. Inicialmente, una simulación no se está ejecutando. Luego pueden usar piezas o herramientas que se les proporcionan para construir una máquina. Una vez que presionan inicio, comienza la simulación y ya no pueden editar su máquina. Si la máquina resuelve el mapa, el jugador ha superado el nivel. De lo contrario, tendrán que presionar detener, alterar su máquina e intentar nuevamente.

La razón por la que todo debe ser determinista es porque planeo producir código que mapeará cada máquina (un conjunto de piezas y herramientas que intentan resolver un nivel) a un archivo xml o json registrando la posición, el tamaño y la rotación de cada pieza. Entonces será posible que los jugadores compartan soluciones (que están representadas por estos archivos) para que puedan verificar soluciones, aprender unas de otras, realizar competiciones, colaborar, etc. Por supuesto, la mayoría de las soluciones, particularmente las simples o rápidas. unos, no se verán afectados por la falta de determinismo. Pero los diseños lentos o complejos que resuelven niveles realmente difíciles podrían ser, y esos son los que probablemente serán los más interesantes y vale la pena compartir.


Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat . Si cree que tiene una solución al problema, considere publicarlo como una respuesta en lugar de un comentario; esto hace que sea más fácil de editar, evaluar a través de la votación / marcado aceptado, o comentar directamente la sugerencia misma para obtener comentarios en lugar de tejiendo respuestas en un hilo de conversación más largo.
DMGregory

Respuestas:


45

Sobre el manejo de números de coma flotante de manera determinista

El punto flotante es determinista. Bueno, debería ser. Es complicado.

Hay mucha literatura sobre números de coma flotante:

Y cómo son problemáticos:

Por resumen. Al menos, en un solo hilo, las mismas operaciones, con los mismos datos, que suceden en el mismo orden, deben ser deterministas. Por lo tanto, podemos comenzar preocupándonos por las entradas y reordenando.


Una de esas entradas que causa problemas es el tiempo.

En primer lugar, siempre debe calcular el mismo paso de tiempo. No digo que no midas el tiempo, digo que no pasarás el tiempo en la simulación física, porque las variaciones en el tiempo son una fuente de ruido en la simulación.

¿Por qué mide el tiempo si no lo pasa a la simulación de física? Desea medir el tiempo transcurrido para saber cuándo se debe llamar a un paso de simulación y, suponiendo que esté usando el modo de reposo, cuánto tiempo duerme.

Así:

  • Medir el tiempo: Sí
  • Usar tiempo en simulación: No

Ahora, reordenamiento de instrucciones.

El compilador podría decidir que f * a + bes lo mismo b + f * a, sin embargo, eso puede tener un resultado diferente. También podría compilarse en fmadd , o podría decidir tomar varias líneas como esa que suceden juntas y escribirlas con SIMD , o alguna otra optimización que no se me ocurra en este momento. Y recuerde que queremos que las mismas operaciones sucedan en el mismo orden, por lo que queremos controlar qué operaciones suceden.

Y no, usar el doble no te salvará.

Debe preocuparse por el compilador y su configuración, en particular para sincronizar números de coma flotante en la red. Debe obtener las compilaciones para aceptar hacer lo mismo.

Podría decirse que escribir ensamblaje sería ideal. De esa manera usted decide qué operación hacer. Sin embargo, eso podría ser un problema para soportar múltiples plataformas.

Así:


El caso de los números de punto fijo

Debido a la forma en que los flotadores se representan en la memoria, los valores grandes perderán precisión. Es lógico que mantener sus valores pequeños (abrazadera) mitiga el problema. Por lo tanto, no hay grandes velocidades ni habitaciones grandes. Lo que también significa que puede usar física discreta porque tiene menos riesgo de hacer túneles.

Por otro lado, se acumularán pequeños errores. Entonces, truncar. Quiero decir, escalar y emitir a un tipo entero. De esa manera, sabes que nada se está acumulando. Habrá operaciones que puede realizar manteniéndose con el tipo entero. Cuando necesitas volver al punto flotante, lanzas y deshaces la escala.

Tenga en cuenta que digo escala. La idea es que 1 unidad se represente realmente como una potencia de dos (16384 por ejemplo). Sea lo que sea, conviértalo en una constante y úselo. Básicamente lo está utilizando como número de punto fijo. De hecho, si puede usar números de punto fijo adecuados de alguna biblioteca confiable mucho mejor.

Estoy diciendo truncado. Sobre el problema de redondeo, significa que no puedes confiar en el último bit del valor que obtuviste después del lanzamiento. Entonces, antes de la escala de lanzamiento para obtener un poco más de lo que necesita, y truncarlo después.

Así:

  • Mantenga valores pequeños: sí
  • Redondeo cuidadoso: sí
  • Números de puntos fijos cuando sea posible: sí

Espera, ¿por qué necesitas coma flotante? ¿No podrías trabajar solo con un tipo entero? Correcto. Trigonometría y radiación. Puede calcular tablas para trigonometría y radiación y hacer que se horneen en su fuente. O puede implementar los algoritmos utilizados para calcularlos con un número de coma flotante, excepto que utilice números de punto fijo. Sí, necesita equilibrar la memoria, el rendimiento y la precisión. Sin embargo, puede permanecer fuera de los números de coma flotante y ser determinista.

¿Sabías que hicieron cosas así para la PlayStation original? Por favor, conoce a mi perro, parches .

Por cierto, no estoy diciendo que no use punto flotante para gráficos. Solo por la física. Quiero decir, claro, las posiciones dependerán de la física. Sin embargo, como sabe, un colisionador no tiene que coincidir con un modelo. No queremos ver los resultados del truncamiento de los modelos.

Por lo tanto: USE NÚMEROS DE PUNTO FIJO.


Para ser claros, si puede usar un compilador que le permite especificar cómo funcionan los puntos flotantes, y eso es suficiente para usted, entonces puede hacerlo. Esa no siempre es una opción. Además, estamos haciendo esto para el determinismo. Los números de puntos fijos no significan que no haya errores, después de todo, tienen una precisión limitada.

No creo que "el número de punto fijo sea difícil" sea una buena razón para no usarlos. Y si desea una buena razón para usarlos, es el determinismo, en particular el determinismo en todas las plataformas.


Ver también:


Anexo : Sugiero mantener el tamaño del mundo pequeño. Dicho esto, tanto OP como Jibb Smart mencionan que alejarse de los flotadores de origen tienen menos precisión. Eso tendrá un efecto en la física, uno que se verá mucho antes que en el borde del mundo. Los números de puntos fijos, bueno, tienen una precisión fija, serán igualmente buenos (o malos, si lo prefiere) en todas partes. Lo cual es bueno si queremos determinismo. También quiero mencionar que la forma en que solemos hacer física tiene la propiedad de amplificar pequeñas variaciones. Vea The Butterfly Effect - Deterministic Physics en The Incredible Machine and Contraption Maker .


Otra forma de hacer física.

He estado pensando, la razón por la cual el pequeño error de precisión en los números de coma flotante se amplifica es porque estamos haciendo iteraciones en esos números. Cada paso de simulación tomamos los resultados del último paso de simulación y hacemos cosas sobre ellos. Acumulación de errores encima de errores. Ese es tu efecto mariposa.

No creo que veamos una sola compilación utilizando un solo subproceso en la misma máquina que produzca diferentes resultados con la misma entrada. Sin embargo, en otra máquina podría, o una construcción diferente podría.

Hay un argumento para probar allí. Si decidimos exactamente cómo deberían funcionar las cosas y podemos probar en el hardware de destino, no deberíamos publicar compilaciones que tengan un comportamiento diferente.


Sin embargo, también hay un argumento para no trabajar lejos que acumula tantos errores. Quizás esta sea una oportunidad para hacer física de una manera diferente.

Como sabrán, existe una física continua y discreta, ambas trabajan en cuánto avanzaría cada objeto en el paso de tiempo. Sin embargo, la física continua tiene los medios para descubrir el instante de la colisión en lugar de probar diferentes instantes posibles para ver si ocurrió una colisión.

Por lo tanto, propongo lo siguiente: utilice las técnicas de física continua para determinar cuándo ocurrirá la próxima colisión de cada objeto, con un gran intervalo de tiempo, mucho mayor que el de un solo paso de simulación. Luego, toma el instante de colisión más cercano y descubre dónde estará todo en ese instante.

Sí, eso es mucho trabajo de un solo paso de simulación. Eso significa que la simulación no comenzará instantáneamente ...

... Sin embargo, puede simular los siguientes pasos de simulación sin verificar la colisión cada vez, porque ya sabe cuándo ocurrirá la próxima colisión (o que no se produce una colisión en el gran intervalo de tiempo). Además, los errores acumulados en esa simulación son irrelevantes porque una vez que la simulación alcanza el gran paso de tiempo, simplemente colocamos las posiciones que calculamos de antemano.

Ahora, podemos usar el presupuesto de tiempo que habríamos utilizado para verificar las colisiones en cada paso de simulación para calcular la próxima colisión después de la que encontramos. Es decir, podemos simular con anticipación utilizando el gran paso de tiempo. Suponiendo un mundo de alcance limitado (esto no funcionará para grandes juegos), debe haber una cola de estados futuros para la simulación, y luego cada cuadro que interpolas desde el último estado al siguiente.


Yo abogaría por la interpolación. Sin embargo, dado que hay aceleraciones, no podemos simplemente interpolar todo de la misma manera. En cambio, necesitamos interpolar teniendo en cuenta la aceleración de cada objeto. Para el caso, podríamos actualizar la posición de la misma manera que lo hacemos para el paso de tiempo grande (lo que también significa que es menos propenso a errores porque no estaríamos usando dos implementaciones diferentes para el mismo movimiento).


Nota : Si estamos haciendo estos números de coma flotante, este enfoque no resuelve el problema de los objetos que se comportan de manera diferente cuanto más lejos están del origen. Sin embargo, si bien es cierto que la precisión se pierde cuanto más te alejas del origen, eso sigue siendo determinista. De hecho, es por eso que ni siquiera mencionó eso originalmente.


Apéndice

De OP en el comentario :

La idea es que los jugadores puedan guardar sus máquinas en algún formato (como xml o json), de modo que se registre la posición y rotación de cada pieza. Ese archivo xml o json se usará para reproducir la máquina en la computadora de otro jugador.

Entonces, no hay formato binario, ¿verdad? Eso significa que también debemos preocuparnos de lo que sea que los números de punto flotante recuperados coincidan o no con el original. Ver: precisión de flotación revisada: portabilidad de flotación de nueve dígitos


Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Vaillancourt

2
¡Gran respuesta! 2 puntos más a favor del punto fijo: 1. el punto flotante se comportará de manera diferente más cerca o más lejos del origen (si tiene el mismo rompecabezas en un lugar diferente), pero el punto fijo no lo hará; 2. El punto fijo en realidad tiene más precisión que el punto flotante para la mayor parte de su rango. Puede obtener precisión utilizando bien el punto fijo
Jibb Smart

Es posible codificar datos binarios en XML y JSON utilizando base64elementos. No es una forma eficiente de representar grandes cantidades de tales datos, pero es incorrecto implicar que impiden el uso de representaciones binarias.
Pikalek

1
@Pikalek Lo sé, OP me preguntó al respecto en los comentarios, mencioné base64 como una opción, entre otras, incluyendo hexadecimal, reinterpretar la conversión como int y usar el formato protobuf ya que nadie entenderá esos archivos de todos modos, no están (sin entrenamiento ) humanamente legible. Luego, supongo, un mod eliminó los comentarios (no, no está en el chat vinculado anteriormente). ¿Volverá a suceder eso? ¿Debo eliminar eso de la respuesta? ¿Debería hacerlo más largo?
Theraot

@ Theraot Ah, puedo ver cómo podría haber interpretado eso de manera diferente en el contexto de los comentarios eliminados. (FWIW, leí los chats sobre esta respuesta y la pregunta). E incluso si hubiera una forma nativa y eficiente de codificar los datos, todavía existe la cuestión más importante de asegurarse de que signifique lo mismo en todas las plataformas. Dado el abandono, tal vez sea mejor dejarlo como está. ¡Gracias por aclararlo!
Pikalek

6

Trabajo para una compañía que hace un cierto juego de estrategia en tiempo real bien conocido, y puedo decirles que es posible el determinismo de coma flotante.

El uso de diferentes compiladores, o el mismo compilador con diferentes configuraciones, o incluso diferentes versiones del mismo compilador, puede romper el determinismo.

Si necesita un juego cruzado entre plataformas o versiones de juegos, entonces creo que tendrá que ir a un punto fijo: el único juego cruzado posible que conozco con punto flotante es entre PC y XBox1, pero eso es bastante loco.

Tendrá que encontrar un motor de física que sea completamente determinista, o tomar un motor de código abierto y hacerlo determinista, o hacer funcionar su propio motor. Fuera de mi cabeza, tengo la sensación de que Unity de todas las cosas agregó un motor de física determinista, pero no estoy seguro de si es solo determinista en la misma máquina o determinista en todas las máquinas.

Si vas a intentar rodar tus propias cosas, algunas cosas que pueden ayudarte:

  • Los flotadores IEE754 son deterministas si no está haciendo nada demasiado afrutado (google "determinismo IEE754" para obtener más información sobre lo que está o no cubierto)
  • Debe asegurarse de que cada cliente tenga su modo de redondeo y precisión configurados de manera idéntica (use controlfp para configurarlo)
  • El modo de redondeo y la precisión pueden ser cambiados por ciertas bibliotecas de matemáticas, por lo que si está utilizando bibliotecas cerradas, es posible que desee verificarlas después de realizar llamadas (nuevamente usando controlfp para verificar)
  • algunas instrucciones SIMD son deterministas, muchas no lo son, ten cuidado
  • como se mencionó anteriormente, para garantizar el determinismo también necesita la misma plataforma, la misma versión exacta del mismo compilador, compilando la misma configuración, con la misma configuración del compilador
  • incorpore algunas herramientas para detectar desincronizaciones de estado y ayude a diagnosticarlas, por ejemplo, CRC el estado del juego en cada fotograma para detectar cuándo se produce una desincronización, luego tenga un modo de registro detallado que puede habilitar donde las modificaciones al estado del juego se registran laboriosamente en un archivo, luego tome 2 archivos de simulaciones que se separaron entre sí y compárelos en una herramienta de diferencias para ver dónde salió mal
  • Inicializa todas tus variables en el estado del juego, fuente principal de desincronizaciones
  • toda la simulación del juego debe realizarse exactamente en el mismo orden cada vez para evitar desincronizaciones, es increíblemente fácil equivocarse, es recomendable estructurar la simulación del juego de tal manera que minimice esto. Realmente no soy un tipo de patrón de diseño de software, pero para este caso probablemente sea una buena idea: puede considerar algún tipo de patrón donde la simulación del juego es como una caja segura, y la única forma de mutar el estado del juego es insertar "mensajes" o "comandos", con solo acceso constante proporcionado a cualquier cosa fuera del estado del juego (por ejemplo, representación, redes, etc.). Entonces, la simulación en red para un juego multijugador es un caso de enviar estos comandos a través de la red, o reproducir la misma simulación es un caso de grabar el flujo de comandos la primera vez,

1
De hecho, Unity está trabajando hacia un objetivo de determinismo multiplataforma con su nuevo sistema Unity Physics para su Pila de tecnología orientada a datos, pero, según tengo entendido, todavía es un trabajo en progreso y aún no está completo / listo para usar.
DMGregory

¿Cuál es un ejemplo de una instrucción SIMD no determinista? ¿Estás pensando en unos aproximados como rsqrtps?
Ruslan

@DMGregory debe estar en la vista previa entonces, ya que puede usarlo, pero como usted dice, puede que aún no esté terminado.
Joe

@Ruslan sí rsqrtps / rcpps los resultados dependen de la implementación
Joe

5

No estoy seguro de si este es el tipo de respuesta que está buscando, pero una alternativa podría ser ejecutar los cálculos en un servidor central. Haga que los clientes envíen la configuración a su servidor, deje que realice la simulación (o recupere una en caché) y envíe los resultados, que luego el cliente interpreta y procesa en gráficos.

Por supuesto, esto cierra cualquier plan que pueda tener para ejecutar el cliente en modo fuera de línea, y dependiendo de cuán intensivamente computacional sean las simulaciones, es posible que necesite un servidor muy potente. O múltiples, pero al menos tiene la opción de asegurarse de que tengan la misma configuración de hardware y software. Una simulación en tiempo real puede ser difícil pero no imposible (piense en las transmisiones de video en vivo, funcionan, pero con un ligero retraso).


1
Estoy completamente de acuerdo. Así es como se garantiza una experiencia compartida con todos los usuarios. gamedev.stackexchange.com/questions/6645/… analiza un tema similar, comparando la diferencia entre la física del lado del cliente y la del lado del servidor.
Tim Holt

1

Voy a dar una sugerencia contraintuitiva que, aunque no es 100% confiable, debería funcionar bien la mayor parte del tiempo y es muy fácil de implementar.

Reduce la precisión.

Use un tamaño de paso de tiempo constante predeterminado, realice la física sobre cada paso de tiempo en un flotador estándar de doble precisión, pero luego cuantifique la resolución de todas las variables a precisión simple (o algo aún peor) después de cada paso. Entonces, la mayoría de las posibles desviaciones que la reordenación de punto flotante podría introducir (en comparación con una ejecución de referencia del mismo programa) se eliminarán porque esas desviaciones ocurren en dígitos que ni siquiera existen en la precisión reducida. Por lo tanto, la desviación no tiene la posibilidad de una acumulación de Lyapunov (Efecto Mariposa) que eventualmente se volvería notable.

Por supuesto, la simulación será un poco menos precisa de lo que podría ser (en comparación con la física real), pero eso no es realmente notable siempre y cuando todas las ejecuciones de su programa sean inexactas de la misma manera .

Ahora, técnicamente hablando, por supuesto, es posible que un reordenamiento cause una desviación que llegue a un dígito de mayor importancia, pero si las desviaciones son realmente solo causadas por flotación y sus valores representan cantidades físicas continuas, esto es extremadamente improbable. Tenga en cuenta que hay 500 millones de doublevalores entre dos single, por lo que se puede esperar que la gran mayoría de los pasos de tiempo en la mayoría de las simulaciones sean exactamente iguales entre las ejecuciones de simulación. Con suerte, los pocos casos en que una desviación se realice a través de la cuantización se verán en simulaciones que no durarán tanto (al menos no con una dinámica caótica).


También le recomendaría que considere el enfoque completamente opuesto a lo que está preguntando: ¡ abrace la incertidumbre ! Si el comportamiento es ligeramente no determinista, entonces esto está más cerca de los experimentos de física reales. Entonces, ¿por qué no aleatorizar deliberadamente los parámetros de inicio para cada ejecución de simulación, y hacer que sea un requisito que la simulación tenga éxito consistentemente en múltiples ensayos? Eso enseñará mucho más sobre física y sobre cómo diseñar las máquinas para que sean lo suficientemente robustas / lineales, en lugar de las súper frágiles que solo son realistas en una simulación.


Redondear hacia abajo no ayudará, porque si el resultado de alta precisión no es determinista, eventualmente un resultado se redondeará en un sentido y en otro en otro. Por ejemplo, siempre puede redondear al número entero más cercano, pero luego un sistema computa 1.0 y el otro calcula 0.9999999999999999999999999999999999999999 y se redondean de manera diferente.
yoyo

Sí, eso es posible, como ya dije en la respuesta. Pero sucederá muy raramente , al igual que otros problemas técnicos en la física del juego. Así redondeo hace ayuda. (Sin embargo, no redondearía ; redondear al más cercano para evitar
sesgos

0

¡Crea tu propia clase para almacenar números!

Puede forzar un comportamiento determinista si sabe con precisión cómo se realizarán los cálculos. Por ejemplo, si las únicas operaciones con las que trata son multiplicación, división, suma y resta, entonces sería suficiente representar todos los números como un número racional. Para hacer esto, una clase racional simple estaría bien.

Pero si desea lidiar con cálculos más complicados (posiblemente funciones trigonométricas, por ejemplo), tendrá que escribir esas funciones usted mismo. Si quisieras poder tomar el seno de un número, deberías poder escribir una función que se aproxime al seno de un número mientras solo usas las operaciones mencionadas anteriormente. Todo esto es factible, y en mi opinión evita muchos de los detalles peludos en otras respuestas. La compensación es que, en cambio, tendrás que lidiar con algunas matemáticas.


3
La aritmética racional es completamente impracticable para cualquier tipo de integración numérica. Incluso si cada paso de tiempo solo lo hace * / + -, los denominadores se volverán cada vez más grandes con el tiempo.
Leftaroundabout

Esperaría que incluso sin considerar la integración, esta no sería una buena solución porque después de solo un par de multiplicaciones o divisiones, los números que representan su numerador y denominador desbordarían un número entero de 64 bits.
jvn91173

0

Hay cierta confusión de terminología aquí. Un sistema físico puede ser completamente determinista, pero imposible de modelar durante un período de tiempo útil porque su comportamiento es extremadamente sensible a las condiciones iniciales, y un cambio infinitamente pequeño en las condiciones iniciales producirá comportamientos completamente diferentes.

Aquí hay un video de un dispositivo real cuyo comportamiento es intencionalmente impredecible, excepto en un sentido estadístico:

https://www.youtube.com/watch?v=EvHiee7gs9Y

Es fácil construir sistemas matemáticos simples (usando solo la suma y la multiplicación) donde el resultado después de N pasos depende del enésimo lugar decimal de las condiciones iniciales. Escribir software para modelar dicho sistema de manera consistente, en cualquier hardware y software que el usuario pueda tener, es casi imposible, incluso si tiene un presupuesto lo suficientemente grande como para probar la aplicación en cada combinación probable de hardware y software.

La mejor manera de solucionar esto es atacar el problema en su origen: hacer que la física de su juego sea tan determinista como sea necesario para obtener resultados reproducibles.

La alternativa es tratar de hacerlo determinista ajustando el software de la computadora para modelar algo que no es lo que especificó la física. El problema es que ha introducido varias capas más de complejidad en el sistema, en comparación con el cambio explícito de la física.

Como ejemplo específico, suponga que su juego involucra colisiones de cuerpos rígidos. Incluso si ignora la fricción, el modelado exacto de colisiones entre objetos de forma arbitraria que pueden estar girando a medida que se mueven es en la práctica imposible. Pero si cambia la situación para que los únicos objetos sean ladrillos rectangulares no giratorios, la vida se vuelve mucho más simple. Si los objetos en su juego no parecen ladrillos, entonces oculte ese hecho con algunos gráficos "no físicos" - por ejemplo, literalmente oculte el instante de colisión detrás de humo o llamas, o una burbuja de texto de dibujos animados "Ouch" o lo que sea.

El jugador tiene que descubrir la física del juego jugando el juego. No importa si no es "totalmente realista" siempre que sea autoconsistente y lo suficientemente similar a la experiencia de sentido común como para ser plausible.

Si hace que la física misma se comporte de manera estable, un modelo de computadora también puede producir resultados estables, al menos en el sentido de que los errores de redondeo serán irrelevantes.


1
No veo ninguna confusión en la terminología. El OP quiere un comportamiento determinista de un sistema potencialmente caótico. Eso es completamente factible.
Mark

El uso de formas más simples (como círculos y rectángulos) no cambia el problema en absoluto. Todavía necesita muchas funciones trigonométricas, sqrt, etc ...
jvn91173

-1

Use precisión de punto flotante doble , en lugar de precisión de punto flotante único . Aunque no es perfecto, es lo suficientemente preciso como para ser considerado determinista en su física. Puede enviar un cohete a la luna con precisión de doble punto flotante, pero no con precisión de punto flotante único.

Si realmente necesita un determinismo perfecto, use matemática de punto fijo . Esto le dará menos precisión (suponiendo que use la misma cantidad de bits), pero resultados deterministas. No conozco ningún motor de física que use matemática de punto fijo, por lo que es posible que deba escribir el suyo si desea seguir esta ruta. (Algo que desaconsejaría).


11
El enfoque de doble precisión va en contra del efecto mariposa . En un sistema dinámico (como un simulador de física), incluso una pequeña desviación en las condiciones iniciales puede amplificarse a través de la retroalimentación, convirtiéndose en un error perceptible. Todo lo que hacen los dígitos adicionales es retrasar esto un poco más, lo que obliga a la bola de nieve a rodar un poco más antes de que sea lo suficientemente grande como para causar problemas.
DMGregory

2
Dos errores a la vez: 1) Los puntos flotantes dobles sufren los mismos problemas y generalmente solo posponen el problema en un futuro cada vez más difícil de depurar. 2) No existe una regla que establezca que el punto fijo debe ser menos preciso que el punto flotante. Dependiendo de la escala y el problema en cuestión, o de la memoria que esté listo para usar por número de punto fijo, pueden ser menos precisos, igualmente precisos o más precisos. No tiene sentido decir "son menos precisos".
phresnel

@phresnel, como ejemplo de precisión de punto fijo, la serie IBM 1400 utilizaba matemática decimal de punto fijo de precisión arbitraria. Dedique 624 dígitos a cada número, y ha excedido el rango y la precisión del punto flotante de doble precisión.
Mark

@phresnel (2) Buen punto. Actualicé mi respuesta para asumir el mismo número de bits.
Evorlor

-2

Usa el patrón de recuerdo .

En su ejecución inicial, guarde los datos posicionales de cada cuadro, o cualquier referencia que necesite. Si eso es demasiado incumplimiento, solo hazlo cada n cuadros.

Luego, cuando reproduzca la simulación, siga la física arbitraria, pero actualice los datos posicionales cada n cuadros.

Pseudocódigo demasiado simplificado:

function Update():
    if(firstRun) then (SaveData(frame, position));
    else if(reproducedRun) then (this.position = GetData(frame));

99
No creo que esto funcione para el caso de OP. Digamos que tú y yo estamos jugando el juego en diferentes sistemas. Cada uno de nosotros coloca las piezas del rompecabezas de la misma manera: una solución que el desarrollador no predijo de antemano. Cuando hace clic en "Inicio", su PC simula la física de tal manera que la solución es exitosa. Cuando hago lo mismo, alguna pequeña diferencia en la simulación conduce a que mi solución (idéntica) no sea calificada como exitosa. Aquí, no tengo la oportunidad de consultar el recuerdo de su ejecución exitosa, porque sucedió en su máquina, no en el momento del desarrollo.
DMGregory

@DMGregory Eso es correcto. Gracias.
jvn91173
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.