Jump to content

How should the update and render logic be separated?


mtycholaz
 Share

Recommended Posts

I've been trying to wrap my head around understanding the update and render functions.

 

Here's my game loop:

  • Update function runs at 25 fps
  • Render function runs as fast as it can (usually 50-60 FPS)

For the sake of argument, lets pretend that I'm going to animate a box moving from left to right on the screen.

 

Here's what's bugging me. If I put the code to change the xy into the update function, then in one second the box will have 25 position changes. Essentially, even though my render loop runs faster, the animation would appear to run at 25 FPS. 

 

I want to take advantage of my faster running rendering function for smoother animations. It would seem to me that I should initiate the move in the update function. Something like .moveTo(position), but then actually set the xy coordinates of the object in the render function.

 

This is my first time writing a game loop so I'm not sure how other people do it, but it just seems weird to me to change the xy coordinates in the render function.

 

I'd like to know how other people have approached this problem and what your solutions are.

 

UPDATE:

 

Or should the update function change the xy coordinates, and the render function just interpolate the change/difference in values?

Link to comment
Share on other sites

Separating update and render is probably a good idea, but I don't think they should be completely independent: why render the same frame again if you haven't updated anything? You may want to wait until an update occurs before re-drawing.

 

 

Or should the update function change the xy coordinates, and the render function just interpolate the change/difference in values?

 

This would give you the best visual result, but it's an expensive process, because you need the xy coordinates for two update frames to be able to interpolate, and the interpolation itself takes time.

 

For this reason many people update some things in the update function (for example position coordinates), some other things in the render function (for example which animation frame to show for an animated character).

 

I suppose it's a matter of finding a good balance between performance and visual appearance.

Link to comment
Share on other sites

Just use one loop: update.

Call the render function from the update loop, like this:

function update() {  requestAnimationFrame(update, canvas);  //... game logic...  render();}function render() {  //Render your sprites}
Link to comment
Share on other sites

I recently implemented what Glenn Fiedler described in his very popular article: http://gafferongames.com/game-physics/fix-your-timestep/

It works very well for me so far. If I run logic at 30 fps, difference between interpolation on/off  is very noticeable on desktop (60fps) even more so on modern monitors (120 fps).

 

Essentially what I did is:
Run normal requestAnimationFrame, keep a buffer of time passed, run logic like so:

while (accumulator >= dt){  accumulator -= LOGIC_STEP_TIME;  runLogic();}render();

This means that you can have more logic steps per frame (if device is slow and you have say 20 fps) or less than 1 per frame if you run logic at 30fps and render at 50-60fps.

So why render if you don't do logic update?

Interpolation.

 

You take accumulator time, divide it by LOGIC_STEP_TIME and you get alpha number [0-1). Then you interpolate between old position and new one according to that number. So you do something like this:

gfx.x = (x - old_x) * alpha + old_x;

Only problem with this is you are always rendering 1 step behind logic. But when you think about it, it's about 33ms difference at most. That's so tiny we can't react so fast and can't notice it either. On mobile games it's even more negligible since you cannot make fast paced action game based on player needing muscle memory to get through levels.

 

You could extrapolate instead of interpolation, but that would result in noticeable errors and thus is worse than interpolating.

 

One last thing:
I disagree with Gio in that interpolating is expensive process. Sure you need twice the memory for spatial data and you need to do something with that data. But unless you have thousands of items it doesn't matter. All other stuff like particles and easing animations you do with speed (or easing function), so you don't need to interpolate. Which is what you can do to levarage 60fps with 30fps update too. Run you logic at 30, rendering game objects will be also 30, but easing animations and particles and other stuff whose position isn't based on game logic could render at 60fps. But I still like interpolation better, especially since mobile games can rarely afford particles :)
Link to comment
Share on other sites

Just use one loop: update.

Call the render function from the update loop...

This isn't very physics engine friendly as it could make it unstable. Even if you code based on timestep and not constants it could make your game feel very differently on slow and fast devices. If you aren't coding based on timestep then your game would run at 200% speed on my pc. 

Link to comment
Share on other sites

If you aren't coding based on timestep then your game would run at 200% speed on my pc. 

Could explain this further? My understanding is that requestAnimationFrame is synchronized with the screen refresh rate (which is 60hz on almost every device) so the game loop will run at about 60fps regardless of the CPU clock speed.

Link to comment
Share on other sites

 

I recently implemented what Glenn Fiedler described in his very popular article: http://gafferongames.com/game-physics/fix-your-timestep/

It works very well for me so far. If I run logic at 30 fps, difference between interpolation on/off  is very noticeable on desktop (60fps) even more so on modern monitors (120 fps)....

 

 

I've came across this article before during my research and based my game loop off it. It's a very well done article. Where I'm having trouble is how to synchronize my objects in memory with what is on the screen.

 

From what I've read, people have two objects to solve this. The first is in memory and represents the current game state. The second is the display object, which is the actual object on-screen. The memory object is only updated during the update function, and the display object is updated during the render function. Basically I would need to use interpolation during the render, and update the position. I will have to experiment though to see what happens during lag, and high/low FPS.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...