I'm having some trouble figuring out how I can handle collisions that are specifically colliding on the top or bottom a rect. How can specify those collisions?

Here's a little code snippet to give you an idea of my approach. As it is now it doesn't matter where it collides.

# the ball has hit one of the paddles. send it back in another direction.
    if paddleRect.colliderect(ballRect) or paddle2Rect.colliderect(ballRect):
        if directionOfBall == 'upleft':
            directionOfBall = 'upright'
        elif directionOfBall == 'upright':
            directionOfBall = 'upleft'
        elif directionOfBall == 'downleft':
            directionOfBall = 'downright'
        elif directionOfBall == 'downright':
            directionOfBall = 'downleft'

Thanks in advance.


Paddle rect:

|    |
|    |
|    | Sides
|    |

I need to know if the ball has hit either the top or the bottom.

  • 1
    \$\begingroup\$ possible duplicate of 2d Collision detecton axis aligned boxes \$\endgroup\$ Sep 3, 2013 at 20:56
  • \$\begingroup\$ When two rects are overlapping there is no directionality to their state of collision, they are just ... colliding ... Do you mean if you have two rects that are moving, how to tell whether or not they collided against a given edge? \$\endgroup\$
    – Mokosha
    Sep 4, 2013 at 0:46
  • \$\begingroup\$ @sean No. It's not a duplicate. My question is about Pygame specifically, I'm not making a physics engine myself. \$\endgroup\$
    – Chakotay
    Sep 5, 2013 at 15:23
  • \$\begingroup\$ @Mokosha Well they are moving...but I need to know if the one rect (the ball) has collided with the other rect's (the paddle) top or botom. Look at my edit above. \$\endgroup\$
    – Chakotay
    Sep 5, 2013 at 15:24

2 Answers 2


Makeup of angles:

Basically you have to look at the angles between the center of the rectangle you are using for a paddle and the center of the rectangle of the ball (can also be a point since we collapse the ball rectangle into a point anyways).

enter image description here

The angle between the center points is then compared to the quadrants given by the corner points of the paddle (this gives left, right, up, down). The following program does just that with a bit of normalization to make lookup in the array easier.

Test program

The part relevant to your question is really the DirRect class.

import pygame
import math

class DirRect(pygame.Rect):
    def direction_to_rect(self, drect):
        ar = math.atan2(self.centery - self.top, self.right - self.centerx) # half of the angle of the right side
        # construct the corner angles into an array to search for index such that the index indicates direction
        # this is normalized into [0, 2π] to make searches easier (no negative numbers and stuff) 
        dirint = [ 2*ar, math.pi, math.pi+2*ar, 2*math.pi]
        # calculate angle towars the center of the other rectangle, + ar for normalization into
        ad = math.atan2(self.centery - drect.centery, drect.centerx - self.centerx) + ar
        # again normalization, sincen atan2 ouputs values in the range of [-π,π]
        if ad < 0:
            ad = 2*math.pi + ad
        # search for the quadrant we are in and return it
        for i in xrange(len(dirint)):
            if ad < dirint[i]:
                return i
        # just in case -1 as error indicator
        return -1

screen = pygame.display.set_mode([400,400])

# This is the paddle
paddle = DirRect( (150,150),(40,20) )
# colorize directional information
colors = [ (255,0,0), #right
           (0,255,0), #up
           (0,0,255), #left
           (0,0,0), #down
           (255,255,255) # error = -1

#show direction for every point
dsurf = pygame.display.get_surface()
for x in xrange(dsurf.get_width()):
    for y in xrange(dsurf.get_height()):
        prect = pygame.Rect((x,y),(0,0))
        dsurf.set_at( (x,y), colors[paddle.direction_to_rect(prect)])
#show paddle
pygame.draw.rect( dsurf, (128,128,128), paddle, 1)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
def on_collide(paddle, ball):
    # we collided, so which side? Args are the `Rect`s of paddle and ball.
    if paddle.centery < ball.centery:   
        print("paddle bottom")
    elif paddle.centery > ball.centery:
        print("paddle top")

    if paddle.centerx < ball.centerx:
        print("paddle right")
    elif paddle.centerx > ball.centerx:
        print("paddle left")
  • \$\begingroup\$ That looks like a great answer, although I have not had the chance to try it yet. But can pygame do print statements? \$\endgroup\$
    – Chakotay
    Oct 30, 2013 at 23:11
  • \$\begingroup\$ Yep, you can have a standard console open with pygame. Or you can replace them with your actions there. \$\endgroup\$
    – monkey
    Oct 31, 2013 at 1:37
  • \$\begingroup\$ this is quiet simple but really what I was looking for \$\endgroup\$
    – xhallix
    Jan 2, 2015 at 8:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .