hi, i’m trying to make an enemy shoot where the player is going instead of where they are, however when i stay still the bullet dosen’t move at all and if i move the bullet shoots in the wrong direction.
ok, the behavior has improved a lot now, it still isn’t perfect, but i prefer the enemies to have imperfect aim, at least now they are trying to hit you
i’ll leave the code here in case someone needs it
##predics where the target will be and attacks there
func attackWithPrediction(target: Entity) -> void:
var bullet: Projectile = NEEDLE.instantiate()
bullet.global_position = global_position
bullet.direction = interceptTarget(target.global_position,global_position,target.velocity,bullet.speed)
if not bullet.direction.is_zero_approx():
get_tree().root.add_child(bullet)
##uses data to intercept target and returns the predicted location
func interceptTarget(targetPosition: Vector2,shooterPosition: Vector2, targetVelocity: Vector2,projectileSpeed: float) -> Vector2:
var targetToShooter: Vector2 = shooterPosition - targetPosition
var DC: float = targetToShooter.length()
var alpha: float = targetPosition.angle_to(targetVelocity)
var SA: float = targetVelocity.length()
var r: float = SA / projectileSpeed
var positionToShoot: Vector2 = aimMath.solveQuadratic(1 - r * r,2 * r * DC * cos(alpha),-(DC * DC))
var directionToShoot: float = max(positionToShoot.x,positionToShoot.y)
var timeToHit: float = directionToShoot / projectileSpeed
var predictedTargetLocation: Vector2 = targetPosition + targetVelocity * timeToHit
return shooterPosition.direction_to(predictedTargetLocation)
class aimMath:
##retruns a vector containing (root1,root2)
static func solveQuadratic(a: float, b: float, c: float) -> Vector2:
var root1: float
var root2: float
var discriminant: float = b * b - 4 * a * c
if discriminant < 0:
return Vector2(0,0)
else:
root1 = (-b + sqrt(discriminant))/(2 * a)
root2 = (-b - sqrt(discriminant))/(2 * a)
return Vector2(root1,root2)
Unfortunately I don’t know how to fix your current function, I wish I could but, I can share a resource that worked for me when I implemented such a feature a few years ago on a project of mine.
I used that video which worked like a charm, it’s made in Unity but the maths will be the same for any engine, you’ll just need to translate the code to GDScript which should be fairly easy.
In your current code, the bullet’s direction will always be set to the direction of the target’s velocity.
When calculating the predictedPosition, you need to add the target’s current position.
And bullet.direction should receive the direction towards the predictedPosition (instead of just the normalized position).
(This is still a very rough estimation for the bullet’s direction. If you need something more precise, you should take a look at the video @sixrobin shared.)
func attackWithPrediction(target: Entity) -> void:
var bullet: Projectile = NEEDLE.instantiate()
var timeToHit: float
var predictedPosition: Vector2
bullet.global_position = global_position
timeToHit = global_position.distance_to(target.global_position) / bullet.speed
# This is incorrect:
# predictedPosition = target.velocity * timeToHit
# bullet.direction = predictedPosition.normalized()
# This is what you wanted:
predictedPosition = target.global_position + target.velocity * timeToHit
bullet.direction = global_position.direction_to(predictedPosition)
get_tree().root.add_child(bullet)
However, you’ll see that it still doesn’t work correctly and this is because you are calculating the travel time of the bullet to the position where the player WAS at the time of shooting the bullet, which is not where he WILL BE when the bullet reaches that place, if he continues to move.
That’s where it gets a little more complicated, as we’re entering trigonometry and that’s where @sixrobin’s video comes into play to properly fix it.