Jump to content
  • Advertisement
Sign in to follow this  
zgintasz

Efficiently detect shoot direction with gravity playing a role?

This topic is 917 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey,

how could I efficiently calculate shoot direction for enemy AI in order for it to hit the player? Things I know:

player position, player velocity, gravity, bullet spawn position, bullet initial velocity/speed(not direction, gravity is also applied for it)

 

7Afw7nR.png

Edited by Gintas Z.

Share this post


Link to post
Share on other sites
Advertisement

If you ignore air resistance, the player and the bullet follow paraboles. You seem to be look for the crossing point of two paraboles. That sounds like a solved problem to me.

 

On the other hand, just shooting and hitting the player at exactly the right spot every single time isn't much fun, so you probably want to add some randomness into it. You could also consider using a straight line for the bullet, which reduces the problem to finding the crossing point between a parabole and a straight line. Add some compensation based on distance, and some random for spreading the fire somewhat.

Theoretically, compensation should also take angle of firing into account, but you can overcompensate a bit, and the remaining difference will get lost in randomness anyway.

 

EDIT:

You can also cheat, and always shoot the player at a known height. That means you can pre-compute the  time delay between firing and hitting a spot at the desired height at a given distance. You can also compute when the player is at that height, and how close he is to the AI then.

Edited by Alberth

Share this post


Link to post
Share on other sites

A formula to guess the position is:
x = posX + velX * time + 0.5 * gravX * time * time;

 

So we could get X intersection time:

bulletPosX + bulletVelX * time + 0.5 * gravX * time * time = playerPosX + playerVelX * time + 0.5 * gravX * time * time

 

Then get the time from Y parabolas. Then do something, but doesn't matter what yet, because how the hell do I extract time out of this mess?

 

Or is there a different way?

Edited by Gintas Z.

Share this post


Link to post
Share on other sites
bulletPosX + bulletVelX * time + 0.5 * gravX * time * time = playerPosX + playerVelX * time + 0.5 * gravX * time * time

<==> (subtract '0.5 * gravX * time * time' from both sides)

bulletPosX + bulletVelX * time = playerPosX + playerVelX * time

<==>

 (bulletVelX - playerVelX) * time = playerPosX - bulletPosX

<==>

time = (playerPosX - bulletPosX) / (bulletVelX - playerVelX)

?

Share this post


Link to post
Share on other sites

You have a system of 5 equations and 5 unknowns:

EKbfFX3.png

 

X, Y, bullet_velocity_x, bullet_velocity_y, t are unknown.

Bullet velocity is a shooting direction times initial bullet speed.

 

Or do you want the solution?

Edited by Alex Mekhed

Share this post


Link to post
Share on other sites

@Alberth, damn feeling stupid now, didn't notice that. Ok, so should I be doing it like this?

                float timeX = (aimingAtPlayer.getPosX() - bulletSpawnPos.x) / (bulletVelocity.x - aimingAtPlayer.getVelocity().x);
                float timeY = (aimingAtPlayer.getPosY() - bulletSpawnPos.y) / (bulletVelocity.y - aimingAtPlayer.getVelocity().y);

                float first = bulletSpawnPos.x + bulletVelocity.x * timeX + 0.5f * Constants.WORLD_GRAVITY.x * timeX * timeX;
                float second = aimingAtPlayer.getPosX() + aimingAtPlayer.getVelocity().x * timeX + 0.5f * Constants.WORLD_GRAVITY.x * timeX * timeX;
                float third = bulletSpawnPos.y + bulletVelocity.y * timeX + 0.5f * Constants.WORLD_GRAVITY.y * timeX * timeX;
                float fourth = aimingAtPlayer.getPosY() + aimingAtPlayer.getVelocity().y * timeX + 0.5f * Constants.WORLD_GRAVITY.y * timeX * timeX;
                if(Math.abs(first - second) < 0.1f && Math.abs(third - fourth) < 0.1f)
                {
                    isAimingAtPlayerBlocked = false;
                    // gather direction from vector2(first, second) or vector2(third, fourth)
                }
                else
                    isAimingAtPlayerBlocked = true;

And then do the same checking thing with timeY instead of timeX? Is this mess even efficient? No better way?

Edited by Gintas Z.

Share this post


Link to post
Share on other sites
bulletPosX + bulletVelX * time + 0.5 * gravX * time * time = playerPosX + playerVelX * time + 0.5 * gravX * time * time

<==> (subtract '0.5 * gravX * time * time' from both sides)

bulletPosX + bulletVelX * time = playerPosX + playerVelX * time

<==>

 (bulletVelX - playerVelX) * time = playerPosX - bulletPosX

<==>

time = (playerPosX - bulletPosX) / (bulletVelX - playerVelX)

?

bulletVelX is unknown

Share this post


Link to post
Share on other sites

And then do the same checking thing with timeY instead of timeX? Is this mess even efficient? No better way?
Shouldn't timeX == timeY (with some epsilon) ?

 

That would mean you don't need anything but the two first lines, until you established the time?

Share this post


Link to post
Share on other sites

@Alex it is known. I listed all the things I know in the first post.

Are you sure? Cause:

velocity = shoot direction * speed

You are asking how can you find shoot direction. Then how can velocity be known?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!