I recommend do calculate the reflection vector to the incident vector on the circular surface.
In the following formula N
is the normal vector of the circle, I
is the incident vector (the current direction vector of the bouncing ball) and R
is the reflection vector (outgoing direction vector of the bouncing ball):
R = I - 2.0 * dot(N, I) * N.
Use the pygame.math.Vector2
.
To calculate the normal vector, you' ve to know the "hit" point (dvx
, dvy
) and the center point of the circle (cptx
, cpty
):
circN = (pygame.math.Vector2(cptx - px, cpty - py)).normalize()
Calculate the reflection:
vecR = vecI - 2 * circN.dot(vecI) * circN
The new angle can be calculated by math.atan2(y, x)
:
self.angle = math.atan2(vecR[1], vecR[0])
Code listing:
import math
import pygame
px = [...] # x coordinate of the "hit" point on the circle
py = [...] # y coordinate of the "hit" point on the circle
cptx = [...] # x coordinate of the center point of the circle
cpty = [...] # y coordinate of the center point of the circle
circN = (pygame.math.Vector2(cptx - px, cpty - py)).normalize()
vecI = pygame.math.Vector2(math.cos(self.angle), math.sin(self.angle))
vecR = vecI - 2 * circN.dot(vecI) * circN
self.angle = math.pi + math.atan2(vecR[1], vecR[0])