Question: I'm fairly new to python and I'm trying to build a game with Pygame. I kept having issues with collisions not being recognized. Here's the code I tried import pygame pygame.init() WIDTH, HEIGHT = (900, 500) WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('Bong Pong') FPS = 60 WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) BORDER = pygame.Rect(WIDTH// 2 -5, 0, 10, HEIGHT) VEL = 3 PLAYER_HEIGHT = 50 PLAYER_WIDTH = 15 BALL_HEIGHT = 15 BALL_WIDTH = 15 def draw_window(player_1, player_2, game_ball): WIN.fill(WHITE) pygame.draw.rect(WIN, BLACK, BORDER) pygame.draw.rect(WIN, BLACK, player_1) pygame.draw.rect(WIN, BLACK, player_2) pygame.draw.rect(WIN, RED, game_ball) pygame.display.update() def player_1_movement(keys_pressed, player_1): if keys_pressed[pygame.K_w] and player_1.y - VEL > 0: player_1.y -= VEL if keys_pressed [pygame.K_s] and player_1.y + PLAYER_HEIGHT + VEL < 500: player_1.y += VEL def player_2_movement(keys_pressed, player_2): if keys_pressed[pygame.K_UP] and player_2.y - VEL > 0: player_2.y -= VEL if keys_pressed [pygame.K_DOWN] and player_2.y + PLAYER_HEIGHT + VEL < 500: player_2.y += VEL def player_collision(player_1, player_2, game_ball, ball_vel_x): if game_ball.colliderect(player_1) or game_ball.colliderect(player_2): ball_vel_x *= -1 def main(): clock = pygame.time.Clock() run = True player_1 = pygame.Rect(50, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT) player_2 = pygame.Rect(850, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT) game_ball = pygame.Rect(50 + PLAYER_WIDTH, HEIGHT//2 - BALL_HEIGHT// 2, BALL_WIDTH, BALL_HEIGHT) ball_vel_y = 2 ball_vel_x = 2 while run: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.QUIT() keys_pressed = pygame.key.get_pressed() player_1_movement(keys_pressed, player_1) player_2_movement(keys_pressed, player_2) draw_window(player_1, player_2, game_ball) if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500: ball_vel_y *= -1 game_ball.y -= ball_vel_y player_collision(player_1, player_2, game_ball, ball_vel_x) game_ball.x += ball_vel_x main() if __name__ == '__main__': main()  I've also tried putting the game_ball.x += ball_vel_x  in the player_collsion function but it doesn't reverse it properly. I've already solved the issue by putting the entire player_collision function code inside the main function like so  def main(): clock = pygame.time.Clock() run = True player_1 = pygame.Rect(50, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT) player_2 = pygame.Rect(850, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT) game_ball = pygame.Rect(50 + PLAYER_WIDTH, HEIGHT//2 - BALL_HEIGHT// 2, BALL_WIDTH, BALL_HEIGHT) ball_vel_y = 2 ball_vel_x = 2 while run: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.QUIT() keys_pressed = pygame.key.get_pressed() player_1_movement(keys_pressed, player_1) player_2_movement(keys_pressed, player_2) draw_window(player_1, player_2, game_ball) if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500: ball_vel_y *= -1 game_ball.y -= ball_vel_y if game_ball.colliderect(player_1) or game_ball.colliderect(player_2): ball_vel_x *= -1 game_ball.x += ball_vel_x main()  and this works exactly how I want it I just want to clear up my understanding of why this function wouldn't work properly if just called in the main function instead of putting it directly in.

Answer: Python has no concept of in-out parameters. The argument is passed by value. If you change ball_vel_x in the player_collision function, only the parameter changes, but the argument remains unchanged. You must return the new value of ball_vel_x from the function: def player_collision(player_1, player_2, game_ball, ball_vel_x): if game_ball.colliderect(player_1) or game_ball.colliderect(player_2): ball_vel_x *= -1 return ball_vel_x  def main(): # [...] while run: # [...] ball_vel_x = player_collision(player_1, player_2, game_ball, ball_vel_x) # [...]   Another possibility is to store the velocity in an object (e.g. gyame.math.Vector2). A variable stores a reference to an object, so you can change the object's attributes in the function if the variable is an argument of the function call: def player_collision(player_1, player_2, game_ball, ball_vel): if game_ball.colliderect(player_1) or game_ball.colliderect(player_2): ball_vel.x *= -1 def main(): # [...] ball_vel = pygame.math.Vector2(2, 2) while run: # [...] if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500: ball_vel.y *= -1 game_ball.y -= ball_vel.y player_collision(player_1, player_2, game_ball, ball_vel) game_ball.x += ball_vel.x