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

2007-12-04 Thread Greg Ewing

Matt Smith wrote:
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.


There's no need to calculate angles even then. Take a unit vector
perpendicular to the surface, and find the dot product of that
with the velocity. This is the magnitude of the component of the
velocity perpendicular to the surface. Multiply the unit vector
by that and add it to the original velocity (assuming your unit
vector points "away" from the surface).

As a general rule, it's almost never necessary to deal with
angles when doing this sort of thing. There's usually some
combination of vector operations that will give you what you
want much more easily and efficiently.

This is even more true in 3D, where angular coordinate systems
(so-called Euler angles) have various nasty problems due to
singularities. It's better to stay with cartesian coordinates
if at all possible.

--
Greg


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

2007-12-04 Thread Ian Mallett
Opps, that second ex. should have been math.acos()


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

2007-12-03 Thread Casey Duncan


On Dec 3, 2007, at 12:30 PM, Ian Mallett wrote:


On 12/3/07, Matt Smith <[EMAIL PROTECTED]> wrote:

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)

Yep, and if you want to do trig functions in Python with the 'Math'
module with degrees, you must convert to radians.
math.cos(math.radians(blah))
math.degrees(math.cos(blah))


Except that the output of sine/cos is not an angle, thus calling  
math.degrees() on it makes little sense. Honestly I find it easier to  
just use radians all the time rather than convert back and forth,  
except for a few pygame methods that take degrees...


-Casey


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

2007-12-03 Thread Ian Mallett
On 12/3/07, Matt Smith <[EMAIL PROTECTED]> wrote:
> > 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)
Yep, and if you want to do trig functions in Python with the 'Math'
module with degrees, you must convert to radians.
math.cos(math.radians(blah))
math.degrees(math.cos(blah))
Ian


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

2007-12-03 Thread Matt Smith

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)



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

2007-12-03 Thread Boer Kees

ok, I had this problem once, a while ago, simulating bouncing rigid balls. lost 
the code...
 
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)
 
-blit ball/line 
-handle input
-get the current time in ms, (decide to sleep some milliseconds till next 
planned frame, or just continue without sleeping, if in a state of lag)
 
If you want to simulate a 'real' bouncing ball, reduce the 'energy' of the ball 
(mass times speed) each time the ball bounces, by reducing speed with a 
percentage (simulating impression-depression, converting energy to the line and 
ball in the form of 'heat') 
 
and slightly reduce speed each 'meter' traveled (to simulate air friction). 
 
if you want, you can make this all just like in the real world: include size 
and weight of the ball in the air friction part, make the balls bounce against 
each other, or go to the 'non rigid' balls (oeh!),  etc.
 
For good results, simulate reality. So give your ball a mass. Then, applying 
'force' to it (by mouse input, or whatever), you can just slam in Newton's 
laws, and balls of different weight all behave nicely to the laws of physics.
 
dont calculate the position of the ball from the top left of a sprite or rect. 
Use the MIDDLE. And keep in mind the size of the ball, when calculating the 
bounces, I dont want to see big balls sink halfway through the line, before 
they bounce (heheheh.. happened to me :) )
 
A ball at least has a size, a mass, a position, a speed, and a direction of 
speed.
 
hope you are writing a 2d environment :) 
 
 
 
 
_
Share life as it happens with the new Windows Live.Download today it's FREE!
http://www.windowslive.com/share.html?ocid=TXT_TAGLM_Wave2_sharelife_112007

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

2007-12-02 Thread Greg Ewing

Patrick Mullen wrote:

> The only downside to this
> method, is if the framerate goes down, the physics will slow down
> along with it - but this may be preferable to jerkiness anyway.

Right. You don't want the physics to run too far ahead of
what's displayed on the screen. If rendering gets slowed
down for any reason, I find it's better to just let the
physics get slowed down as well. Otherwise the game starts
taking big jumps and becomes difficult to play.

The way I'm doing this in my games at the moment is to
set up a timer which sends events at regular intervals,
let's call it dt. Whenever one of these events occurs,
I set a physics_update_needed flag. Then my main loop
does something like

   Get all the events that have occurred since last
 time round the loop
   Process all of these events
   If physics_update_needed is set:
 Advance physics by dt
 Clear physics_update_needed
   Render

The result of this is that as long as an update/render
cycle can be done in less than dt, everything proceeds
smoothly with frames dt apart. If not, the frame rate
and game speed slow down together to whatever can be
supported.

I prefer to use timer events rather than clock.tick(),
because I don't like the idea of busy waiting. It's
a really bad thing to do on a multitasking system.

--
Greg


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

2007-12-02 Thread Patrick Mullen
> 1. Have the physics and graphics running in separate threads. I don't have a
> clue how to implement this!
This is a very experimental technique.  I think there may be a few
games that do this, but the majority do not.

>
> 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?

If your framerate is fairly constant, i.e. it doesn't ever go slower
than what you place inside the clock.tick() call, than you should be
able to get away with simply calling the physics once per frame
without using time_passed as part of the calculation.  (Substituting
some fixed time, like 0.02 as needed).  The only downside to this
method, is if the framerate goes down, the physics will slow down
along with it - but this may be preferable to jerkiness anyway.  What
you won't have is a bad framerate that causes the physics to go out of
sync or go haywire.  And the pausing problem won't matter.

To handle slower framerates, you could detect if time_passed is above
some threshold, and call the physics function twice if the time is too
large.  But it's better to keep the framerate up, no?

clock.tick(60) should guarantee that the framerate is a steady 60 fps
unless things slow down.

So here's my untested example, factoring out time_passed, and making
physics a function:

#physics
def run_physics(ob):
time_passed = 0.02   #.02 is a decent time interval for 60 fps,
adjust as needed.  (1/60.0 is more accurate)
# The physics
# Reverse velocity taking into account bounciness if we hit the ground
if ob.ypos >= 384 and ob.velocity > 0:
# Avoid the ball sinking into the ground
ob.ypos = 384
ob.velocity = -ob.velocity * ob.bounce

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

# The main loop
while True:

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

clock.tick(60) / 1000.0

run_physics(ball)   #Make global variables attributes of ball

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


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

2007-12-01 Thread Matt Smith

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