Comunidad de diseño web y desarrollo en internet

Física en Flash: Rebote y movimiento de cuerpo rígido

Bueno, después de infructíferas incursiones en el campo de la publicación de artículos les traigo este, mi ultimo tutorial... ...dinámica de cuerpos rígidos!!, eeeeeeehh(ovación y aplausos). En los juegos modernos todos 3d re rosos, es imposible que falte un buen motor de física que calcule, cuando menos, como reaccionan los objetos 3D al chocar entre ellos o contra el escenario, muy buenos ejemplos de estos podemos ver en "Hitman-codemane 47", "Far Cry" y "Doom 3".


En este tuto, como le dicen los gallegos a los tutoriales, voy a tratar de echar algo de luz sobre
esta magia de hacer que los objetos se comporten como si tuvieran propiedades físicas reales como el
volumen, el peso, la masa, etc, etc, etc. Esto no tiene nada de nuevo ni de mágico, solamente agarre
las carpetas de física 1 de la facu e implemente las fórmulas. Por que usé flash? Porque desarrollas
rápido, esta orientado a gráficos y me permite tipear sin que el código se me valla del tema de
dinámica, como por ejemplo, al no tener que tipear rutinas para la detección de colisiones entre
sprites, con lo que considero que resulta mas fácil de leer, el código terminado puede verse en
cualquier explorador sin complicaciones. En suma, se adapta a mi manera fácil de pensar.

Algo de teoría

Seguramente a varios de nosotros, en alguna oportunidad, se nos habrá caído un tenedor de la mesa,
una llave de tuercas del capó del auto, una lapicera del pupitre, etc. Como habremos notado, no cae
y se queda en su lugar, sino que repiquetea y salta asta que finalmente queda quieta y podemos
recogerla.

El hecho que repiquetea y se mueva de manera tan aleatoria se debe a que esta expuesta a varias
fuerzas que no solo la hacen rebotar contra el piso, sino que además gira dependiendo de cual de sus
extremos choque primero. En la realidad, un cuerpo esta sometido a infinitas fuerzas que lo hacen
modificar su posición y su orientación. Todas esas fuerzas sumadas, dan una(o varias) fuerza(s)
resultantes, finalmente, simplificamos todas esas fuerzas en:

  • Velocidad horizontal
  • Velocidad vertical
  • Velocidad de giro
  • Aceleración horizontal
  • Aceleración vertical
  • Aceleración de giro.

Todas están modifican la posición horizontal (alias posición en X), y la posición vertical (alias
posición en Y) en cada instante de tiempo, o en nuestro caso, en cada frame de animación.

Aparte de lo anterior, nuestro cuerpo rígido posee algo llamado "coeficiente de restitución
elástica", que es lo que hace que cada vez rebote con menos intensidad asta quedarse quieto.

La combinación de todas estas variables le dan a nuestro cuerpo rígido(CR) la sensación de que pesa,
rebota etc. Al que, para simplificar, consideraremos que es uniforme, es decir, que no tiene un lado
mas pesado que el otro.

Consideración con los rebotes

Cuando nuestra barra choque contra algo, en nuestro caso las paredes y el piso de la caja donde
rebota el CR, su velocidad se multiplicará por (-1), o sea, cambiará de sentido, dependiendo de
contra que choque, a la vez que se multiplica por el coeficiente de restitución. Como este ultimo es
menor a 1, la velocidad disminuirá debido a la perdida de energía que implica el choque. Si la barra
choca en un ángulo distinto de 0 o 180, entonces debe tener una velocidad de rotación igual la
velocidad en Y o X actual multiplicado por el coseno o seno, respectivamente, del ángulo que toma la
barra con la horizontal.

Las variables

Demos un vistazo mas detenido al tema de las variables que intervienen en todo esto, las mismas
interactúan de la siguiente manera:

La velocidad modifica la posición o rotación , la aceleración modifica la velocidad. La única
excepción a lo anterior es que la velocidad también es afectada por el coeficiente de restitución
elástica de la barra. El mismo depende del material con la que esta hecha la barra.

Manos a la obra

Bueno, ya podemos ir poniendo las variables en el código del primer fotograma de nuestro archivo
flash.

      var intAceleracionY:Number = 0.25;
      //Simula la gravedad para una animación mas realista podes ponerle 0.9.
      var intVelocidadRotacion:Number = 5;
      //es como para que tenga una rotación inicial.
      var intVelocidadX:Number = 17;
      var intVelocidadY:Number = 0;
      var intPosAnteriorX:Number;
      //Esto es para que si los frames por segundo son muy bajos no nos estropee el efecto.
      var intPosAnteriorY:Number;
      //Item anterior
      var intCoeficienteRestitucion:Number = 0.6;
      //Para que no rebote eternamente.
