[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Bouncing ball - separating the physics from the frame rate



Hi,

I know have the following code for my bouncing ball program:

#! /usr/bin/python

import sys, pygame, math

pygame.init()

xpos = 92
ypos = 0
gravity = 9.8
velocity = 0
# How much of the velocity of the ball is retained on a bounce
bounce = 0.8

screen = pygame.display.set_mode((200, 400), 0, 32)
# The ball is a 16px sprite
ball = pygame.image.load('ball.png')
clock = pygame.time.Clock()


# The main loop
while True:

    # Test for exit
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()

    # The physics
    # Reverse velocity taking into account bounciness if we hit the ground
    if ypos >= 384 and velocity > 0:
        # Avoid the ball sinking into the ground
        ypos = 384
        velocity = -velocity * bounce

    time_passed = clock.tick(60) / 1000.0
    newvelocity = velocity + (gravity * time_passed)
    # Use the average velocity over the period of the frame to change position
    ypos = ypos + int(((velocity + newvelocity) / 2) * time_passed * 160)
    velocity = newvelocity

    # Update the screen
    screen.fill((0, 0, 0))
    screen.blit(ball, (xpos, ypos))
    pygame.display.update()

The bounce is pretty realistic and I can live with the slight error caused by returning the ball to the floor exactly each time it bounces. Next I am going to have a look at adding in some sideways movement and bouncing off walls as well. Before I do that I would like to separate the physics calculations from the frame rate calculations and drawing loop. I really don't have a clue how to do this. I have never programmed anything in real time before. Having had a think about this I can see two possible ways of doing it.

1. Have the physics and graphics running in separate threads. I don't have a clue how to implement this!

2. Call a function from the main loop every time it passes which does the physics calculations based on a clock independent of the frame rate but which pauses when the simulation is paused (window not in focus?) Is there a function in the sys module that I can use to test for a pause?

Can anyone give me some more pointers on the best and most pythonic way of doing this.

Thanks.

Matt