Detect collision with lines and limit movement












1














I'm making a game with libGDX in Java. I'm trying to make a collision detection. As you can see in the image, I have a line which is a wall and a player with specified radius. The desired position is the next location which the player is trying to be in. But because there is a wall, he's placed in the Actual Position which is on the Velocity vector, but more closer to the prev location. I'm trying to figure out how can I detect that closer position?
enter image description here



My attempt:



private void move(float deltaTime) {
float step;
beginMovementAltitude();
if (playerComponent.isWalking())
step = handleAcceleration(playerComponent.getSpeed() + playerComponent.getAcceleration());
else step = handleDeacceleration(playerComponent.getSpeed(), playerComponent.getAcceleration());
playerComponent.setSpeed(step);
if (step == 0) return;
takeStep(deltaTime, step, 0);
}
private void takeStep(float deltaTime, float step, int rotate) {
Vector3 position = playerComponent.getCamera().position;
float x = position.x;
float y = position.y;
int radius = playerComponent.getRadius();
auxEnvelope.init(x, x + radius, y, y + radius);
List<Line> nearbyLines = lines.query(auxEnvelope);
float theta;
int numberOfIntersections = 0;
float angleToMove = 0;
Gdx.app.log(step + "", "");
for (Line line : nearbyLines) {
VertexElement src = line.getSrc();
VertexElement dst = line.getDst();
auxVector3.set(playerComponent.getCamera().direction);
auxVector3.rotate(Vector3.Z, rotate);
float nextX = x + (step * deltaTime) * (auxVector3.x);
float nextY = y + (step * deltaTime) * playerComponent.getCamera().direction.y;
float dis = Intersector.distanceLinePoint(src.getX(), src.getY(), dst.getX(), dst.getY(), nextX, nextY);
boolean bodyIntersection = dis <= 0.5f;
auxVector21.set(src.getX(), src.getY());
auxVector22.set(dst.getX(), dst.getY());
auxVector23.set(nextX, nextY);
if (bodyIntersection) {
numberOfIntersections++;
if (numberOfIntersections > 1) {
return;
}
theta = auxVector22.sub(auxVector21).nor().angle();
float angle = (float) (180.0 / MathUtils.PI * MathUtils.atan2(auxVector23.y - position.y, auxVector23.x - position.x));
if (angle < 0) angle += 360;
float diff = (theta > angle) ? theta - angle : angle - theta;
if (step < 0) step *=-1;
angleToMove = (diff > 90) ? theta + 180 : theta;
}
}
if (numberOfIntersections == 0) {
moveCameraByWalking(deltaTime, step, rotate);
} else {
moveCameraInDirection(deltaTime, step, angleToMove);
}
}









share|improve this question
























  • What did you try, what is your error?
    – michaeak
    Nov 13 at 7:22










  • In the link you gave I didn't see relevant part to put the player in the "fixed" position. What I tried at the beginning is to check if the next position is in distance from wall smaller than radius. If true, I won't let the player move there. This behavior is fine if the speed of player is fixed. But in my game the speed is accelerating and decelerating according to input - so what happens is the player doesn't move if the speed is high but when it is low it does (making some "joggy" movement effect when decelerating near the wall)
    – Gad Wissberg
    Nov 13 at 7:27










  • Can you please provide the code for this attempt you described in the question?
    – michaeak
    Nov 13 at 7:28










  • Yes, posted to the question
    – Gad Wissberg
    Nov 13 at 7:32










  • In the first method it seems a lot of lines are duplicated, is this the actual code? I guess not, as this would not compile (duplicate variable name). Same applies to the second method
    – michaeak
    Nov 13 at 7:33


















1














I'm making a game with libGDX in Java. I'm trying to make a collision detection. As you can see in the image, I have a line which is a wall and a player with specified radius. The desired position is the next location which the player is trying to be in. But because there is a wall, he's placed in the Actual Position which is on the Velocity vector, but more closer to the prev location. I'm trying to figure out how can I detect that closer position?
enter image description here



My attempt:



private void move(float deltaTime) {
float step;
beginMovementAltitude();
if (playerComponent.isWalking())
step = handleAcceleration(playerComponent.getSpeed() + playerComponent.getAcceleration());
else step = handleDeacceleration(playerComponent.getSpeed(), playerComponent.getAcceleration());
playerComponent.setSpeed(step);
if (step == 0) return;
takeStep(deltaTime, step, 0);
}
private void takeStep(float deltaTime, float step, int rotate) {
Vector3 position = playerComponent.getCamera().position;
float x = position.x;
float y = position.y;
int radius = playerComponent.getRadius();
auxEnvelope.init(x, x + radius, y, y + radius);
List<Line> nearbyLines = lines.query(auxEnvelope);
float theta;
int numberOfIntersections = 0;
float angleToMove = 0;
Gdx.app.log(step + "", "");
for (Line line : nearbyLines) {
VertexElement src = line.getSrc();
VertexElement dst = line.getDst();
auxVector3.set(playerComponent.getCamera().direction);
auxVector3.rotate(Vector3.Z, rotate);
float nextX = x + (step * deltaTime) * (auxVector3.x);
float nextY = y + (step * deltaTime) * playerComponent.getCamera().direction.y;
float dis = Intersector.distanceLinePoint(src.getX(), src.getY(), dst.getX(), dst.getY(), nextX, nextY);
boolean bodyIntersection = dis <= 0.5f;
auxVector21.set(src.getX(), src.getY());
auxVector22.set(dst.getX(), dst.getY());
auxVector23.set(nextX, nextY);
if (bodyIntersection) {
numberOfIntersections++;
if (numberOfIntersections > 1) {
return;
}
theta = auxVector22.sub(auxVector21).nor().angle();
float angle = (float) (180.0 / MathUtils.PI * MathUtils.atan2(auxVector23.y - position.y, auxVector23.x - position.x));
if (angle < 0) angle += 360;
float diff = (theta > angle) ? theta - angle : angle - theta;
if (step < 0) step *=-1;
angleToMove = (diff > 90) ? theta + 180 : theta;
}
}
if (numberOfIntersections == 0) {
moveCameraByWalking(deltaTime, step, rotate);
} else {
moveCameraInDirection(deltaTime, step, angleToMove);
}
}









share|improve this question
























  • What did you try, what is your error?
    – michaeak
    Nov 13 at 7:22










  • In the link you gave I didn't see relevant part to put the player in the "fixed" position. What I tried at the beginning is to check if the next position is in distance from wall smaller than radius. If true, I won't let the player move there. This behavior is fine if the speed of player is fixed. But in my game the speed is accelerating and decelerating according to input - so what happens is the player doesn't move if the speed is high but when it is low it does (making some "joggy" movement effect when decelerating near the wall)
    – Gad Wissberg
    Nov 13 at 7:27










  • Can you please provide the code for this attempt you described in the question?
    – michaeak
    Nov 13 at 7:28










  • Yes, posted to the question
    – Gad Wissberg
    Nov 13 at 7:32










  • In the first method it seems a lot of lines are duplicated, is this the actual code? I guess not, as this would not compile (duplicate variable name). Same applies to the second method
    – michaeak
    Nov 13 at 7:33
















1












1








1







I'm making a game with libGDX in Java. I'm trying to make a collision detection. As you can see in the image, I have a line which is a wall and a player with specified radius. The desired position is the next location which the player is trying to be in. But because there is a wall, he's placed in the Actual Position which is on the Velocity vector, but more closer to the prev location. I'm trying to figure out how can I detect that closer position?
enter image description here



My attempt:



private void move(float deltaTime) {
float step;
beginMovementAltitude();
if (playerComponent.isWalking())
step = handleAcceleration(playerComponent.getSpeed() + playerComponent.getAcceleration());
else step = handleDeacceleration(playerComponent.getSpeed(), playerComponent.getAcceleration());
playerComponent.setSpeed(step);
if (step == 0) return;
takeStep(deltaTime, step, 0);
}
private void takeStep(float deltaTime, float step, int rotate) {
Vector3 position = playerComponent.getCamera().position;
float x = position.x;
float y = position.y;
int radius = playerComponent.getRadius();
auxEnvelope.init(x, x + radius, y, y + radius);
List<Line> nearbyLines = lines.query(auxEnvelope);
float theta;
int numberOfIntersections = 0;
float angleToMove = 0;
Gdx.app.log(step + "", "");
for (Line line : nearbyLines) {
VertexElement src = line.getSrc();
VertexElement dst = line.getDst();
auxVector3.set(playerComponent.getCamera().direction);
auxVector3.rotate(Vector3.Z, rotate);
float nextX = x + (step * deltaTime) * (auxVector3.x);
float nextY = y + (step * deltaTime) * playerComponent.getCamera().direction.y;
float dis = Intersector.distanceLinePoint(src.getX(), src.getY(), dst.getX(), dst.getY(), nextX, nextY);
boolean bodyIntersection = dis <= 0.5f;
auxVector21.set(src.getX(), src.getY());
auxVector22.set(dst.getX(), dst.getY());
auxVector23.set(nextX, nextY);
if (bodyIntersection) {
numberOfIntersections++;
if (numberOfIntersections > 1) {
return;
}
theta = auxVector22.sub(auxVector21).nor().angle();
float angle = (float) (180.0 / MathUtils.PI * MathUtils.atan2(auxVector23.y - position.y, auxVector23.x - position.x));
if (angle < 0) angle += 360;
float diff = (theta > angle) ? theta - angle : angle - theta;
if (step < 0) step *=-1;
angleToMove = (diff > 90) ? theta + 180 : theta;
}
}
if (numberOfIntersections == 0) {
moveCameraByWalking(deltaTime, step, rotate);
} else {
moveCameraInDirection(deltaTime, step, angleToMove);
}
}









share|improve this question















I'm making a game with libGDX in Java. I'm trying to make a collision detection. As you can see in the image, I have a line which is a wall and a player with specified radius. The desired position is the next location which the player is trying to be in. But because there is a wall, he's placed in the Actual Position which is on the Velocity vector, but more closer to the prev location. I'm trying to figure out how can I detect that closer position?
enter image description here



My attempt:



private void move(float deltaTime) {
float step;
beginMovementAltitude();
if (playerComponent.isWalking())
step = handleAcceleration(playerComponent.getSpeed() + playerComponent.getAcceleration());
else step = handleDeacceleration(playerComponent.getSpeed(), playerComponent.getAcceleration());
playerComponent.setSpeed(step);
if (step == 0) return;
takeStep(deltaTime, step, 0);
}
private void takeStep(float deltaTime, float step, int rotate) {
Vector3 position = playerComponent.getCamera().position;
float x = position.x;
float y = position.y;
int radius = playerComponent.getRadius();
auxEnvelope.init(x, x + radius, y, y + radius);
List<Line> nearbyLines = lines.query(auxEnvelope);
float theta;
int numberOfIntersections = 0;
float angleToMove = 0;
Gdx.app.log(step + "", "");
for (Line line : nearbyLines) {
VertexElement src = line.getSrc();
VertexElement dst = line.getDst();
auxVector3.set(playerComponent.getCamera().direction);
auxVector3.rotate(Vector3.Z, rotate);
float nextX = x + (step * deltaTime) * (auxVector3.x);
float nextY = y + (step * deltaTime) * playerComponent.getCamera().direction.y;
float dis = Intersector.distanceLinePoint(src.getX(), src.getY(), dst.getX(), dst.getY(), nextX, nextY);
boolean bodyIntersection = dis <= 0.5f;
auxVector21.set(src.getX(), src.getY());
auxVector22.set(dst.getX(), dst.getY());
auxVector23.set(nextX, nextY);
if (bodyIntersection) {
numberOfIntersections++;
if (numberOfIntersections > 1) {
return;
}
theta = auxVector22.sub(auxVector21).nor().angle();
float angle = (float) (180.0 / MathUtils.PI * MathUtils.atan2(auxVector23.y - position.y, auxVector23.x - position.x));
if (angle < 0) angle += 360;
float diff = (theta > angle) ? theta - angle : angle - theta;
if (step < 0) step *=-1;
angleToMove = (diff > 90) ? theta + 180 : theta;
}
}
if (numberOfIntersections == 0) {
moveCameraByWalking(deltaTime, step, rotate);
} else {
moveCameraInDirection(deltaTime, step, angleToMove);
}
}






java libgdx 2d collision-detection






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 at 7:45

























asked Nov 13 at 7:02









Gad Wissberg

6117




