It happens because your code thinks the circle is going at max velocity when it's actually sitting still.
Here's your code instrumented to show the last amount that each line collision moved the circle. If you put the circle on top of the two lines and hold the down arrow, you'll see that they stabilize at (0.58, -1.02) and (-0.58, -3.78
).
I didn't show vx and vy, but if I did, you'd see that they're (0, 4.8
).
So every frame the velocity moves the circle by (0, 4.8
). Then the first line pushes the circle up and right so it doesn't overlap. Then the second line pushes it up and back left. Then the circle moves around until it finds a balance point where they all cancel out.
You'll notice that if you let go of the keys, the circle settles back down (as the velocity is killed by the "friction") until it's resting nicely on the lines.
Does that make sense at all?
To fix it...your best bet might be to use a Verlet integration step instead of the symplectic Euler step you're using now. The Verlet works from the current and previous positions, and doesn't store the velocity, so you tend to get less of these problems where the position and the velocity don't match up.
Euler:
x = x + v*dt
v = v + a*dt
Symplectic or semi-implicit Euler:
(uses the next velocity instead of the previous one,
which makes it conserve energy better)
v = v + a*dt
x = x + v*dt
Verlet:
x = x + (x - old_x) + a*dt*dt
Hope that helps!