[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] Bouncing ball - separating the physics from the frame rate
Boer Kees wrote:
The best I think you can do, is, in pseudo code:
mainloop:
-get the current time in ms
-calculate the new position of the ball
-take speed of ball, take direction of ball, calculate the imaginary
end position of the ball
-keep checking (with calculus), if the line ball-beginpos to
ball-endpos crosses a line, if so, say where and at what angle that line
is, and calculate the new imaginary endpos, mirrored about the line
closest to the beginpos. (so, the position of the ball is correct, even
if it bounces a couple of times inside one
time-frame) (http://hyperphysics.phy-astr.gsu.edu/hbase/hframe.html for
a good physics reference, also, choose radians, steer away from degrees
http://en.wikipedia.org/wiki/Sine)
Hi,
Rather than use the angle of the ball, I have used the vertical and horizontal
components of the velocity of the ball. If the ball hits a vertical wall then
reverse the horizontal component of the velocity taking into account the 'bounce
factor'. This seems to work for horizontal and vertical surfaces but I can see
how it could fall down when I introduce non-horizontal or vertical surfaces.
although I imagine that I could keep using the vectors but convert them into
angular vectors on collision. I am still wrestling with what to do when the ball
hits a surface and wants to pass through it, currently I am truncating the
movement - this will become less accurate as the frame rate gets slower.
Anyway, here is my latest code, not taking into account all of the fantastic
responses my post has had over the last day or so. I will have a look at all of
them and I'll modify the code accordingly over the next few days. Please not,
I'm only just getting to grips with OOP!
Thanks for looking,
Matt
#! /usr/bin/python
import sys, pygame
pygame.init()
xsize = 800
ysize = 600
startx = 192
starty = 0
floor = ysize - 16
ceiling = 0
lwall = 0
rwall = xsize - 16
class world:
gravity = 1000
bounce = 0.8
class ball(world):
def __init__(self):
self.velocity = [0, 0]
self.position = [0, 0]
self.sprite = pygame.image.load('ball.png')
def put(self, x, y):
self.position[0] = x
self.position[1] = y
def push(self, x, y):
self.velocity[0] = x
self.velocity[1] = y
def update(self, timepassed):
newvelocity = self.velocity[1] + (world.gravity * timepassed)
self.position[1] = self.position[1] + int(((self.velocity[1] +
newvelocity) / 2) * timepassed)
self.velocity[1] = newvelocity
self.position[0] = self.position[0] + int(self.velocity[0] * timepassed)
def checkcollision(self):
# Check for collisions and rebound if necessary
if self.position[1] >= floor and self.velocity[1] > 0:
self.position[1] = floor
self.velocity[1] = -self.velocity[1] * world.bounce
self.velocity[0] = self.velocity[0] * world.bounce
if self.position[1] <= ceiling and self.velocity[1] < 0:
self.position[1] = ceiling
self.velocity[1] = -self.velocity[1] * world.bounce
self.velocity[0] = self.velocity[0] * world.bounce
if self.position[0] >= rwall and self.velocity[0] > 0:
self.position[0] = rwall
self.velocity[0] = -self.velocity[0] * world.bounce
self.velocity[1] = self.velocity[1] * world.bounce
if self.position[0] <= lwall and self.velocity[0] < 0:
self.position[0] = lwall
self.velocity[0] = -self.velocity[0] * world.bounce
self.velocity[1] = self.velocity[1] * world.bounce
screen = pygame.display.set_mode((xsize, ysize), 0, 32)
clock = pygame.time.Clock()
ball1 = ball()
ball1.put(startx, starty)
ball1.push(-8000, 4000)
# The main loop
while True:
# Test for exit
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# Update the screen
screen.fill((0, 0, 0))
screen.blit(ball1.sprite, ball1.position)
pygame.display.update()
# Apply physics to the ball
timepassed = clock.tick(50) / 1000.0
ball1.checkcollision()
ball1.update(timepassed)