Aunque este tip se justifica por sí mismo como introducción y desarrollo de los constraints, está pensado en base al tutorial anterior sobre Integración de Verlet. De todos modos, puede ser leido individualmente sin problema.
En primer lugar voy a explicar brevemente qué son los contraints.
Los constraints o restricciones son eso, restricciones. En este caso, de movimiento.
Imaginemos una barra de longitud L que cumpla las siguientes condiciones ideales, que no se pueda doblar, romper, estirar o comprimir (básicamente la definición de un cuerpo rígido ideal). Ahora, supongamos que tomamos 2 puntos cualesquiera de la misma, por motivos prácticos, en sus extremos.
Es claro que sin importar lo que ocurra, la distancia entre ambos puntos debe ser forzosamente L (la longitud de la barra), incluso aunque los movamos individualmente. Si pensamos esto en términos más normales o, mejor dicho, ejemplos palpables, esto resulta obvio y no requiere mayor explicación.
Supongamos que por motivos que no importan por el momento nos vemos obligados a mover las partículas y, también por motivos que no nos interesan por el momento, deseamos que las partículas permanezcan a la misma distancia.
En este caso, lo único que se conservaría es el ángulo que forman. Por lo tanto, si calculamos la distancia actual, le restamos la original (podría dar negativo, esto es correcto e importante) y la dividimos por 2, vamos a obtener cuánto debemos mover las partículas la una hacia la otra (el número negativo, haría que se alejen).
Paso a paso lo que hacemos es:
- Calcular la distancia entre las partículas.
- Calcular el ángulo que forman.
- Calcular cuánto tenemos que moverlas.
- Reubicarlas.
Si traducimos lo anterior a una función, obtenemos lo siguiente :
Código :
constraint = function (mc1:MovieClip, mc2:MovieClip, distancia:Number, elasticidad:Number, fijo1:Boolean, fijo2:Boolean):Void { // if (fijo1 && fijo2) { return; } // fijo1 = (fijo1 != true) ? false : true; fijo2 = (fijo2 != true) ? false : true; elasticidad = (elasticidad > 1 || typeof (elasticidad) != "number") ? 1 : ((elasticidad < 0) ? 0 : elasticidad); // var xdist = mc1._x - mc2._x; var ydist = mc1._y - mc2._y; var dist = Math.sqrt (xdist * xdist + ydist * ydist); var diff = dist - distancia; // if (Math.abs (diff) < .1) { return; } // var correccion = (fijo1 || fijo2) ? diff : diff / 2; var angulo = -Math.atan2 (xdist, ydist); // if (!fijo1) { mc1._x += correccion * Math.sin (angulo) * elasticidad; mc1._y -= correccion * Math.cos (angulo) * elasticidad; } // if (!fijo2) { mc2._x -= correccion * Math.sin (angulo) * elasticidad; mc2._y += correccion * Math.cos (angulo) * elasticidad; } };
Aunque el código anterior está pensado para ser claro y simple de entender, realiza su trabajo como se supone que debe hacerlo.
Un ejemplo de cómo aplicamos el código anterior podría ser el siguiente:
En este caso, empleamos la variable elasticidad y obtenemos un efecto que podría tildarse de más orgánico (como en el juego Flow).
Además, empleamos una función que llama a la función constraints. La ventaja es que podemos fácilmente decidir cuántas iteraciones deseamos en el proceso de restringir.
Porqué tenemos que iterar? Es simple, el caso que veníamos analizando había sólo 2 partículas y un contraint. Con varios, la cosa se complica. Ya que satisfacer un constraint puede "desatisfacer" otro/s.
Cómo satisfacer todos los constraints al mismo tiempo? Bien, si uno lo analiza, es equivalente a resolver un sistema de ecuaciones bastante complejo. Pero, si satisfacemos una a una las restricciones, qué ocurre?
Exacto, el sistema se parece cada vez más a la solución final. Si repetimos el proceso infinitas veces, obtendríamos la posición exacta que deseamos.
Pero eso no es necesario, con 3 veces alcanza en la mayoría de los casos. Esto se debe a que este sistema no acumula errores. Un error pequeño al principio, significa un error menor luego de algunos fotogramas. Es decir, incluso con sólo una iteración obtendríamos el efecto deseado (aunque podría llegar a ser visualmente feo).
A estas alturas, ya puede resultar más clara la utilidad de la Integración de Verlet. Luego de modificar la posición de las partículas para satisfacer sus correspondientes sistemas de constraints, las hemos movido. Si además del código para las restricciones, le agregamos el que corresponde a la integración, vamos a ver cómo las partículas se unen para formar sólidos que rotan, rebotan, no se deforman y responden naturalmente a las colisiones.
Parece mentira? Pues no lo es:
Bajar los archivos del tutorial.
Igualmente, el ejemplo anterior es solo eso, un ejemplo. En realidad, si quisieramos convertir lo anterior en nuestro propio Half-life 2, vamos a necesitar un milagro, evitar que los objetos vibren cuando deberían estar quietos y un mejor sistema de detección de colisiones. Pero no hace falta ser demasiado crédulo para observar que no falta mucho para crear nuestra propia simulación física creible (no realista, sólo creible).
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.
Por nicosantos el 22 de Junio de 2007
Por M@U el 23 de Junio de 2007
HernanRivas :
.... a este ejemplo que posteaste, agregarle gravedad, es decir; que si tienes un constraint los demas caigan por el empuje de la gravedad, pero sigan manteniendo su distancia unos a otros....
Entiendo si mi pregunta esta muy gruesa, o si te incomoda responder!!!... En horabuena, te quedo muy buena !!!...
Por penholder el 23 de Junio de 2007
Por HernanRivas el 24 de Junio de 2007
Es más, el ejemplo de la caja que rebota hace precisamente eso. Las 4 esquinas de la caja se mantienen unidas usando 6 constraints y la gravedad se incluye dentro de la función de Verlet, que es la misma que se ocupa de los rebotes y la rotación de la caja. A esta función se le pueden agregar sin ningún problema aceleraciones en cualquier eje (es más, la función la escribí pensando en eso y hasta permite que cada punto tenga una aceleración distinta).
Te recomendaría que revisaras el .fla de la caja que cae y el tutorial anterior.
Por M@U el 25 de Junio de 2007
Por o_o el 28 de Junio de 2007
Por clipdepelicula el 10 de Enero de 2008