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

Re: [pygame] Why does my ball vibrate?



A somewhat simple fix to get the ball to stop bouncing would be like this (put after velocity is set to newvelocity):
if abs(velocity) < 0.01:
  gravity = 0
  velocity = 0

This is just a quick fix though (and alters gravity, which is bad), you probably want to use Patrick's or James'.

On Nov 28, 2007 1:57 PM, James Paige <Bob@xxxxxxxxxxxxxxxxxxx> wrote:
On Wed, Nov 28, 2007 at 08:26:19PM +0000, Matt Smith wrote:
> Hi,
>
> I am beginning to learn Pygame and I have written a short program to
> simulate a bouncing ball. The motion of the ball is pretty realistic
> until it has almost come to rest. The ball continues to vibrate long
> after you would have expected it to come to a complete rest (or be
> moving less than 1 pile each time as it will never stop moving 100%).
> Also, the ball can start to bounce higher again if I click somewhere
> else on the desktop. I can't work out why this happens so can anyone
> shed some light on it and suggest how I can prevent it.Here 's my code:

I have two suggestions, see below:

> #! /usr/bin/python
>
> import sys, pygame
> 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:

Here you probably want "if ypos >= 384 ..." rather than checking the
precise pixel position, since your ball could be falling fast enough to
skip over pixel 384. I notice you have a check for that later, but why
not put it here?

>         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 + (((velocity + newvelocity) / 2) * time_passed * 160)

Your velocity is a floating point number, and floating point math has
limited precision. Because your ball sprite is being displayed only at
integer pixel coordinates, you ought not to let your xpos and ypos have
decmals. I suggest you change the above line to this:

 ypos = ypos + int(((velocity + newvelocity) / 2) * time_passed * 160)

This throws away the decmal on the ypos, but preserves it for your
velocity. This fix alone, even without the ypos == 384 thing I mentioned
above, is enough to solve your bouncing problem.

>     # Prevent the ball from sinking into the ground
>     if ypos >= 384:
>         ypos = 384
>     velocity = newvelocity
>
>     # Update the screen
>     screen.fill((0, 0, 0))
>     screen.blit(ball, (xpos, ypos))
>     pygame.display.update()
>
> Thanks for looking.
>
> Matt

You are welcome :)

---
James Paige



--
This, from Jach.

How many programmers does it take to change a light bulb?
None. It's a hardware problem.

How many Microsoft programmers does it take to change a light bulb?
None. Microsoft just declared darkness as the newest innovation in cutting-edge technology.