Ready. Aim. FIRE!

If you've ever programmed a game, then you know that physics is critical to realistic play.

No, I am not going to explain how to build a physics engine. I just started with the basics.

How to Launch Things

Whether it is catapults, tanks or worms with slingshots, the most important thing is: whatever goes up must come down... specifically in a parabolic trajectory.

Now, computers are smart, but they're also dumb. It would be nice if we could just tell it a speed and an angle and have it determine everything else. OR give it an x,y coordinate and have it calculate the speed and angle. But computers don't solve algebra equations unless we tell them how. They just plug-n-chug input and give output.

That means we have to do the algebra ourselves. *Sigh*

Programming basic kinematics is the easy part. We provide the initial position, speed, angle and time since "launch" and we can determine the speed, direction and position. Do this 60 times a second and we can animate it. If you need a refresher on the big four, I recommend Khan Academy.

The only real challenge making this app was solving the algebra to adjust the angle of launch based on a selected (arbitrary) target. If you plug the final position into the big four and solve for the angle, you get something pretty ugly. A few trigonometric identities and a quadratic formula later we get this code:
//global declarations
   var g = -9.80665;
   var time = 0; //time
   var v0 = 10;//initial velocity (muzzle)
   var theta = Math.PI/4;//trajectory angle
   var x0 = 0;//initial position
   var y0 = 0;
   var target = {"X":0,"y":0,"active":false};

//x and y are the coordinates that were clicked by the user
function defineTrajectory(x,y){
    tanTheta1 = quadraticFormula(g*x*x/(2*v0*v0),x,-(y-y0)+(g*x*x/(2*v0*v0)),1);
    tanTheta2 = quadraticFormula(g*x*x/(2*v0*v0),x,-(y-y0)+(g*x*x/(2*v0*v0)),-1);
    //two solutions, so we pick positive first
    if (tanTheta1 > 0) theta = Math.atan(tanTheta1);
    else theta = Math.atan(tanTheta2);
    //this updates the visual layout to reflect the angle
    $('#angle').val(theta*180/Math.PI);
    //this tells us where to draw the big red target
    target.x = x;
    target.y = y;
    target.active = true;
    //then we calculate the rest of the trajectory
    //using the big four and then draw the scene
    calcValues();
    drawScene();
    drawTrajectory();
}
function quadraticFormula(a,b,c,sign){
    if (b*b-(4*a*c) < 0) return false;//imaginary solution
    return (-b+(sign*Math.sqrt(b*b-(4*a*c))))/(2*a);
}

What happens if there isn't enough speed to reach the selected point, no matter the angle? I'll leave that for someone else to decide. On to the next project! Orbital trajectories!

0 comments: