首页 > 解决方案 > Move a point toward the mouse

问题描述

enter image description here

(I'm using processing for this but it is not necessarily relevant.)

I'm looking for an algorithm that would take the point A and the point B (B being the mouse cursor position) and use them so that every frame the point A moves a little bit towards B (from -1px to 1px left/right up/down)

I tried x1 += cos(atan((mouseY-y1)/(mouseX-x1))) and the same with sin for y1, but I doesn't seem to work.

If someone has an idea I would appreciate it.

I'm not looking for a built-in function that would do the job, I'd like to understand the math behind it.

Thank you for your time.

标签: javamathprocessing

解决方案


It is important that the point coordinates are floating point values:

float x = 0.0, y= 0.0;

For the computation of the movement of the point, I recommend to use PVector.

Setup 2 vectors, for the point and the mouse position:

PVector Pt = new PVector(x, y);
PVector Pm = new PVector(mouseX, mouseY);

Calculate the Unit vector from Pt to Pm:

PVector D = PVector.sub(Pm, Pt);
D.normalize();

Calculate the new point by newPt = Pt + D * min(speed, dist), but ensure that the point moves not further than the Euclidean distance to the mouse:

float speed = 3;
float movelen = min(PVector.dist(Pt, Pm), speed);
PVector newPt = PVector.add(Pt, D.mult(movelen));

The same can be achieved by arithmetic operations

float dx = mouseX - x;
float dy = mouseY - y;
float dist = sqrt(dx*dx + dy*dy);
if (dist > 0) {
    float movelen = min(dist, speed);
    x += dx/dist * movelen;
    y += dy/dist * movelen;
}

(dx,dy) is the vector from the point to the mouse and dist ist the Euclidean distance between the 2 points. A Unit vector can be calculated by dividing a vector by its magnitude, so (dx/dist, dy/dist) is the unit direction vector. Finally (dx/dist * movelen, dx/dist * movelen) is the same as D * movelen.

See the example:
(the code works for any speed, even below 1.0)

float x = 0.0, y= 0.0;

void setup() {
    size(300, 300);
    x = (float)random(width);
    y = (float)random(height);
}

void draw() {
    float speed = 3;

    /*
    //setup points
    PVector Pt = new PVector(x, y);
    PVector Pm = new PVector(mouseX, mouseY);

    // calcualte normalized direction
    PVector D = PVector.sub(Pm, Pt);
    D.normalize();

    // calcualte new point
    float movelen = min(PVector.dist(Pt, Pm), speed);
    PVector newPt = PVector.add(Pt, D.mult(movelen));
    x = newPt.x;
    y = newPt.y;
    */

    float dx = mouseX - x;
    float dy = mouseY - y;
    float dist = sqrt(dx*dx + dy*dy);
    if (dist > 0) {
        float movelen = min(dist, speed);
        x += dx/dist * movelen;
        y += dy/dist * movelen;
    }

    background(196);
    stroke(0);
    fill(255, 0, 0);
    ellipse((int)x, (int)y, 10, 10);
    fill(0, 255, 0);
    ellipse(mouseX, mouseY, 10, 10);
}

推荐阅读