Lo próximo que vamos a hacer es crear un movieclip que sea mas ancho que alto. Puede ser cualquier
cosa, un auto, una flechita, cualquier cosa. En mi caso puse 2 bolas de colores unidas por una
inerte barra de carbón.

Para comodidad instancia una variable que represente la barra, del tipo movieclip para aprovechar
las características de auto completar del IDE de flash.
    var myBarra:MovieClip;
    myBarra = this.Barra;

Otra cosa que conviene hacer, es poner otro movieclips como delimitadores a los bordes del lienzo,
para que podamos detectar mas cómodamente las colisiones contra el piso y las paredes.

A continuación calculamos el rebote entre cada una de las paredes y el piso
if (myBarra.hitTest(this.BounderBottom)) {
	//---Calculo el rebote vertical
while (myBarra.hitTest(this.BounderBottom)) { myBarra._y--; } intVelocidadY *= (-1); intVelocidadY *= intCoeficienteRestitucion; if ((myBarra._rotation>0 && myBarra._rotation<90) || (myBarra._rotation<-90 && myBarra._rotation>=(-179))) { intVelocidadRotacion = (-Math.abs(intVelocidadY)*Math.cos(myBarra._rotation)); }
if ((myBarra._rotation<0 && myBarra._rotation>-90) || (myBarra._rotation>90 && myBarra._rotation<180)) { intVelocidadRotacion = (Math.abs(intVelocidadY)*Math.cos(myBarra._rotation)); } } //---Calculo el rebote horizontal if (myBarra.hitTest(this.BounderDer)) { while (myBarra.hitTest(this.BounderDer)) { myBarra._x--; } intVelocidadX *= (-1); intVelocidadX *= intCoeficienteRestitucion; //---Calculo la velocidad de rotacion if ((myBarra._rotation>0 && myBarra._rotation<90) || (myBarra._rotation<-90 && myBarra._rotation>=(-179))) { intVelocidadRotacion = (-Math.abs(intVelocidadX)*Math.cos(myBarra._rotation)); } if ((myBarra._rotation<0 && myBarra._rotation>-90) || (myBarra._rotation>90 && myBarra._rotation<180)) { intVelocidadRotacion = (Math.abs(intVelocidadX)*Math.cos(myBarra._rotation)); } } if (myBarra.hitTest(this.BounderIZ)) { while (myBarra.hitTest(this.BounderIZ)) { myBarra._x++; } intVelocidadX *= (-1); intVelocidadX *= intCoeficienteRestitucion; if ((myBarra._rotation>0 && myBarra._rotation<90) || (myBarra._rotation<-90 && myBarra._rotation>=(-179))) { intVelocidadRotacion = (-Math.abs(intVelocidadX)*Math.cos(myBarra._rotation)); } if ((myBarra._rotation<0 && myBarra._rotation>-90) || (myBarra._rotation>90 && myBarra._rotation<180)) { intVelocidadRotacion = (Math.abs(intVelocidadX)*Math.cos(myBarra._rotation)); } }

Una vez que calculamos toda las velocidades, modificamos las posiciones.
intVelocidadY += intAceleracionY; myBarra._x += intVelocidadX; myBarra._y += intVelocidadY;
Con el ángulo pasa algo especial, ya que si impacta contra el piso, tiene que, aparte de rotar por
el impacto, enderezarse para obtener su posición horizontal.
while ((myBarra._rotation>0 && myBarra._rotation<90 && myBarra.hitTest(this.BounderBottom)) || (myBarra._rotation<-90 && myBarra._rotation>=(-179) && myBarra.hitTest(this.BounderBottom))) {
	myBarra._rotation--;
}
while ((myBarra._rotation<0 && myBarra._rotation>-90 && myBarra.hitTest(this.BounderBottom)) || (myBarra._rotation>90 && myBarra._rotation<180 && myBarra.hitTest(this.BounderBottom))) {
myBarra._rotation++; }
y ahora sí, modificamos el ángulo de la barra.
myBarra._rotation += intVelocidadRotacion;
Bueno, por ahora esto es todo, les dejo el modelo terminado junto con el fuente. No olviden criticar
constructivamente y sugerir mejoras para el código. Espero que les halla gustado chau.


Este ejemplo simula dos pelotas de goma unidas por una inerte barra de carbón.
Hacé clic con el mouse para levantar la barra y darle velocidad de rotación.

¿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.

Descargar Archivo

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate