Search code examples
pythonpygamepong

Ball doesn't bounce of screen edges in PyGame


I'm building a Pong game in Python with PyGame. For some reason, the ball in the game doesn't bounce off the walls / screen edges sometimes. It bounces off the walls once or twice and stops.

I don't know why that happens.

Could someone check my code to see if there are any errors?

import os
import pygame

WIDTH = 600
HEIGHT = 500

class Slider:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.height = 120
        self.width = 8

    def draw(self, win):
        pygame.draw.rect(win, (0, 255, 64), (self.x, self.y, self.width, self.height))

    def move(self, dir, dis):
        if dir == 'top' and self.y >= 0:
            self.y -= dis
        elif dir == 'bottom' and self.y <= 379:
            self.y += dis 
        else: 
            self.y = self.y

class Ball:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = 15

        self.speedY = 0.2
        self.speedX = 0.2

        self.top = y
        self.bottom = y + 30
        self.left = x
        self.right = x + 30

    def draw(self, win):
        ball = pygame.draw.circle(win, (255, 255, 0), (self.x, self.y), self.radius)
        self.top = ball.top
        self.bottom = ball.bottom
        self.left = ball.left
        self.right = ball.right

    def move(self):

        if self.top <= 0:
            self.speedY *= -1
        else:
            self.y += self.speedY
            self.x += self.speedX

        if self.bottom >= HEIGHT:
            self.speedY *= -1
        else:
            self.y += self.speedY
            self.x += self.speedX
            
        if self.left <= 0:
            self.speedX *= -1
        else:
            self.y += self.speedY
            self.x += self.speedX

        if self.right >= WIDTH:
            self.speedX *= -1
        else:
            self.y += self.speedY
            self.x += self.speedX


def draw_window(win, *sprites):
    pygame.display.update()
    win.fill((0, 0, 0, 0))
    for sprite in sprites:
        sprite.draw(win)

def main():
    win = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption('Pong Game')

    slider1 = Slider(100, 250)
    slider2 = Slider(500, 250)
    ball = Ball(300, 250)

    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                slider1.move('bottom', 0.3)
            elif event.key == pygame.K_UP:
                slider1.move('top', 0.3)
            else:
                print(pygame.key.name(event.key))

        ball.move()

        key = pygame.key.get_pressed()

        if key[pygame.K_s]:
            slider2.move('bottom', 0.3)
        elif key[pygame.K_w]:
            slider2.move('top', 0.3)

        draw_window(win, slider1, slider2, ball)


    pygame.quit()
    quit()

main()

Solution

  • You need to change your move method a bit, you need to remove the else blocks as they mess up ball's movement, just always move the ball once when calling move. You can also combine checking whether ball is on edge for an axis in one line (using or):

    def move(self):
    
        if self.top <= 0 or self.bottom >= HEIGHT:
            self.speedY *= -1
    
        if self.left <= 0 or self.right >= WIDTH:
            self.speedX *= -1
    
        self.y += self.speedY
        self.x += self.speedX