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

Re: [pygame] Weird problem



On 10/13/06, Kai Kuehne <kai.kuehne@xxxxxxxxx> wrote:
My real problem is how to move something slow and another thing
really fast if I set - let's say - the frame rate to 30. For the slow-thing
I could move it 1 pixel per frame. Ok, works great. And the fast-thing could
be moved 3 pixels per frame but than it looks not very cool. It's lagging
and you see the movement-steps. And what if the slow-thing is too fast, though?

I think one approach that may help you is decoupling update/simulation
rate from draw/frame rate, such that you have a fixed simulation rate
with a variable draw rate. It is the most common solution to the issue
you are trying to solve in professional games. It is often referred to
as "frame skipping"

The basic idea is to get some nice high update rate (say like 60 times
a second) and then to only draw frames to the screen at the rate that
makes sense given how well the client computer can perform. In most
games, the time to draw a frame is much much higher than the time to
perform one simulation step, and in such cases this approach makes a
lot of sense to get consistent and quite playable behavior on a large
variety of computers. (if you aren't using HW rendering, your game
would definitely fall in that group). For games where simulation steps
aren't much much faster than drawing a frame, it's good to also limit
the number of simulation steps that will be performed without drawing,
so that the game will slow down instead of becoming unplayable because
you can't see stuff moving.

I don't have any sample code to show for it right now, but the
implementation is usually something like:

milliseconds_per_update = 1000.0/updates_per_second;
timer = pygame.time.Clock()
while playing:
 time_bucket += timer.tick()/1000.0
 update_count = min(time_bucket/milliseconds_per_update, max_updates_per_draw)
 for i in xrange(update_count):
   update()
 draw()
 time_bucket %= milliseconds_per_update

so then you can go ahead and set your updates_per_second to 60 (or
even 120, which is often done with stuff with more advanced physics
stuff or discrete collision detection & fast objects)

with a high simulation rate, it's easy to have stuff move both fast
and slow. But since you are skipping frames, if the comp can't handle
drawing 60, it will draw what it can handle, but stuff will move the
way you designed.

I usually use 60 updates per second with a max of 5 updates per draw -
the reason being that I think 12 drawn frames per second is kind of
the low limit for playability. since 60/5 = 12, it means that if a
comp can't handle 12 fps, then the game will slow down in order to try
to keep at 12fps (if it can)


I cannot set the speed to 0.5 because pygame.Rect uses integers for the
position things.

You can totally use fractional speeds (and positions), they will just
be drawn at integer positions. The integer draw position thing can be
a problem for slowly moving objects (cause stuff will seem to stutter
a bit as they move) but that's a problem no matter what approach you
use. So don't worry at all about fractional speeds. (btw, "sub pixel
rendering" is the term for the solution to the slow object with
integer draw position problem, if you feel like researching it)


Probably (well, surely probably) this is a noob question. But atm,
I'm not getting to it...

It is a common question for noob's to ask, but it is actually
something real experts have differing opinions on about the best
solutions, so it's a great question. Note there are other approaches
than what I suggested that are used in AAA games, but I think this is
the most general purpose, and going too deep into all that would
probably be way off topic for a pygame mailing list