Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Given a sprite with an x and y coordinate, how would I move it toward another sprite with an x and y coordinate?

I've already made it face towards the other sprite, and I've made it move towards the other sprite, however because I'm using sin and cos it's circling the player and slowly moving in on them. Here's the method:

Enemy.prototype.update = function(playerX, playerY) {
    // Rotate us to face the player
    this.rotation = Math.atan2(this.y - playerY, this.x - playerX) - 2.35;

    // Move towards the player
    this.x += Math.sin(this.rotation) * this.speed;
    this.y -= Math.cos(this.rotation) * this.speed;
}

How can I get the sprite to just move towards the player in a straight line rather than a circle? I found a good example but it uses XNA Vector2's so it's not working with x and y positions directly.

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

I'm not particularly sure where that 2.35 value is coming from, which could be adding artifacts to your code, so I've removed it from my answers.

That being said, your basic intuition seems to be correct, however you have your sin and cos switched. Also, I'd wager that since you're already taking the difference between two (X,Y) coordinates, that you do not need to subtract the Y value since you're in the reference frame of the sprite itself. Finally, if you're trying to move towards the player, then your vector math is wrong. Given two vectors a and b, (a - b) is the vector in the direction from b to a and (b - a) is the vector in the direction from a to b.

Perhaps what you wanted was:

Enemy.prototype.update = function(playerX, playerY) {
    // Rotate us to face the player
    this.rotation = Math.atan2(playerY - this.y, playerX - this.x);

    // Move towards the player
    this.x += Math.cos(this.rotation) * this.speed;
    this.y += Math.sin(this.rotation) * this.speed;
}

A better way to encode this is to separate the rotation from the movement. If all you're doing is moving towards the player, then you shouldn't be worried about what way you're facing:

Enemy.prototype.update = function(playerX, playerY) {

    // Calculate direction towards player
    toPlayerX = playerX - this.x;
    toPlayerY = playerY - this.y;

    // Normalize
    toPlayerLength = Math.sqrt(toPlayerX * toPlayerX + toPlayerY * toPlayerY);
    toPlayerX = toPlayerX / toPlayerLength;
    toPlayerY = toPlayerY / toPlayerLength;

    // Move towards the player
    this.x += toPlayerX * this.speed;
    this.y += toPlayerY * this.speed;

    // Rotate us to face the player
    this.rotation = Math.atan2(toPlayerY, toPlayerX);
}
share|improve this answer
    
Worked perfect, thanks. The -2.35 is there because the sprite starts off a little off centre, and that's the radians needed to make it look centre. :) –  James Dawson Mar 13 '13 at 20:41
add comment

I would solve this using simple algebra.

Given your sprite's position and the target location you should be able to find the slope of the line that would connect the two coordinates. This can be done using the following equation:

enter image description here

Essentially, the numerator (top number) is going to be velocity you apply on the Y axis and the denominator (bottom number) is going to be the velocity you apply to the X axis. These numbers already have a bit of a bias on speed though and could improperly influence how fast you end up moving. As a result, we want to normalize this into a single unit.

To normalize this into a unit vector you first must find the length of the vector using the equation sqrt((x * ax) + (y * y))

Once you've found the length you can convert it to a unit vector by dividing the x and y values by the length.

Multiply this unit vector by your speed and you should be properly moving towards your target.

In code this would look something like:

var run = playerX - this.x;
var rise = playerY - this.y;
var length = sqrt((rise*rise) + (run*run)); //pseudocode
var unitX = run / length;
var unitY = rise / length;

this.x += unitX * this.speed;
this.y += unitY * this.speed;

You might need to do some fiddling with the sign or the order of the numbers depending on what direction is up, etc. but the concept should apply.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.