# Accuracy Variable when using look_at() for targeting

v4.1.3

### Question

Hello!
I have a 2d top-down game that has the player target enemies with a gun using their mouse cursor.
Currently I have the player’s weapon looking at the mouse cursor, with the following code:

var accuracy = 25 # lower is more accurate
var lerpFactor = 0.1 #smoothing for aim accuracy

func _process(_delta):
var target = get_global_mouse_position()
var aimedTarget = target + Vector2(randf_range(-accuracy, accuracy), randf_range(-accuracy, accuracy))
look_at(lerp(aimedTarget, target, lerpFactor))

This targeting has the “gun” looking at the global mouse position and lerping between that location and the accuracy value.
The problem is that the closer the target is to the player, the worse the accuracy gets, and i am not sure how to fix that.
Preferably I would like the accuracy to stay the same regardless of the distance to the player, or get better the closer the target position is.
Any advice on how to accomplish that?

Hi! So the issue is a mathematical/logical one. If you consider your player at the “origin”, or in other words, at 0, 0, then a target that is 50 pixels along the x axis away could (in the extremes) be at either 25, 50 or -25, 50, which if you calculate it would give you an angle variance of around 90 degrees! Where as a larger distance would result in a smaller angle.

There are two things you could do:

1. Include distance in your calculation,
``````var frame_accuracy = accuracy * target.distance_to(global_position) * 0.1
var aimedTarget = target + Vector2(randf_range(-frame_accuracy, frame_accuracy), randf_range(-frame_accuracy, frame_accuracy))
``````

You would probably need to change the values, maybe use a remap so it goes from a “close” accuracy to another based on distance.

``````lerp_angle(rotation, rotation + randf(accuracy), lerpFactor)
``````

If I was doing this, I would choose option 2, unless I wanted to get a cursor showing for the target.

1 Like

Thank you for the info! I will try these and see!

So, if anyone else stumbles across this post and wonders how I fixed it… Well I ended up completely changing the way the “gun” handles aiming and accuracy.

So if you are looking for a way to have a 2D gun or projectile firing weapon aim and fire, here is how I did it:

First, the weapon has an Area2D node that gives it its range, and it uses that range area to look for targets, and then find the closest target.
The code for this looks like this:

First I stored all the targets in range in an array:

``````func findEnemies():
var enemies = []
var bodies = \$Area2D.get_overlapping_bodies()
for body in bodies:
if body.is_in_group("Enemy"):
enemies.append(body)
``````

Then I used this code to look for the closest enemy.

``````func findClosestEnemy():
var closestDistance = INF
var closestEnemy = null
if enemies.size() > 0:
for enemy in enemies:
if enemy != null and enemy.is_in_group("Enemy"):
var enemyHealthNode = enemy.get_child(1)
if enemyHealthNode.currentHealth > 0:
var distance = player.global_position.distance_to(enemy.global_position)
if distance < closestDistance:
closestDistance = distance
closestEnemy = enemy
``````

Once I had the closest target, I could then use this code to rotate the gun/weapon to look at the target.
You can use the lerp() function to control how fast you want the rotation to happen, so mess with the final value to get the feel you want.

``````if closestEnemy:
#find position of closest enemy
var targetEnemy = closestEnemy.position
#get vector from self to enemy
var v = targetEnemy - global_position
#get angle of vector
var angle = v.angle()
#get current rotation
var r = global_rotation
#get angle to target
angle = lerp_angle(r, angle, .06)
#set rotation
global_rotation = angle
``````

**Also, my initial desire was to use the mouse position as the target, and I forgot to mention that this is still possible with this code! Simply replace the first two lines of code from the block above with the following:

``````#get mouse cursor position
var mousePos = get_global_mouse_position()
#get vector from self to mouse position
var v = mousePos - global_position
``````

So all that handles rotation to look at the target, but it does not handle accuracy! How did I do that you ask? Well, I ended up modifying the way the projectile fired by the gun spawns to control the accuracy.
Here is how I did this:

``````#variables
var accuracy = .1
var currentAmmo = 30

func shoot():
if currentAmmo > 0:
var b = Bullet.instantiate()