2

I wanted to create a function that is responsible for bouncing ball from the edge of the screen. I know i can do it better with math and Vector2 function but i wonder why i have this error, and why i can run window without this line of code:

if ball.y >= HEIGHT - 10:
    move_y = -vall_vel

Code

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

    def draw(self, window):
        pygame.draw.circle(window, self.color, (self.x, self.y), 10)

ball = Ball(WIDTH // 2, HEIGHT // 2, red)

def main():
    run = True

    ball_vel = 10
    move_x = ball_vel
    move_y = ball_vel

    def update():
        WINDOW.fill(black)

        ball.draw(WINDOW)

        player.draw(WINDOW)
        pygame.display.update()

    def ball_move():
        
        if HEIGHT - 10 > ball.y > 0 and WIDTH - 10 > ball.x > 0:
            ball.x += move_x
            ball.y += move_y
        
        if ball.y >= HEIGHT - 10:
            move_y = -ball_vel

    while run:
        clock.tick(FPS)

        ball_move()

        update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • You have to declare `move_y` as a global variable, otherwise the `ball_move()` function thinks it's a local variable. – John Gordon Dec 05 '20 at 02:46
  • 1
    I assume this is not the whole script as there is an `if` statement at the top that affects `move_y`. Please post the full traceback, and the lines it describes, if you haven't done so already. – OakenDuck Dec 05 '20 at 02:47
  • @JohnGordon the variables `move_x` and `move_y` are redefined in the first few lines of the function; they're available to any inner functions inside `main`. – OakenDuck Dec 05 '20 at 02:48
  • I badly copy and pasted my code but first two lines of code is just refer to the 2 lines in the ball_move() function. Using a global variable helped me a lot so thank you. – Sebastian Sieradzki Dec 05 '20 at 03:39
  • 1
    @OakenDuck they are available for _reading_ in the global scope, but not _assignment_. – John Gordon Dec 05 '20 at 03:57
  • They aren't global, either. This is where the `nonlocal` keyword comes in. However, *there is no good reason to nest the functions like this* in the first place. – Karl Knechtel Dec 05 '20 at 07:47

1 Answers1

2

The issue is caused by the function

The code which causes the issue is in a function:

def ball_move():

   if HEIGHT - 10 > ball.y > 0 and WIDTH - 10 > ball.x > 0:
       ball.x += move_x
       ball.y += move_y

   if ball.y >= HEIGHT - 10:
       move_y = -ball_vel

In the function ball_move is written to the variable move_y. This means the variable is declared inside the function's body and is a local variable (local in ball_move). Reading a variable before it is declared causes the error

UnboundLocalError: local variable 'move_y' referenced before assignment

You have to use the global statement if you want to be interpret the variable as global variable. Actually there exist a variable with the same name in the function main. But since the same variable is to be set in main, it must also be declared there as global:

def main():
    global run, move_x, move_y        # <---- ADD

    run = True
    ball_vel = 10
    move_x = ball_vel
    move_y = ball_vel

    def update():
        WINDOW.fill(black)
        ball.draw(WINDOW)
        player.draw(WINDOW)
        pygame.display.update()

    def ball_move():
        global move_x, move_y         # <---- ADD

        if HEIGHT - 10 > ball.y > 0 and WIDTH - 10 > ball.x > 0:
            ball.x += move_x
            ball.y += move_y
        if ball.y >= HEIGHT - 10:
            move_y = -ball_vel

    while run:
        clock.tick(FPS)
        ball_move()
        update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174