# Line Collision In Pygame?

I am working on a game(a platformer) that is physics and momentum based. I want to make it so that the player(a single dot) can bounce off of the lines with correct physics, but to do that, I need to know which line it is touching. Knowing if it is touching a line or not is simple. I just have to check for a white dot where the player is. The problem is that I cannot find out which line the player is touching. I thought of making a ton of rects along each line and testing for the player, but that would cause too much lag. Does anyone have any ideas? :/

• I think a modern CPU can handle 100+ AABB collisions, especially if you optimize it. – Bálint Apr 29 '16 at 14:51
• @Bálint how do you do AABB? – Larry McMuffin Apr 29 '16 at 14:55
• I think Pygame habdles that, it's the simplest type of collision, it works by checking collision between the rectangles around the objects. Are your lines only vertical and horizontal? Or they're at different angles. – Bálint Apr 29 '16 at 15:00
• @Bálint any angle. – Larry McMuffin Apr 29 '16 at 15:08

You could do it as you did above (get the distance to the line and if it's less than some number, they are colliding), or you could see if the player's position is a point on the line. If so, they are colliding. The downside of doing it this way is you have to do intra-frame collision checking (ie if the players speed is 2 pixels, you could miss an intersection with a line 1 pixel wide), IE project the player's path for the next frame as a line segment, and if that line segment intersect a line, the player will intersect with the line within the next frame, so go to that point in time and calculate the collision and how far the players moves afterwards but before the next frame.

As I understand your method the "less than" will cover the situation where a player goes past a line (since the distance will be negative), but that's assuming you cover distance with respect to the orientation of the line (eg lines at the top of the screen are "upside-down" and lines at the bottom are "right-side up;" therefore, being above the top line and below the bottom line will be a "negative distance."

Of course, this is all moot if the player will only ever move one pixel at a time. :)

• I already had code that calculated each pixel the player moved and checked if it collided. As long as you don't have over 100 lines being tested at once, it should run fine. :P Not only that, there is no way to check if the player's position is on the line if you just have the two endpoints of the line without using my way. You failed to even answer the question of how to check if the player is hitting the line because you can't just tell the computer to look at the line and the player and see if they are touching. :/ – Larry McMuffin May 3 '16 at 20:43
• I assumed you would know to use the equation for the intersection of a point and a line, but if you insist I spell it out for you: - Call your two endpoints A and B at coordinates (Ax,Ay) and (Bx,By) respectively. - Call your player's position C at coordinates (Cx,Cy). - The formula of the line is then y-Ay=(By-Ay)/(Bx-Ax)(x-Ax) - The point intersects if Cy-Ay=(By-Ay)/(Bx-Ax)(Cx-Ax) This will always be less complex than making a rectangle encompassing A and B and doing a collision check with C. – codepants May 7 '16 at 2:03
• but that was the question. I figured it out and I wrote out the formula. :/ – Larry McMuffin May 9 '16 at 12:50
• You said "The problem is that I cannot find out which line the player is touching. <...> Does anyone have any ideas?" I did not interpret this to mean you wanted the verbatim equation. So that's my bad for not interpreting appropriately, but next time, please be more precise. :) – codepants May 10 '16 at 18:57

I figured it out. Since lines can be seen as equations, you can detect if the player(or whatever)'s rise is equal(or similar) to the rise of the line. To convert a line to a segment, just make pygame check to see if the player is colliding with a rect that's two corners are the start and end points of the line. Make sure the rect has a positive side though, or .colliderect.

Here is how I calculated it: First, I took checked if the player(or whatever) was in range of the line. (using the previously mentioned method) Then I calculated the rise of the line by dividing the Y length by the X length. I did the same thing for the player, but finding the length of a line from the line's starting point to the player. Next I subtracted the line rise from the player rise. Then I found the absolute of that. If the absolute value(the difference in the rises of the lines) was less than a specific number(based on the width of the line), it was considered a collision. I used 0.1 for a 1 pixel wide line.

It is recommended that you check for each pixel the player moves to see if it is colliding.