I am making a game with some bouncing elements IN a circle (I use pygame) , My elements have 2 attributes , one for the angle and one for the speed Here is how elements moves :
mvx = math.sin(self.angle) * self.speed
mvy = -math.cos(self.angle) * self.speed
self.x += mvx
self.y += mvy
My problem is this : I know the angle at the top (99.6°) , I have the collision point (x and y ) , but I'm unable to find the angle at the bottom(42.27°) Does someones can make a relation between the first angle and the second ?
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])