25. Representación del estado físico con variables y objetos en JavaScript

Una simulación necesita recordar qué ocurre ahora para calcular qué ocurrirá después. Organizar posición, velocidad, masa y fuerzas en objetos claros vuelve el modelo más fácil de ampliar y comprobar.

25.1 Qué es el estado de un sistema

El estado reúne los valores necesarios para continuar una simulación desde un instante. Para una partícula en una dimensión puede incluir tiempo, posición y velocidad. Si las fuerzas dependen de otras propiedades, también necesitaremos masa, carga o tamaño.

El estado debe distinguirse de la historia: no hace falta guardar todas las posiciones anteriores para calcular la siguiente. La historia es útil para gráficos, repeticiones y diagnóstico, pero el integrador trabaja con el estado actual.

Elegir un estado mínimo reduce inconsistencias. Si almacenamos posición y también una distancia calculable, ambas podrían dejar de coincidir.

25.2 Variables, constantes y parámetros

Una variable de estado cambia durante la evolución, como posición o velocidad. Un parámetro configura el modelo y suele mantenerse durante un experimento, como masa o gravedad. Una constante del programa expresa un valor que no se reasigna.

TipoEjemploUso
Estadoposición, velocidad, tiempoSe actualiza en cada paso
Parámetromasa, gravedadConfigura el comportamiento
Valor derivadoenergía cinéticaSe calcula desde otros datos
Historialmuestras anterioresVisualización y análisis

25.3 Del conjunto de variables a un objeto

Variables separadas funcionan en ejemplos pequeños, pero un objeto mantiene juntos los datos que pertenecen al mismo cuerpo.

const cuerpo = {
  posicionM: 0,
  velocidadMps: 3,
  masaKg: 2,
  fuerzaNetaN: 4
};

const aceleracion = cuerpo.fuerzaNetaN / cuerpo.masaKg;
console.log(aceleracion + ' m/s²');

El resultado es 2 m/s². Los sufijos de unidad hacen visible el contrato de los datos y reducen mezclas accidentales.

25.4 Estado en una y dos dimensiones

En una dimensión basta un número para posición y otro para velocidad. En dos dimensiones cada magnitud vectorial necesita componentes:

posición = { x, y }    velocidad = { x, y }

La masa continúa siendo escalar. Agrupar vectores como objetos mejora la lectura, aunque en simulaciones muy grandes pueden preferirse arreglos por razones de rendimiento.

No mezcles coordenadas de pantalla con metros sin una conversión explícita. El estado físico puede usar metros y la función de dibujo transformarlos a píxeles.

25.5 Datos iniciales y reinicio

El estado inicial define el comienzo de un experimento. Conviene construirlo mediante una función para obtener una copia nueva cada vez que se reinicia la simulación.

function crearEstadoInicial() {
  return { tiempoS: 0, posicionM: 0, velocidadMps: 2 };
}

let estado = crearEstadoInicial();
estado.posicionM = 10;
estado = crearEstadoInicial();
console.log(estado.posicionM + ' m');

El resultado vuelve a 0 m. Reutilizar el mismo objeto sin restaurar todas sus propiedades puede dejar datos residuales entre ejecuciones.

25.6 Una función de actualización

La función de actualización recibe el estado, los parámetros y el intervalo dt. Una secuencia clara calcula fuerza neta, aceleración, velocidad y posición.

entrada actual → calcular derivados → actualizar estado → dibujar

La física no debería depender directamente del lienzo. Separar cálculo y representación permite probar el modelo sin navegador y dibujar el mismo estado de distintas maneras.

También conviene limitar dt cuando una pestaña vuelve después de una pausa larga; un salto temporal enorme puede atravesar obstáculos.

25.7 Mutación o estado nuevo

Podemos modificar el objeto existente o devolver uno nuevo. La mutación reduce asignaciones y es común en motores en tiempo real. El enfoque inmutable facilita comparar estados, deshacer pasos y detectar cambios.

La elección debe ser consistente. Una función que a veces muta y a veces devuelve copias genera errores difíciles de rastrear. Para aprender, devolver un nuevo objeto hace explícita la transición.

25.8 Laboratorio: inspeccionar el estado

Configurá el cuerpo y avanzá la simulación paso a paso. El panel JSON muestra el objeto después de cada actualización.

Los valores aparecen debajo.
Tiempo0,00 s
Posición0,00 m
Velocidad2,00 m/s
Aceleración2,00 m/s²

Estado inicial creado.

25.9 Actualización inmutable

function siguienteEstado(estado, fuerzaNetaN, masaKg, dt) {
  const aceleracion = fuerzaNetaN / masaKg;
  const velocidad = estado.velocidad + aceleracion * dt;
  return {
    tiempo: estado.tiempo + dt,
    posicion: estado.posicion + velocidad * dt,
    velocidad
  };
}

const inicial = { tiempo: 0, posicion: 0, velocidad: 2 };
const siguiente = siguienteEstado(inicial, 4, 2, 0.5);
console.log(siguiente.velocidad + ' m/s');
console.log(siguiente.posicion + ' m');

El nuevo estado tiene velocidad 3 m/s y posición 1,5 m; el objeto inicial permanece intacto. Se usó Euler semiexplícito.

25.10 Validación, copias y serialización

Antes de actualizar, verificá números finitos, masa positiva y dt mayor que cero. Un NaN puede propagarse por todo el sistema.

JSON.stringify permite guardar estados formados por datos simples. No conserva funciones, referencias especiales ni tipos como Map. Para repeticiones deterministas también deben guardarse entradas y condiciones iniciales.

Una copia superficial con {...estado} no duplica objetos anidados. Si posición es un objeto, debemos copiarla explícitamente o usar una estrategia consistente.

25.11 Ejercicio integrador

Un cuerpo tiene masa 4 kg, posición 1 m y velocidad 2 m/s. Actúa una fuerza neta de 8 N durante un paso dt = 0,5 s. Usando Euler semiexplícito, calculá el nuevo estado.

Ver solución y código

a = 8/4 = 2 m/s²; v = 2 + 2·0,5 = 3 m/s; x = 1 + 3·0,5 = 2,5 m; t = 0,5 s.

const estado = { tiempo: 0, posicion: 1, velocidad: 2 };
const masa = 4, fuerza = 8, dt = 0.5;
const aceleracion = fuerza / masa;
estado.velocidad += aceleracion * dt;
estado.posicion += estado.velocidad * dt;
estado.tiempo += dt;
console.log(estado.velocidad + ' m/s');
console.log(estado.posicion + ' m');
console.log(estado.tiempo + ' s');

25.12 Ideas para recordar

  • El estado contiene los datos necesarios para continuar la evolución.
  • Estado, parámetros, derivados e historial cumplen funciones diferentes.
  • Los nombres con unidades aclaran el contrato del objeto.
  • La física debe separarse del dibujo.
  • Mutar o devolver copias son opciones válidas si se usan consistentemente.
  • El reinicio debe crear un estado limpio.
  • Validar masa, tiempo y números finitos evita errores propagados.

En el próximo tema estudiaremos el bucle de simulación y la integración por pasos.