Use vector2 in pygame. Collide with the window frame and restrict the ball to the rectangular area
A vector defines a direction and an amount. You have to add the vector to the location of the ball. Sadly pygame.Rect
stores integral numbers only, so the location of the object has to be stored in a pygame.math.Vector2
, too. You need 1 vector for the location of the object and a 2nd one for the direction. Every time when the location changes, then the .rect
attribute has to be set by the rounded location.
If the object hits a surface then the Ball is reflected (.reflect()) by the Normal vector to the surface.
Minimal example: repl.it/@Rabbid76/PyGame-BallBounceOffFrame
import pygame
import random
class Ball(pygame.sprite.Sprite):
def __init__(self, startpos, velocity, startdir):
super().__init__()
self.pos = pygame.math.Vector2(startpos)
self.velocity = velocity
self.dir = pygame.math.Vector2(startdir).normalize()
self.image = pygame.image.load("ball.png").convert_alpha()
self.rect = self.image.get_rect(center = (round(self.pos.x), round(self.pos.y)))
def reflect(self, NV):
self.dir = self.dir.reflect(pygame.math.Vector2(NV))
def update(self):
self.pos += self.dir * self.velocity
self.rect.center = round(self.pos.x), round(self.pos.y)
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
all_groups = pygame.sprite.Group()
start, velocity, direction = (250, 250), 5, (random.random(), random.random())
ball = Ball(start, velocity, direction)
all_groups.add(ball)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
all_groups.update()
if ball.rect.left <= 100:
ball.reflect((1, 0))
if ball.rect.right >= 400:
ball.reflect((-1, 0))
if ball.rect.top <= 100:
ball.reflect((0, 1))
if ball.rect.bottom >= 400:
ball.reflect((0, -1))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (100, 100, 300, 300), 1)
all_groups.draw(window)
pygame.display.flip()
Lets assume you have a group of blocks:
block_group = pygame.sprite.Group()
Detect the collision of the ball
and the block_group
. Once a collision (pygame.sprite.spritecollide()
) is detected, reflect
the ball on the block:
block_hit = pygame.sprite.spritecollide(ball, block_group, False)
if block_hit:
bl = block_hit[0].rect.left - ball.rect.width/4
br = block_hit[0].rect.right + ball.rect.width/4
nv = (0, 1) if bl < ball.rect.centerx < br else (1, 0)
ball.reflect(nv)