Question

hello i am pretty new to programming with pygame and i have this code:

import sys, pygame

pygame.init()
screen = pygame.display.set_mode((800, 368))
background = pygame.image.load("background.png")
background.convert()
screen.blit(background, (0, 0))

speed = [1, 1]
width = 800
height = 368

ball = pygame.image.load("ball.bmp")
ballrect = ball.get_rect()
player1 = pygame.image.load("player1.png")
player1rect = player1.get_rect()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: 
            sys.exit()              

    ballrect = ballrect.move(speed)
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    screen.blit(ball, ballrect)
    screen.blit(player1, player1rect)
    pygame.display.update()

but when i run it there comes too many balls it should only be one ball. and there comes more and more balls.

Was it helpful?

Solution

Fredrik Håård is right about re-drawing the background.

The screen acts as an image, and when you call screen.blit() you draw over part of that image. When the while 1: loop repeats, your image already has one or more copies of the ball on it, and your current code simply draws another image of the ball onto screen.

You can draw the background before you move the ball, thus avoiding adding a new variable to hold the previous ball position.

...
while 1:
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        sys.exit()

    screen.blit(background, ballrect, ballrect) #redraw background over old ball location
    ballrect = ballrect.move(speed)
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    screen.blit(ball, ballrect)
    screen.blit(player1, player1rect)
    pygame.display.update()

Alternatively, you can reconstruct the entire screen each time, by replacing screen.blit(background, ballrect, ballrect) above with screen.blit(background, (0, 0)), which ensures that the background is correct for each 'frame', but is significantly slower.

My preferred approach is to note that you can pass pygame.display.update() a list of rectangles, which makes the call return much quicker. Make sure you do an initial, full screen, display update before entering the while loop:

...
pygame.display.update()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    old_ballrect = ballrect
    screen.blit(background, old_ballrect, old_ballrect) #redraw background over old ball location
    ballrect = ballrect.move(speed)
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    screen.blit(ball, ballrect)
    screen.blit(player1, player1rect)
    pygame.display.update([old_ballrect, ballrect])

OTHER TIPS

Not being a pygame expert, I assume you would need to do something like

new_ball_rect = ballrect.move(speed)
...
screen.blit(background, ballrect, ballrect) #redraw background over old ball location
screen.blit(ball, new_ball_rect)

to re-draw the background over the old ball image.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top