4
\$\begingroup\$

Right now, when I spawn a shootable object, it goes like this:

enter image description here

Because I just set it's angle to this:

float aimAngle = (float) Math.atan2(velocity.y, velocity.x);
bullet.setBodyAngle(aimAngle);

I want it to be like this:

enter image description here

I think I should use angular velocity or torque, but I have no idea how. I can't just set it's angle like in previous code every frame, because it makes physics collisions glitch.

\$\endgroup\$
  • 1
    \$\begingroup\$ The effect you have shown is produced by wind resistance, which would be a pain to simulate correctly. Have you considered some kind of hand-tuned hack? \$\endgroup\$ – MickLH Jan 12 '16 at 22:29
  • \$\begingroup\$ are you sure? object moves in a strict projectile, angular velocity seems to be exactly for this, I just can find correct value. I'm sure there should be some formula. \$\endgroup\$ – Gintas_ Jan 12 '16 at 22:32
  • 1
    \$\begingroup\$ Here's a thought experiment to show you: Where does the angular force come from in the real world? Would the same happen in space? \$\endgroup\$ – MickLH Jan 12 '16 at 23:20
  • \$\begingroup\$ But that's not real world... If we can guess where projectile will land, we should be able to guess angular velocity \$\endgroup\$ – Gintas_ Jan 13 '16 at 8:15
  • 1
    \$\begingroup\$ This link might help you \$\endgroup\$ – Hamza Hasan Jan 13 '16 at 9:50
3
\$\begingroup\$

Summary

My recommendation is to compute a restorative torque to apply to the object. This is physically more accurate than setting the velocity directly, and the simulation will be better behaved.

This solution should also work for any launch angle. Below is a gif of this method at work stabilizing arrows launched from a car.

Firing arrows with working flights

Restorative Torque

This video on the concept of control system stability describes exactly what you are trying to achieve. The video (and the series) is very well made, but the example of the dart at 2:35 is particularly informative.

In the example Brian describes, the dart (or projectile in your case), tends to orient itself with the velocity vector because of the air pressure on the flights of the dart.

Implementation

When the projectile is created, there should be some angularDamping set for the body to damp out rotational forces. Then the restorative torque may be applied as follows:

//Get the velocity of the projectile
b2Vec2 projVel = projBody.GetLinearVelocity();

//Get the current angle of the body in the range 0,2*pi
double ang = projBody.GetAngle() % pi;
if(ang < 0){
    ang = ang + 2*pi;
}

//Compute the difference between the projectile angle and the angle of the velocity vector
double diff = atan2(-projVel.x, projVel.y) - ang;

//Need the absolute angle for a couple of tests
double absDiff = abs(diff);

//Test if the difference exceeds some very small threshold value (e.g. 10e-6)
if(absDiff > thresh){

    /*Test if the difference in angles is greater than pi
   (If so then the projectile has completely flipped around
   and the restoring torque needs to be applied in the opposite direction)*/
    if(absDiff > pi){
         diff = diff-2*pi;
    }

    /*Apply the restorative torque, scaled with the velocity so that
    the faster the object is moving, the greater its tendency
    to align with the direction of motion.

    The torqueCoeff is a tunable coefficient:
     - increase it if your body isn't aligning quickly enough
     - decrease if it's wobbling back and forth too much.
    You can also play with the angularDamping coefficient to produce the results you want*/
    projBody.ApplyTorque(diff*projVel.Length()*torqueCoeff);
}

Please be advised, this code is untested. I have translated it from some lua code I have written for a love2d project (the co-ordinate system in love2d is flipped about the horizontal axis so some of the angles are computed differently).

\$\endgroup\$
  • \$\begingroup\$ nice! It didn't work fine when shot to the left, so I used simple if's and multiplied torque by -1 if aiming to left. However, I can't seem to make it work when shooting to the bottom right circle quarter side, it's spinning too fast. \$\endgroup\$ – Gintas_ Jan 21 '16 at 17:13
0
\$\begingroup\$

Stated that i agree with MickLH comments.

Assuming no Air resistance. The flight time of a parabola thorw is :

 T=2*V0 * sin(a) / g 

where V0 is launch velocity , a is launch angle and g is gravitational acceleration.

Th = V0 * sin(a) / g 

is the time from ground to higher point. In higher point your desired angle is 0 so compute

(0 - angle) / Th as angular velocity

\$\endgroup\$
  • \$\begingroup\$ If V0 is a vector2, I assume final result will also be vector2. However, box2D takes omega parameter in setAngularVelocity method, how could I convert final result to omega? \$\endgroup\$ – Gintas_ Jan 13 '16 at 15:47
  • \$\begingroup\$ @Gintas_ I believe dnk meant “launch speed” (magnitude of launch velocity). That's a scalar value instead of a vector so it'll result in a float. Nothing else in the equation seems to mandate a vector for V0. \$\endgroup\$ – Slipp D. Thompson Jan 13 '16 at 16:31
  • \$\begingroup\$ I tried it, it seems to work only on some cases. If a bullet is thrown to the ground side(y < 0), doesn't work at all. It seems to work only if I throw a bullet 135 degree angle, something like that... \$\endgroup\$ – Gintas_ Jan 13 '16 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.