If you're seeing this message, it means we're having trouble loading external resources on our website.

Si estás detrás de un filtro de páginas web, por favor asegúrate de que los dominios *.kastatic.org y *.kasandbox.org estén desbloqueados.

Contenido principal

Atracción mutua

Esperamos que te haya sido útil empezar con un escenario sencillo de un objeto que atrae a otro objeto y luego seguir con un objeto atrae a muchos objetos. Sin embargo, probablemente te encontrarás en una situación un poco más complicada: muchos objetos se atraen entre sí. En otras palabras, cada objeto en un sistema dado atrae a cualquier otro objeto en ese sistema (excepto a sí mismo).
Ya tenemos hecho prácticamente todo el trabajo. Consideremos un programa con un arreglo de objetos Mover:
var movers = [];

for (var i = 0; i < 5; i++) {
    movers[i] = new Mover(
        random(0.1, 2),
        random(width),
        random(height));
}

draw = function() {
    background(255, 255, 255);
    for (var i = 0; i < movers.length; i++) {
        movers[i].update();
        movers[i].display();
    }
};
La función draw() es donde tenemos que hacer algo de magia. Actualmente estamos diciendo: “para cada mover i, actualízate y despliégate”. Ahora lo que necesitamos decir es: “para cada mover i, sé atraído por cualquier otro mover j, actualízate y despliégate”.
for (var i = 0; i < movers.length; i++) {
    // Para cada Mover, ¡revisa cada Mover!
    for (var j = 0; j < movers.length; j++) {
        var force = movers[j].calculateAttraction(movers[i]);
        movers[i].applyForce(force);
    }
}

for (var i = 0; i < movers.length; i++) {
    movers[i].update();
    movers[i].display();
}
Observa que hicimos hecho un nuevo bucle for completamente nuevo arriba del bucle de actualizar y desplegar. Eso es porque queremos estar seguros de calcular todas las fuerzas de atracción antes de actualizar cada mover. Si actualizáramos accidentalmente cada mover en ese primer bucle for, entonces estaríamos afectando el cálculo de las fuerzas de atracción después, y no serían precisas.
Nuestro código todavía no funciona porque necesitamos que cada Mover tenga un método calculateAttraction(). En el ejemplo anterior, teníamos un objeto Attractor con un método llamado calculateAttraction(). Ahora, como tenemos movers que se atraen, podemos copiar ese método en el objeto Mover:
Mover.prototype.calculateAttraction = function(m) {
  var force = PVector.sub(this.position, m.position);
  var distance = force.mag();
  distance = constrain(distance, 5.0, 25.0);                        
  force.normalize();

  var strength = (G * this.mass * m.mass) / (distance * distance);
  force.mult(strength);
  return force;
};
Por supuesto, tenemos un pequeño problema. Cuando estamos buscando cualquier mover i y cualquier mover j, ¿estamos bien con las veces que i es igual a j? Por ejemplo, ¿el mover #3 debería atraer al mover #3? La respuesta, por supuesto, es no. Si hay cinco objetos, solo queremos que el mover #3 atraiga al 0, 1, 2 y 4, saltándose a sí mismo. Sin embargo, queremos calcular y aplicar tanto la fuerza del mover #3 sobre el mover #1, como la del mover #1 sobre el mover #3. Las fuerzas calculadas serán las mismas para el par, pero la aceleración resultante será distinta, dependiendo de la masa de cada mover. Nuestra tabla de atracción debe verse así:
0 ⇢ 1, 2, 3, 4
1 ⇢ 0, 2, 3, 4
2 ⇢ 0, 1, 3, 4
3 ⇢ 0, 1, 2, 4
Y así, terminamos este ejemplo al modificar nuestro bucle de manera que los bucles internos eviten que los movers se atraigan a sí mismos:
for (var i = 0; i < movers.length; i++) {
    for (var j = 0; j < movers.length; j++) {
       if (i !== j) {
         var force = movers[j].calculateAttraction(movers[i]);
         movers[i].applyForce(force);
       }
    }
}
Ahora veamos todo junto:

Este curso de "Simulaciones Naturales" es un derivado de "La Naturaleza del Código" por Daniel Shiffman, usado bajo una Licencia Creative Commons Reconocimiento-NoComercial 3.0 Unported.