1
\$\begingroup\$

In the below code, is the method I use to move a bullet to its destination and stop when bullet is near to destination. But the problem is the bullet is stopping not accurately, sometimes there's a small offset or span or sometimes is accurate depends on the angle.

public Vector2 getVelocity(Vector2 currentPosition, Vector2 targetPosition) {
    Vector2 targetDirection = targetPosition.cpy().sub(currentPosition);
    return targetDirection
            .nor();
}

final float SPEED = 6;
float pos = bulletPosition.len();
float des = bullet.destination.len();
float tol = Constants.TIME_STEP * SPEED;

if(MathUtils.isEqual(pos,des, tol)) {
    body.setLinearVelocity(0,0); 
} else {
    body.setLinearVelocity(getVelocity(bulletPosition, destination).scl(SPEED));
}

[SOLVED]

if(MathUtils.isEqual(pos, des, tol)) {
     // quick & dirty way
     body.setTransform(destination, angle);
     // better way
     ...
}
\$\endgroup\$
2
  • \$\begingroup\$ What does MathUtils.isEqual do exactly, is it a direct comparision or an approximation? \$\endgroup\$ Jul 30, 2016 at 14:30
  • \$\begingroup\$ here is the link for MathUtils java doc link \$\endgroup\$
    – ronscript
    Jul 30, 2016 at 15:16

2 Answers 2

2
\$\begingroup\$

Quick & Dirty Way:
You can simply teleport the bullet to location you want after it stops.

Long & Better Way:
For the last moments of movement, you can disable the physics and control the movement yourself by lerp'ing (or any other way, lerp is my favorite) towards the target. This way, you can stop the bullet whenever you want.


Edit
I would solve the situation like this in Unity, and actually this might be a better way than the two above:

float minDisableDistance, minStopDistance, bulletSpeed;
Transform target;

// I'm skipping the parts that you create the bullet, and simply do the job on these:
GameObject bullet; //Assuming this is the bullet.
Rigidbody bulletRigidbody; //Assuming this is the rigidbody of bullet.

void Update()
{
    Vector3 relPos = target.position - bullet.postion;
    float distance = relPos.magnitude;

    if(distance > minDisableDistance)
    {
        //use physics.
    }
    else
    {
        bulletRigidbody.velocity = 0;

        if(distance > minStopDistance)
        {
            bullet.position += bulletSpeed * relPos.normalized * time.deltaTime;
        }
        else
        {
            bullet.position = target.position;
        }
    }
}
\$\endgroup\$
9
  • \$\begingroup\$ ***** it works perfectly! I just tried the "quick & dirty way" . I want to try the better way \$\endgroup\$
    – ronscript
    Jul 30, 2016 at 15:23
  • \$\begingroup\$ can you give me a little pseudo-code on how do I properly do the properway? \$\endgroup\$
    – ronscript
    Jul 30, 2016 at 15:25
  • \$\begingroup\$ @ronscript I can't, I have never used libgdx or box2d. The wikipedia article about lerp is great, take a look: en.wikipedia.org/wiki/Linear_interpolation \$\endgroup\$ Jul 30, 2016 at 15:28
  • \$\begingroup\$ On the lerp method third parameter t. Because my bullet is speed is 6. the t is also 6? \$\endgroup\$
    – ronscript
    Jul 30, 2016 at 15:33
  • \$\begingroup\$ @ronscript No, the third parameter indicates the "ratio" of movement from beginning to end (and third parameter should be in between 0-1 in general). For example if it is 0.5, it means the result is exactly the middle of start and end points. \$\endgroup\$ Jul 30, 2016 at 15:39
0
\$\begingroup\$

I found out the best way! I just use the Vector2 dst method to get the distance between the destination. And hooray!! it was accurate!

float distance = bulletPosition.cpy().dst(destination);

float tol = (Constants.TIME_STEP * SPEED) / 2;

if(distance <= tol) {

     body.setLinearVelocity(0, 0);

}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .