Re: [pygame] frame independant movement
...except that because you know the way gravity works (-9.8m/s*s) and, if you set a constant dt, you can compensate accordingly. For example, a projectile traverses a parabolic arc. If your character were to jump along this arc, naturally, trying to numerically approximate this will give an error. If you use the integrated function (the parabola) instead, you'll get a correct result.
Re: [pygame] frame independant movement
On Wed, Feb 3, 2010 at 3:30 PM, R. Alan Monroe wrote: > > The nice thing about limiting the framerate versus having calculations be > > done based on time passed is that it is much more consistent. With dt > > calculations you will often get huge jumps on slower computers and extra > > slow movement in cases on fast machines, just do to inaccuracies and > error > > in the calculation. On a slower machine, no matter which timing method > you > > use it will be unpleasant. > > What kind of innacuracies, specifically? > > Any time-step based integration of non-linear functions will have errors and inaccuracies, which are larger the larger the time-step is. ...and pretty much all interesting real world physics are non-linear functions. So gravity for instance - if acceleration = time*gravity and position = time*acceleration, the relationship between position and gravity over time is nonlinear, specifically it changes with the square of time elapsed (position = time*time*gravity). Doing that calculation as the sum of repeated linear calculations, will have error. The magnitude of that error will change with your time-step size. The way that's a problem with a game, is when a level is dsigned so that gap is exactly the right distance to be able to jump across it - but then some slower computer uses a different larger time-step than your level designer - so on that fast computer, you can't make the jump, cause the error on the gravity effect is higher, so it pulls the player down sooner. Some other examples of non-linear places with error are springs, friction, application of the force of explosions that aren't instantaneous, etc. etc. All those things and more will behave differently based on your time-step.
Re: [pygame] frame independant movement
On Feb 3, 2010, at 4:30 PM, R. Alan Monroe wrote: >> The nice thing about limiting the framerate versus having calculations be >> done based on time passed is that it is much more consistent. With dt >> calculations you will often get huge jumps on slower computers and extra >> slow movement in cases on fast machines, just do to inaccuracies and error >> in the calculation. On a slower machine, no matter which timing method you >> use it will be unpleasant. > > What kind of innacuracies, specifically? Typical incremental algorithms used in games to simulate "physics" (or even just basic non-linear movement) give different answers over time with different time step intervals. Simple algorithms, such as Euler's method in particular, are especially bad in this regard. This is true even if the time step does not vary over time, but can become especially acute if it does. If for example, time steps have been coming at a steady 30/sec and all of a sudden a few steps are at a rate more like 5/sec, things can not only become inaccurate, but also unstable if you aren't careful. Think about it this way, if you have many bodies in motion in a game, the more they move each frame, the harder it is for you to accurately simulate how they interact. When things move too far each step, things can penetrate or pass through things, generate ridiculously large collision response forces or start resonating and shatter into a million pieces. Also at long time step intervals any code that polls the player's controls or AI code gets called much less frequently, changing the whole behavior of the game in undesirable ways. >> One method for having a smooth variable framerate, without the issues of >> variable time calculations, is to have a fixed time step. Each frame, you >> may process more than one timestep, if you need to in order to keep up. The >> timestep has a fixed amount of time it is supposed to similate, say, .02, >> which would be 60 times per second. If the user is able to run at 60 fps, >> they get very smooth animation, as only one step is occuring on each frame. >> If the user can only run at 30 fps, they will get two steps each frame, so >> it will be jerkier, but still accurate. If they can only run at 10 fps, you >> would set a limit on it (maybe the max is two timesteps in a frame), so >> things would be slower for them but maybe still playable. > >> [code snipped] > > Is anyone aware of any websites that describe this time/frame business > pictorially? I have read about it repeatedly and browsed a lot of > pseudocod over the years, but without a proper diagram it's not really > sinking in for a visual thinker like myself. It's tough to generalize this visually, but here's an example of how Euler's method diverges from an exact simulation over time: http://www.boomer.org/c/p3/c10/c1002.html -Casey
Re: [pygame] frame independant movement
> The nice thing about limiting the framerate versus having calculations be > done based on time passed is that it is much more consistent. With dt > calculations you will often get huge jumps on slower computers and extra > slow movement in cases on fast machines, just do to inaccuracies and error > in the calculation. On a slower machine, no matter which timing method you > use it will be unpleasant. What kind of innacuracies, specifically? > One method for having a smooth variable framerate, without the issues of > variable time calculations, is to have a fixed time step. Each frame, you > may process more than one timestep, if you need to in order to keep up. The > timestep has a fixed amount of time it is supposed to similate, say, .02, > which would be 60 times per second. If the user is able to run at 60 fps, > they get very smooth animation, as only one step is occuring on each frame. > If the user can only run at 30 fps, they will get two steps each frame, so > it will be jerkier, but still accurate. If they can only run at 10 fps, you > would set a limit on it (maybe the max is two timesteps in a frame), so > things would be slower for them but maybe still playable. > [code snipped] Is anyone aware of any websites that describe this time/frame business pictorially? I have read about it repeatedly and browsed a lot of pseudocod over the years, but without a proper diagram it's not really sinking in for a visual thinker like myself. Alan
Re: [pygame] frame independant movement
The way Patrick describes is *by far* the most common way the main loop is done in professional games. As he said, it provides consistent game behavior but allows the actual frame rate to vary based on what the platform can actually provide. The system actually works very very well, as long as drawing takes longer than updating (which it still usually does, partially cause of vsync to the screens refresh rate). However, if updating takes significantly longer than drawing, then doing n updates for each draw ends up making a less playable game versus just slowing down game play and having one update per draw (but if that's your case, the gameplay suffers no matter what your main loop does, so maybe it doesn't matter) ...and .02 is 50 fps, not 60 :) GAMESPEED = 1/60.0 would be a better way to do that. .. and for max, I personally think 4 works really well, cause 15fps with a 60 cycle per second simulation is usually quite playable, but if your fps drops below 15, it's usually more playable to also slow the game down. On Wed, Feb 3, 2010 at 11:59 AM, Patrick Mullen wrote: > One method for having a smooth variable framerate, without the issues of > variable time calculations, is to have a fixed time step. Each frame, you > may process more than one timestep, if you need to in order to keep up. The > timestep has a fixed amount of time it is supposed to similate, say, .02, > which would be 60 times per second. If the user is able to run at 60 fps, > they get very smooth animation, as only one step is occuring on each frame. > If the user can only run at 30 fps, they will get two steps each frame, so > it will be jerkier, but still accurate. If they can only run at 10 fps, you > would set a limit on it (maybe the max is two timesteps in a frame), so > things would be slower for them but maybe still playable. > > def dostuff(dt): >man.x += speed*dt > > GAMESPEED = .02 > > while 1: >dt = clock.tick() >max=2 >while dt>0 and max: > dt -= GAMESPEED > max -= 1 > dostuff(GAMESPEED) > > There might be other problems with this, I've never done it this way, only > seen it referred to. I know in some engines, like doom3, the physics of > everything, game logic etc, happens at a fixed 30hz rate; whereas animation > of the scene is much smoother. > > I am usually lazy and just do clock.tick(30) lol. > >
Re: [pygame] write sound to file for fast loading?
I think it would be easier to simply use a loading screen before a part of the game (f.e. entering an area) and there load any sounds that might come in use into that part. It surely would be nicer to see than lag during the gameplay. Of course this could not be the best solution, but if there are not better options, this would be the better to use. Howdy, folks. I have a problem I've been studying a while and I can't figure out a solution. Pygame or SDL--not sure which--is pretty slow at loading sounds. For large sounds, like songs, this means significant pauses in your game; or very long loading times at startup if you have a few of them to load. I tried using a thread to load a song, but as expected that only resulted in a very laggy game for the duration. So I was thinking it might be faster to pre-process a song: load it via the mixer, write the buffer to a data file, then later load it into an array and feed the array to the mixer. I can see that part of that idea is implemented in _sndarray.py, but I didn't really want to require numpy and I couldn't see how to convert that module's code to my purpose anyhow. I'm strikin' out. Is this even feasible, or is it a hair-brained scheme doomed to failure? Has anyone solved this problem, and would s/he be willing to share? :) Gumm
Re: [pygame] frame independant movement
The nice thing about limiting the framerate versus having calculations be done based on time passed is that it is much more consistent. With dt calculations you will often get huge jumps on slower computers and extra slow movement in cases on fast machines, just do to inaccuracies and error in the calculation. On a slower machine, no matter which timing method you use it will be unpleasant. One method for having a smooth variable framerate, without the issues of variable time calculations, is to have a fixed time step. Each frame, you may process more than one timestep, if you need to in order to keep up. The timestep has a fixed amount of time it is supposed to similate, say, .02, which would be 60 times per second. If the user is able to run at 60 fps, they get very smooth animation, as only one step is occuring on each frame. If the user can only run at 30 fps, they will get two steps each frame, so it will be jerkier, but still accurate. If they can only run at 10 fps, you would set a limit on it (maybe the max is two timesteps in a frame), so things would be slower for them but maybe still playable. def dostuff(dt): man.x += speed*dt GAMESPEED = .02 while 1: dt = clock.tick() max=2 while dt>0 and max: dt -= GAMESPEED max -= 1 dostuff(GAMESPEED) There might be other problems with this, I've never done it this way, only seen it referred to. I know in some engines, like doom3, the physics of everything, game logic etc, happens at a fixed 30hz rate; whereas animation of the scene is much smoother. I am usually lazy and just do clock.tick(30) lol. Timing gets even more interesting when you do multiplayer, then you are dealing with different time rates for each player. Fun stuff :) On Wed, Feb 3, 2010 at 3:38 AM, René Dudfield wrote: > On Wed, Feb 3, 2010 at 7:06 PM, DR0ID wrote: > > On 03.02.2010 11:25, inigo delgado wrote: > >> > >> "Another thing you can do is just use Clock to limit the FPS to 60 or > >> something, but then your game will run slower if you're not getting 60 > fps." > >> > >> Well, true, but you MUST determine the framerate that you want for your > >> game, otherway you will get a 60 FPS in your PC, 70 in another and 120 > in > >> another one that is much more faster/newer than yours and in witch your > game > >> will turn unusable at this framerate > >> > >> I do this: > >> > >> while(true): #principal loop > >># get current time > >>t = time.time() > >> > >>doAll() > >> > >>#At the end i get the time needed to do the calculatons & flip > >>T = t - time.time() > >>delta = T - 1/desiredFrameRate > >>if (delta > 0): # if the cycle has been done too fast > >>time.wait(delta) > >>This way you have your desired framerate or the maximum possible. > >> Additionally you can do this: > >>else: > >>GLOBAL_T = GLOBAL_STANDAR_T - delta # delta is <= 0, - and - is + > >> > >> Being GLOBAL_T the t that you use for your position calculations and > >> global_standar_t the value of global_t if delta is 0. > > > > Hi > > > > You will get different framerates only if you don't limit the fps. Using > > http://www.pygame.org/docs/ref/time.html#Clock.tick you will have always > the > > specified framerate except if the cpu can not keep up (then it will run > > slower), but on faster machines tick will wait, similar to what you do > (tick > > might be more accurate). > > > > ~DR0ID > > > > > Just another note... use Clock.tick_busy_loop if you don't mind > burning a bit of cpu to get far more accurate sleeping. The OS sleep > is often a bit random - and not really meant for accurate sleeping. > > > cu, >
Re: [pygame] frame independant movement
On Wed, Feb 3, 2010 at 7:06 PM, DR0ID wrote: > On 03.02.2010 11:25, inigo delgado wrote: >> >> "Another thing you can do is just use Clock to limit the FPS to 60 or >> something, but then your game will run slower if you're not getting 60 fps." >> >> Well, true, but you MUST determine the framerate that you want for your >> game, otherway you will get a 60 FPS in your PC, 70 in another and 120 in >> another one that is much more faster/newer than yours and in witch your game >> will turn unusable at this framerate >> >> I do this: >> >> while(true): #principal loop >> # get current time >> t = time.time() >> >> doAll() >> >> #At the end i get the time needed to do the calculatons & flip >> T = t - time.time() >> delta = T - 1/desiredFrameRate >> if (delta > 0): # if the cycle has been done too fast >> time.wait(delta) >> This way you have your desired framerate or the maximum possible. >> Additionally you can do this: >> else: >> GLOBAL_T = GLOBAL_STANDAR_T - delta # delta is <= 0, - and - is + >> >> Being GLOBAL_T the t that you use for your position calculations and >> global_standar_t the value of global_t if delta is 0. > > Hi > > You will get different framerates only if you don't limit the fps. Using > http://www.pygame.org/docs/ref/time.html#Clock.tick you will have always the > specified framerate except if the cpu can not keep up (then it will run > slower), but on faster machines tick will wait, similar to what you do (tick > might be more accurate). > > ~DR0ID > Just another note... use Clock.tick_busy_loop if you don't mind burning a bit of cpu to get far more accurate sleeping. The OS sleep is often a bit random - and not really meant for accurate sleeping. cu,
Re: [pygame] frame independant movement
On 03.02.2010 11:25, inigo delgado wrote: "Another thing you can do is just use Clock to limit the FPS to 60 or something, but then your game will run slower if you're not getting 60 fps." Well, true, but you MUST determine the framerate that you want for your game, otherway you will get a 60 FPS in your PC, 70 in another and 120 in another one that is much more faster/newer than yours and in witch your game will turn unusable at this framerate I do this: while(true): #principal loop # get current time t = time.time() doAll() #At the end i get the time needed to do the calculatons & flip T = t - time.time() delta = T - 1/desiredFrameRate if (delta > 0): # if the cycle has been done too fast time.wait(delta) This way you have your desired framerate or the maximum possible. Additionally you can do this: else: GLOBAL_T = GLOBAL_STANDAR_T - delta # delta is <= 0, - and - is + Being GLOBAL_T the t that you use for your position calculations and global_standar_t the value of global_t if delta is 0. Hi You will get different framerates only if you don't limit the fps. Using http://www.pygame.org/docs/ref/time.html#Clock.tick you will have always the specified framerate except if the cpu can not keep up (then it will run slower), but on faster machines tick will wait, similar to what you do (tick might be more accurate). ~DR0ID
Re: [pygame] frame independant movement
Luke, you said: "Another thing you can do is just use Clock to limit the FPS to 60 or something, but then your game will run slower if you're not getting 60 fps." Well, true, but you MUST determine the framerate that you want for your game, otherway you will get a 60 FPS in your PC, 70 in another and 120 in another one that is much more faster/newer than yours and in witch your game will turn unusable at this framerate I do this: while(true): #principal loop # get current time t = time.time() doAll() #At the end i get the time needed to do the calculatons & flip T = t - time.time() delta = T - 1/desiredFrameRate if (delta > 0): # if the cycle has been done too fast time.wait(delta) This way you have your desired framerate or the maximum possible. Additionally you can do this: else: GLOBAL_T = GLOBAL_STANDAR_T - delta # delta is <= 0, - and - is + Being GLOBAL_T the t that you use for your position calculations and global_standar_t the value of global_t if delta is 0. Pseudocode, sure 2010/1/31 DR0ID > On 31.01.2010 20:44, Yanom Mobis wrote: > > How do you make things happen ingame at a constant speed regardless of > frames-per-second? For example, i want my game object to move one square per > second, even if the game is running 30, 45, 60, or 90 fps. > > > Hi > > make it time dependent. > > > # dt is the time passed since the last frame > # use a dt = min(100, dt) to make sure the longest possible frame is 100 ms > long > # this prevents 'jumps' when a frame took long (as moving the window on > windows) > > def update(self, dt): > self.position += self.velocity * dt > > > This solution may have other side effects. > > ~DR0ID > -- Nota: Tildes omitidas para evitar incompatibilidades. :wq