Vector Projection

Basically what it does is it takes two vectors and "flattens" one vector onto the other vector.

To project one vector onto the other.

double dot(Vector2 a, Vector2 b) { return a.x * b.x + a.y * b.y; } Vector2 scale(Vector vec, double scalar) { return new Vector2(vec.x * scalar, vec.y * scalar); } Vector2 projectAOntoB(Vector2 a, Vector2 b) { return scale(b, dot(a,b)/dot(b,b)); }

The vector that restricts your movement can be calculated by subtracting the objects position from centers position.

restrictiveDirection = object.position - center;

So then when you go to update the position of the object you want to restrict along the path you simply project the velocity of the object onto the vector that restricts the movement. Then we can check to see if the projected velocity is in the opposite direction of the restrictive direction using the dot product. (dot(a,b) = length(a) * length(b) * cos(angleBetween(a,b)) = a.x * b.x + a.y * b.y)

projectedVelocity = projectAOntoB(object.velocity, restrictiveDirection); if (dot(projectedVelocity, restrictiveDirection) < 0) { // vectors point in opposite directions projectedVelocity = new Vector2(0, 0); } // update the objects position using the new velocity object.position += projectedVelocity * time;

That code will restrict movement along only the line. If you want to restrict movement to the purple region you can modify the last snippet to look like this.

Vector2 newVelocity; if (dot(object.velocity, restrictiveDirection) < 0) { // vectors point in opposite directions // slide object along boundry newVelocity = object.velocity - projectAOntoB(object.velocity, restrictiveDirection); } else { // moving away from center newVelocity = object.velocity; } // update the objects position using the new velocity object.position += newVelocity * time;