.get_rect() and .move IN pygame

Viewed 500

i'm trying to do a simple ball moviment code with pygame.

Inside my loop, I wrote:

ballrect = ballrect.move([2,0]) to move the ball to right

if((ballrect.left<0) or (ballrect.right>width)): speed[0]= -speed[0] to invert the velocity when the ball "hit" the horizontal edges

if((ballrect.top<0) or (ballrect.bottom>height)): speed[1] = -speed[1] to invert the velocity when the ball "hit" the vertical edges

if((ballrect.left==width/2)): speed[0]=0; speed[1]=2 when my ball achieves the middle of the display, it will stop to move horizontally and start to move vertically.

but when the bottom of my image achieve the vertical edge (ballrect.bottom>height) it doesn't enter in second if to invert the vertical velocity. why?

full code:

import sys, pygame
pygame.init()

size = width, height = 1000, 1000
speed = [2,0]
black = 0

screen = pygame.display.set_mode(size)

ball = pygame.image.load(r"C:\Users\Victor\Desktop\bolinha_de_gorfe.png")
ballrect = ball.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]
    if((ballrect.left==width/2)):
        speed[0]=0
        speed[1]=2

    screen.fill((0,0,100))
    screen.blit(ball,ballrect)
    pygame.display.flip()
1 Answers

The issue if that your if condition (ballrect.left==width/2) is always True once the ball hits the centre-screen, so speed[1]=2 is always being re-set. So even if the direction changes, that change is being overwritten later.

One way to solve this is to move the ball by 1-pixel so that it doesn't keep triggering the "make turn at the middle" clause:

if ( ballrect.left==width/2 ):
    speed[0]=0
    speed[1]=2
    ballrect.left = (width//2)-1   # 1 pixel off, so we don't re-trigger

Or you could set a boolean flag to indicate if the turn was made:

turned_already = False

...

if ( ballrect.left==width/2 and not turned_already ):
    speed[0]=0
    speed[1]=2
    turned_already = True

You may want to add a Frames-per-Second limit to your code. It makes it much easier to see the movement of the ball (rather than the whole thing being over in a split-second).

clock=pygame.time.Clock()           # <<-- HERE
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]
    if ( ballrect.left==width/2 ):
        speed[0]=0
        speed[1]=2
        ballrect.left = (width//2)-1   # 1 pixel off, so we don't re-trigger

    screen.fill((0,0,100))
    screen.blit( ball, ballrect )
    pygame.display.flip()

    clock.tick_busy_loop( 60 )       # <<-- AND HERE

This limits the frame updates to 60 frames per second.

Related