0

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):
        ballHitPaddle.play()
        if directionOfBall == 'upleft':
            directionOfBall = 'upright'
        elif directionOfBall == 'upright':
            directionOfBall = 'upleft'
        elif directionOfBall == 'downleft':
            directionOfBall = 'downright'
        elif directionOfBall == 'downright':
            directionOfBall = 'downleft'

Thanks in advance.

**EDIT**

Paddle rect:

 top
 ____
|    |
|    |
|    | Sides
|    |
 ---- 
bottom

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

Chakotay
  • 101
  • 1
  • 2

2 Answers2

3

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 = [ 2ar, math.pi, math.pi+2ar, 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

pygame.init()

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

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 pygame.display.update()

pygame.quit()

hhofbaue
  • 121
  • 2
1
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")
monkey
  • 151
  • 1
  • 7