6117












  • What did you try, what is your error?
    – michaeak
    Nov 13 at 7:22










  • In the link you gave I didn't see relevant part to put the player in the "fixed" position. What I tried at the beginning is to check if the next position is in distance from wall smaller than radius. If true, I won't let the player move there. This behavior is fine if the speed of player is fixed. But in my game the speed is accelerating and decelerating according to input - so what happens is the player doesn't move if the speed is high but when it is low it does (making some "joggy" movement effect when decelerating near the wall)
    – Gad Wissberg
    Nov 13 at 7:27










  • Can you please provide the code for this attempt you described in the question?
    – michaeak
    Nov 13 at 7:28










  • Yes, posted to the question
    – Gad Wissberg
    Nov 13 at 7:32










  • In the first method it seems a lot of lines are duplicated, is this the actual code? I guess not, as this would not compile (duplicate variable name). Same applies to the second method
    – michaeak
    Nov 13 at 7:33




















  • What did you try, what is your error?
    – michaeak
    Nov 13 at 7:22










  • In the link you gave I didn't see relevant part to put the player in the "fixed" position. What I tried at the beginning is to check if the next position is in distance from wall smaller than radius. If true, I won't let the player move there. This behavior is fine if the speed of player is fixed. But in my game the speed is accelerating and decelerating according to input - so what happens is the player doesn't move if the speed is high but when it is low it does (making some "joggy" movement effect when decelerating near the wall)
    – Gad Wissberg
    Nov 13 at 7:27










  • Can you please provide the code for this attempt you described in the question?
    – michaeak
    Nov 13 at 7:28










  • Yes, posted to the question
    – Gad Wissberg
    Nov 13 at 7:32










  • In the first method it seems a lot of lines are duplicated, is this the actual code? I guess not, as this would not compile (duplicate variable name). Same applies to the second method
    – michaeak
    Nov 13 at 7:33


















What did you try, what is your error?
– michaeak
Nov 13 at 7:22




What did you try, what is your error?
– michaeak
Nov 13 at 7:22












In the link you gave I didn't see relevant part to put the player in the "fixed" position. What I tried at the beginning is to check if the next position is in distance from wall smaller than radius. If true, I won't let the player move there. This behavior is fine if the speed of player is fixed. But in my game the speed is accelerating and decelerating according to input - so what happens is the player doesn't move if the speed is high but when it is low it does (making some "joggy" movement effect when decelerating near the wall)
– Gad Wissberg
Nov 13 at 7:27




In the link you gave I didn't see relevant part to put the player in the "fixed" position. What I tried at the beginning is to check if the next position is in distance from wall smaller than radius. If true, I won't let the player move there. This behavior is fine if the speed of player is fixed. But in my game the speed is accelerating and decelerating according to input - so what happens is the player doesn't move if the speed is high but when it is low it does (making some "joggy" movement effect when decelerating near the wall)
– Gad Wissberg
Nov 13 at 7:27












Can you please provide the code for this attempt you described in the question?
– michaeak
Nov 13 at 7:28




Can you please provide the code for this attempt you described in the question?
– michaeak
Nov 13 at 7:28












Yes, posted to the question
– Gad Wissberg
Nov 13 at 7:32




Yes, posted to the question
– Gad Wissberg
Nov 13 at 7:32












In the first method it seems a lot of lines are duplicated, is this the actual code? I guess not, as this would not compile (duplicate variable name). Same applies to the second method
– michaeak
Nov 13 at 7:33






In the first method it seems a lot of lines are duplicated, is this the actual code? I guess not, as this would not compile (duplicate variable name). Same applies to the second method
– michaeak
Nov 13 at 7:33














1 Answer
1






active

oldest

votes


















1














The idea is to find intersection of path of object center and the line moved by radius of the circle, see that picture.



this is the idea



At first, you need to find a normal to the line. How to do it, depends on how the line is defined, if it's defined by two points, the formula is



nx = ay - by
ny = bx - ax


If the line is defined by canonical equation, then coefficients at x and y define normal, if I remembered correctly.



When normal is found, we need to normalize it - set length to 1 by dividing coordinates by vector length. Let it be n.



Then, we will project starting point, desired point and randomly chosen point on line to n, treating them as radius vectors.



Projection of vector a to vector b is



project (a, b) = scalar_product (a, b) / length (b)**2 * b


but since b is n which length equals 1, we will not apply division, and also we want to only find length of the result, we do not multiply by b. So we only compute scalar product with n for each of three aforementioned points, getting three numbers, let s be the result for starting point, d for desired point, l for chosen point on the line.



Then we should modify l by radius of the circle:



if      (s < d) l -= r;
else if (s > d) l += r;


If s = d, your object moves in parallel along the line, so line can't obstruct its movement. It's highly improbable case but should be dealt with.



Also, that's important, if l was initially between s and d but after modifying is no longer between then, it's a special case you may want to handle (restrict object movement for example)



corner case



Ather that, you should compute (d - s) / (l - s).



If the result is greater or equals 1, the object will not reach the line.

If the result is between 0 and 1, the line obstructs movement and the result indicates part of the path the object will complete. 0.5 means that object will stop halfway.

If the result is negative, it means the line is behind the object and will not obstruct movement.



Note that when using floating point numbers the result will not be perfectly precise, that's why we handle that special case. If you want to prevent this from happening at all, organize loop and try approximations until needed precision is reached.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53275516%2fdetect-collision-with-lines-and-limit-movement%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    The idea is to find intersection of path of object center and the line moved by radius of the circle, see that picture.



    this is the idea



    At first, you need to find a normal to the line. How to do it, depends on how the line is defined, if it's defined by two points, the formula is



    nx = ay - by
    ny = bx - ax


    If the line is defined by canonical equation, then coefficients at x and y define normal, if I remembered correctly.



    When normal is found, we need to normalize it - set length to 1 by dividing coordinates by vector length. Let it be n.



    Then, we will project starting point, desired point and randomly chosen point on line to n, treating them as radius vectors.



    Projection of vector a to vector b is



    project (a, b) = scalar_product (a, b) / length (b)**2 * b


    but since b is n which length equals 1, we will not apply division, and also we want to only find length of the result, we do not multiply by b. So we only compute scalar product with n for each of three aforementioned points, getting three numbers, let s be the result for starting point, d for desired point, l for chosen point on the line.



    Then we should modify l by radius of the circle:



    if      (s < d) l -= r;
    else if (s > d) l += r;


    If s = d, your object moves in parallel along the line, so line can't obstruct its movement. It's highly improbable case but should be dealt with.



    Also, that's important, if l was initially between s and d but after modifying is no longer between then, it's a special case you may want to handle (restrict object movement for example)



    corner case



    Ather that, you should compute (d - s) / (l - s).



    If the result is greater or equals 1, the object will not reach the line.

    If the result is between 0 and 1, the line obstructs movement and the result indicates part of the path the object will complete. 0.5 means that object will stop halfway.

    If the result is negative, it means the line is behind the object and will not obstruct movement.



    Note that when using floating point numbers the result will not be perfectly precise, that's why we handle that special case. If you want to prevent this from happening at all, organize loop and try approximations until needed precision is reached.






    share|improve this answer


























      1














      The idea is to find intersection of path of object center and the line moved by radius of the circle, see that picture.



      this is the idea



      At first, you need to find a normal to the line. How to do it, depends on how the line is defined, if it's defined by two points, the formula is



      nx = ay - by
      ny = bx - ax


      If the line is defined by canonical equation, then coefficients at x and y define normal, if I remembered correctly.



      When normal is found, we need to normalize it - set length to 1 by dividing coordinates by vector length. Let it be n.



      Then, we will project starting point, desired point and randomly chosen point on line to n, treating them as radius vectors.



      Projection of vector a to vector b is



      project (a, b) = scalar_product (a, b) / length (b)**2 * b


      but since b is n which length equals 1, we will not apply division, and also we want to only find length of the result, we do not multiply by b. So we only compute scalar product with n for each of three aforementioned points, getting three numbers, let s be the result for starting point, d for desired point, l for chosen point on the line.



      Then we should modify l by radius of the circle:



      if      (s < d) l -= r;
      else if (s > d) l += r;


      If s = d, your object moves in parallel along the line, so line can't obstruct its movement. It's highly improbable case but should be dealt with.



      Also, that's important, if l was initially between s and d but after modifying is no longer between then, it's a special case you may want to handle (restrict object movement for example)



      corner case



      Ather that, you should compute (d - s) / (l - s).



      If the result is greater or equals 1, the object will not reach the line.

      If the result is between 0 and 1, the line obstructs movement and the result indicates part of the path the object will complete. 0.5 means that object will stop halfway.

      If the result is negative, it means the line is behind the object and will not obstruct movement.



      Note that when using floating point numbers the result will not be perfectly precise, that's why we handle that special case. If you want to prevent this from happening at all, organize loop and try approximations until needed precision is reached.






      share|improve this answer
























        1












        1








        1






        The idea is to find intersection of path of object center and the line moved by radius of the circle, see that picture.



        this is the idea



        At first, you need to find a normal to the line. How to do it, depends on how the line is defined, if it's defined by two points, the formula is



        nx = ay - by
        ny = bx - ax


        If the line is defined by canonical equation, then coefficients at x and y define normal, if I remembered correctly.



        When normal is found, we need to normalize it - set length to 1 by dividing coordinates by vector length. Let it be n.



        Then, we will project starting point, desired point and randomly chosen point on line to n, treating them as radius vectors.



        Projection of vector a to vector b is



        project (a, b) = scalar_product (a, b) / length (b)**2 * b


        but since b is n which length equals 1, we will not apply division, and also we want to only find length of the result, we do not multiply by b. So we only compute scalar product with n for each of three aforementioned points, getting three numbers, let s be the result for starting point, d for desired point, l for chosen point on the line.



        Then we should modify l by radius of the circle:



        if      (s < d) l -= r;
        else if (s > d) l += r;


        If s = d, your object moves in parallel along the line, so line can't obstruct its movement. It's highly improbable case but should be dealt with.



        Also, that's important, if l was initially between s and d but after modifying is no longer between then, it's a special case you may want to handle (restrict object movement for example)



        corner case



        Ather that, you should compute (d - s) / (l - s).



        If the result is greater or equals 1, the object will not reach the line.

        If the result is between 0 and 1, the line obstructs movement and the result indicates part of the path the object will complete. 0.5 means that object will stop halfway.

        If the result is negative, it means the line is behind the object and will not obstruct movement.



        Note that when using floating point numbers the result will not be perfectly precise, that's why we handle that special case. If you want to prevent this from happening at all, organize loop and try approximations until needed precision is reached.






        share|improve this answer












        The idea is to find intersection of path of object center and the line moved by radius of the circle, see that picture.



        this is the idea



        At first, you need to find a normal to the line. How to do it, depends on how the line is defined, if it's defined by two points, the formula is



        nx = ay - by
        ny = bx - ax


        If the line is defined by canonical equation, then coefficients at x and y define normal, if I remembered correctly.



        When normal is found, we need to normalize it - set length to 1 by dividing coordinates by vector length. Let it be n.



        Then, we will project starting point, desired point and randomly chosen point on line to n, treating them as radius vectors.



        Projection of vector a to vector b is



        project (a, b) = scalar_product (a, b) / length (b)**2 * b


        but since b is n which length equals 1, we will not apply division, and also we want to only find length of the result, we do not multiply by b. So we only compute scalar product with n for each of three aforementioned points, getting three numbers, let s be the result for starting point, d for desired point, l for chosen point on the line.



        Then we should modify l by radius of the circle:



        if      (s < d) l -= r;
        else if (s > d) l += r;


        If s = d, your object moves in parallel along the line, so line can't obstruct its movement. It's highly improbable case but should be dealt with.



        Also, that's important, if l was initially between s and d but after modifying is no longer between then, it's a special case you may want to handle (restrict object movement for example)



        corner case



        Ather that, you should compute (d - s) / (l - s).



        If the result is greater or equals 1, the object will not reach the line.

        If the result is between 0 and 1, the line obstructs movement and the result indicates part of the path the object will complete. 0.5 means that object will stop halfway.

        If the result is negative, it means the line is behind the object and will not obstruct movement.



        Note that when using floating point numbers the result will not be perfectly precise, that's why we handle that special case. If you want to prevent this from happening at all, organize loop and try approximations until needed precision is reached.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 20 at 10:16









        trollingchar

        1616




        1616






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53275516%2fdetect-collision-with-lines-and-limit-movement%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Guess what letter conforming each word

            Port of Spain

            Run scheduled task as local user group (not BUILTIN)