Home > Enterprise >  Pygame ball movement flickering
Pygame ball movement flickering

Time:12-30

I have been trying to make a basic Pygame code where the ball bounces around the screen and off your paddle. The paddle movement is smooth, but the ball flickers and is pretty choppy. Here is my complete code:

import pygame, sys
from pygame.locals import *
import random, time

pygame.init()

window = (800, 600)

background = (0, 0, 0)
back = pygame.Surface(window)
entity_color = (255, 255, 255)
x = 362.5
y = 550
ball_x = 387.5
ball_y = 50
width = 75
height = 25
clockobject = pygame.time.Clock()


screen = pygame.display.set_mode((window))

pygame.display.set_caption("Test Game")

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        super(Ball, self).__init__()
        self.surf = pygame.Surface((25, 25))
        self.surf.fill((255, 255, 255))
        self.rect = self.surf.get_rect()
        self.dir_x = 1
        self.dir_y = 1
        self.speed = 2

    def update(self):
        global ball_x
        global ball_y
        if ball_x > 775:
            ball_x = 775
            ball.dir_x = -1
        elif ball_x < 0:
            ball_x = 0
            ball.dir_x = 1
        if ball_y < 0:
            ball_y = 0
            ball.dir_y = 1
        elif ball_y > 600:
            ball_y = 50
            ball_x = 387.5
        if ball_x <= x   75 and ball_x >= x and ball_y <= y and ball_y >= y - 25:
            ball.dir_y = -1
        ball_x = ball_x   ball.speed * ball.dir_x
        ball_y = ball_y   ball.speed * ball.dir_y


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.image_s = pygame.image.load("paddle.png")
        self.image_b = self.image_s.get_rect()
        self.surf = pygame.Surface((75, 25))

        self.surf.fill((255, 255, 255))
        self.rect = self.surf.get_rect()

    def update(self):
        global x
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            x = x - 5
        elif keys[pygame.K_RIGHT]:
            x = x   5

    def checkboundaries(self):
        global x
        if x > 725:
            x = 725
        if x < 0:
            x = 0

ball = Ball()
player = Player()
waiting = True
while waiting:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()
            elif event.key == pygame.K_SPACE:
                running = True
                waiting = False
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
    player.update()
    ball.update()
    player.checkboundaries()
    screen.blit(back, (0,0))
    screen.blit(player.surf, (x, y))
    screen.blit(ball.surf, (ball_x, ball_y))
    pygame.display.flip()
    clockobject.tick(360)

pygame.quit()
sys.exit()

Is this because of something wrong in my code that is running slowly, or am I missing something?

CodePudding user response:

If you are using pygame.sprite.Sprite, you should also use pygame.sprite.Group.

pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.

The latter delegates to the update method of the contained pygame.sprite.Sprites — you have to implement the method. See pygame.sprite.Group.update():

Calls the update() method on all Sprites in the Group. [...]

The former uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects — you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():

Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]

e.g.:

import pygame, sys
from pygame.locals import *

pygame.init()
clockobject = pygame.time.Clock()
screen = pygame.display.set_mode((800, 600))
back = pygame.Surface(screen.get_size())
pygame.display.set_caption("Test Game")

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        super(Ball, self).__init__()
        self.image = pygame.Surface((25, 25))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect(topleft = (387, 50))
        self.dir_x = 1
        self.dir_y = 1
        self.speed = 2

    def update(self):
        if self.rect.x > 775:
            self.rect.x = 775
            self.dir_x = -1
        elif self.rect.x < 0:
            self.rect.x = 0
            self.dir_x = 1
        if self.rect.y < 0:
            self.rect.y = 0
            self.dir_y = 1
        elif self.rect.y > 600:
            self.rect.topleft = (387, 50)
        if self.rect.colliderect(player.rect):
            ball.dir_y = -1
        self.rect.x  = ball.speed * ball.dir_x
        self.rect.y  = ball.speed * ball.dir_y

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.image = pygame.Surface((75, 25))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect(topleft = (363, 550))

    def update(self):
        keys = pygame.key.get_pressed()
        self.rect.x  = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 5
        self.rect.clamp_ip(screen.get_rect())

ball = Ball()
player = Player()
all_sprites = pygame.sprite.Group([ball, player])

started = False
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            elif event.key == pygame.K_SPACE:
                started = True
    
    
    screen.blit(back, (0,0))
    if started:
        all_sprites.update()
        all_sprites.draw(screen)
    pygame.display.flip()
    clockobject.tick(100)

pygame.quit()
sys.exit()
  • Related