Vuelvo a mi juego de billar. Verán, después de lo que se estuvo hablando en el post que menciono arriba hice algunos cambios en mi programación y se hizo patente un problema del que creí que había conseguido zafarme: al tener ya la función que mueve las bolas controlada por un EnterFrame y no un Timer, en el momento de choque hay un instante en el que las bolas (a veces) por poco \"atraviesan\" los bordes, y después, como la posición se corrige, lo hace de manera muy brusca en esos casos. Pues bien, quisiera intentarlo ahora con trigonometría, tal y como me dijo solisarg (no olvidé su código):
Código :
var game:Object = {};
game.numBalls = 2;
for (var i = 1; i<=game.numBalls; ++i) {
var name:String = \"ball\"+i;
game[name] = {};
game[name].clip = _root[name];
game[name].xpos = game[name].clip._x;
game[name].ypos = game[name].clip._y;
game[name].radius = game[name].clip._width/2;
game[name].xmov = 0;
game[name].ymov = 0;
}
game.ball1.xmov = 0;
game.ball1.mass = 1;
game.ball1.ymov = 2;
game.ball2.mass = 1;
game.ball2.ymov = 0;
function moveBalls() {
for (var i = 1; i<=game.numBalls; ++i) {
var ob:Object = game[\"ball\"+i];
ob.tempx = ob.xpos+ob.xmov;
ob.tempy = ob.ypos+ob.ymov;
}
}
function renderBalls() {
for (var i = 1; i<=game.numBalls; ++i) {
var ob = game[\"ball\"+i];
ob.xpos = ob.tempx;
ob.ypos = ob.tempy;
ob.clip._x = ob.xpos;
ob.clip._y = ob.ypos;
}
}
function ball2BallReaction(b1:Object, b2:Object, x1:Number, x2:Number, y1:Number, y2:Number, time:Number) {
//get the masses
var mass1:Number = b1.mass;
var mass2:Number = b2.mass;
// -----set initial velocity variables
var xVel1:Number = b1.xmov;
var xVel2:Number = b2.xmov;
var yVel1:Number = b1.ymov;
var yVel2:Number = b2.ymov;
var run:Number = (x1-x2);
var rise:Number = (y1-y2);
var Theta:Number = Math.atan2(rise, run);
var cosTheta:Number = Math.cos(Theta);
var sinTheta:Number = Math.sin(Theta);
//Find the velocities along the line of action
var xVel1prime:Number = xVel1*cosTheta+yVel1*sinTheta;
var xVel2prime:Number = xVel2*cosTheta+yVel2*sinTheta;
//Find the velocities perpendicular to the line of action
var yVel1prime:Number = yVel1*cosTheta-xVel1*sinTheta;
var yVel2prime:Number = yVel2*cosTheta-xVel2*sinTheta;
// Conservation Equations
var P:Number = (mass1*xVel1prime+mass2*xVel2prime);
var V:Number = (xVel1prime-xVel2prime);
var v2f:Number = (P+mass1*V)/(mass1+mass2);
var v1f:Number = v2f-xVel1prime+xVel2prime;
var xVel1prime:Number = v1f;
var xVel2prime:Number = v2f;
//Project back to Flash\'s x and y axes
var xVel1:Number = xVel1prime*cosTheta-yVel1prime*sinTheta;
var xVel2:Number = xVel2prime*cosTheta-yVel2prime*sinTheta;
var yVel1:Number = yVel1prime*cosTheta+xVel1prime*sinTheta;
var yVel2:Number = yVel2prime*cosTheta+xVel2prime*sinTheta;
//change old pos
b1.tempx = b1.xpos+bl.xmov*time;
b1.tempy = b1.ypos+b1.ymov*time;
b2.tempx = b2.xpos+b2.xmov*time;
b2.tempy = b2.ypos+b2.ymov*time;
b1.xmov = xVel1;
b2.xmov = xVel2;
b1.ymov = yVel1;
b2.ymov = yVel2;
}
function ballToBallDetection(b1:Object, b2:Object) {
//set the speed variables
var xmov1:Number = b1.xmov;
var ymov1:Number = b1.ymov;
var xmov2:Number = b2.xmov;
var ymov2:Number = b2.ymov;
//set the position variables
var xl1:Number = b1.xpos;
var yl1:Number = b1.ypos;
var xl2:Number = b2.xpos;
var yl2:Number = b2.ypos;
//define the constants
var R:Number = b1.radius+b2.radius;
var a:Number = -2*xmov1*xmov2+xmov1*xmov1+xmov2*xmov2;
var b:Number = -2*xl1*xmov2-2*xl2*xmov1+2*xl1*xmov1+2*xl2*xmov2;
var c:Number = -2*xl1*xl2+xl1*xl1+xl2*xl2;
var d:Number = -2*ymov1*ymov2+ymov1*ymov1+ymov2*ymov2;
var e:Number = -2*yl1*ymov2-2*yl2*ymov1+2*yl1*ymov1+2*yl2*ymov2;
var f:Number = -2*yl1*yl2+yl1*yl1+yl2*yl2;
var g:Number = a+d;
var h:Number = b+e;
var k:Number = c+f-R*R;
//solve the quadratic equation
var sqRoot:Number = Math.sqrt(h*h-4*g*k);
var t1:Number = (-h+sqRoot)/(2*g);
var t2:Number = (-h-sqRoot)/(2*g);
if (t1>0 && t1<=1) {
var whatTime:Number = t1;
var ballsCollided:Boolean = true;
}
if (t2>0 && t2<=1) {
if (whatTime == null || t2<t1) {
var whatTime:Number = t2;
var ballsCollided:Boolean = true;
}
}
if (ballsCollided) {
//Collision has happened, so throw a trace
ball2BallReaction(b1, b2, xl1, xl2, yl1, yl2, whatTime);
}
}
_root.onEnterFrame = function() {
moveBalls();
ballToBallDetection(game.ball1, game.ball2);
renderBalls();
};Pero quisiera comprender en primer lugar el fundamento teórico detrás de una comprobación de colisiones eficiente y eficaz (que deberá ser con trigonometría, me temo). Si no me equivoco, cada fotograma se comprueba con trigonometría y teniendo en cuenta la direción, ángulo y velocidad de las bolas si van a chocar con el objeto y, en función de si van a chocar o no, otra función les asigna después una posición en el plano y si es necesario un cambio de ángulo o de velocidad. ¿Es así, a grandes rasgos? Y si no, ¿algún experto podría desgranármelo un poco?
Muchísimas gracias


