GMS 2 Aim In front of Player

Dead Eye

Member
Hello and thank you all for helping. I'm wondering how I would go about making an enemy aim in front of the Player. The turret often rotates to slow to catch up with the player and always misses. My first idea was to put a target object in front of the player but this doesn't work well because the target doesn't help the turret adjust to the speed of the player. Any help would be appreciated, thanks again!
 

Carbiner

Member
Depending on how your movement system works, something like:
Code:
var steps_ahead = 5;
var tar_x = player.x+lengthdir_x(steps_ahead*player.speed,player.direction);
var tar_y = player.y+lengthdir_y(steps_ahead*player.speed,player.direction);
Where tar_x and tar_y are where your turret is trying to aim.
Steps ahead is how far you want the turret to predict the player's position.
 

NightFrost

Member
Note that above works reasonably well only if turret is shooting fast bullets, as you are not taking into account bullet speed or player distance. You probably can arrive at pretty good aim by adjusting steps_ahead by player distance. But if you want a completely accurate solution, you have to do some predictive aiming maths. I recall it requires solving for a triangle where turret is one corner, player is another, and the meeting point is the third. Google should be able to bring up the exact maths.
 
You can get extremely accurate results in situations where both the target and the projectile move at a constant velocity.
If the target is rapidly changing velocity, then this will not be reliable, unless the projectile is moving very fast relative to the target's speed and relative to the distance between the shooter and the target.

we reason that given an accurate firing angle, that at some time ("t") the distance between the shooter and the projectile will be equal to the distance between the shooter and the target. Thus the projectile and the target may be at the same place at the same time (resulting in a collision). And we reason that if we know this time, then we can simply aim the projectile at a location that the target will be occupying at that time.

"p" = (vector) initial Position of target minus initial position of shooter
"v" = (vector) target Velocity
"s" = projectile Speed
"t" = Time
"d" = Distance from shooter at time ("t")
distance squared = (initial target position (minus initial shooter position) + target velocity times time) squared:
d = sqrt((p + v*t)^2)
distance = projectile speed times time:
d = s*t
substitute "d" in ether equation with the right side of the other equation. square both sides to get rid of square root:
(p + v*t)^2 = s^2*t^2
square stuff in parentheses:
p^2 + v^2*t^2 + 2*p*v*t = s^2*t^2
then put whole thing in standard form:
(v^2-s^2)*t^2 + 2*p*v*t + p^2 = 0
use quadratic formula to solve for time ("t") (note: use dot product when multiplying vectors with vectors):
Code:
    //from shooter:
    var _vx = target.hspeed;
    var _vy = target.vspeed;
    var _s = 8;  //any projectile speed above zero is fine.
    var _px = target.x - x;
    var _py = target.y - y;
    //-------------------------------------
    var _a = _vx * _vx + _vy * _vy - _s * _s;  //(v^2-s^2)
    var _b = 2 * (_px * _vx + _py * _vy );     //(2*p*v)
    var _c = _px * _px + _py * _py;           //(p^2)
    //-------------------------------------
    var _disc = _b * _b - 4 * _a * _c;
    if (_disc >= 0) {       //if (_disc < 0) then projectile cannot reach target
        var _t = (-_b - sqrt(_disc)) / (2 * _a);        //doing direct attacks only, not trying to do trick shots where you shoot backwards to hit target
        if (_t > 0) {        //don't shoot if (_t < 0), because that would indicate negative time solutions (and projectile cannot go backwards in time)
            var _aim_x = _px + _vx * _t;
            var _aim_y = _py + _vy * _t;
            with (instance_create(x,y,obj_bullet)) {
                direction = point_direction(0,0,_aim_x,_aim_y);
                speed = _s;
            }
        }
    }
 
Last edited:
Top