12
\$\begingroup\$

"Super Meat Boy" is a difficult platformer that recently came out for PC, requiring exceptional control and pixel-perfect jumping. The physics code in the game is dependent on the framerate, which is locked to 60fps; this means that if your computer can't run the game at full speed, the physics will go insane, causing (among other things) your character to run slower and fall through the ground. Furthermore, if vsync is off, the game runs extremely fast.

Could those experienced with 2D game programming help explain why the game was coded this way? Wouldn't a physics loop running at a constant rate be a better solution? (Actually, I think a physics loop is used for parts of the game, since some of the entities continue to move normally regardless of the framerate. Your character, on the other hand, runs exactly [fps/60] as fast.)

What bothers me about this implementation is the loss of abstraction between the game engine and the graphics rendering, which depends on system-specific things like the monitor, graphics card, and CPU. If, for whatever reason, your computer can't handle vsync, or can't run the game at exactly 60fps, it'll break spectacularly. Why should the rendering step in any way influence the physics calculations? (Most games nowadays would either slow down the game or skip frames.) On the other hand, I understand that old-school platformers on the NES and SNES depended on a fixed framerate for much of their control and physics. Why is this, and would it be possible to create a patformer in that vein without having the framerate dependency? Is there necessarily a loss of precision if you separate the graphics rendering from the rest of the engine?

Thank you, and sorry if the question was confusing.

\$\endgroup\$
2
  • \$\begingroup\$ Tangential to your question. Here is a great article that covers exactly the problems you're describing, and the "right" way to handle timesteps and frame-rates. gafferongames.com/game-physics/fix-your-timestep \$\endgroup\$
    – num1
    Dec 29, 2010 at 4:14
  • \$\begingroup\$ It actually really surprised me that they would do it this way. I suppose it must be because it was built primarily for console, where frame rate can be relied upon. Disappointing! \$\endgroup\$
    – Iain
    Jan 4, 2011 at 12:02

5 Answers 5

7
\$\begingroup\$

Why?

Handful of reasons, take your pick: They didn't know any better. .It's quicker and easier to implement. They were focused more on the gameplay and less on the edge cases that might not crop up in most cases.

You did a pretty good job of explaining why not. I'm sure you've noticed there's lots of topics that cover the subject. I'm not sure you'll find a satisfactory answer beyond the ones I listed.

\$\endgroup\$
1
  • \$\begingroup\$ "They didn't know any better" describes why I've taken that approach with "Jack is a Fool". But - I've relied heavily on calling the dt since the last frame with all of my logic. But - with floating point coordinates, it can lead to some weird, hard to replicate bugs \$\endgroup\$
    – lochok
    Mar 11, 2012 at 1:32
4
\$\begingroup\$

SMB was originally a console game where it's safe to assume that it's able to run at 60fps on all Xbox360s (well, maybe 50 for some PAL players). Assuming a fixed timestep simplifies the code a fair bit.

Whilst it's easy to scale a lot of things by a variable timestep - 'pos += velocity * timestep', it gets quite tricky to do it correctly when you're dealing with accelerations, and rates of change of acceleration, and so on.

Decoupling gameplay and rendering is a nice solution in theory, but implementing it well (with good interpolation) is quite tricky, and things can easily get messy. It's fairly uncommon for this technique to be used in real games (although some big games do do it, particularly RTS games, but more for network game synchronization).

When also designing for a fixed screen resolution as well as a fixed framerate, there's one other thing you can do to make the scrolling extra smooth. You can ensure that the game scrolls at a whole number of pixels-per-frame - avoiding any 'subpixel wobble' you may get by scrolling a fractional number of pixels per frame.

\$\endgroup\$
1
\$\begingroup\$

The obvious solution is to have 2 loops running in parallel - the rendering every 1/60 of a second and the game loop every 1/60 of a second.

But with my experience in Flash (AS3, which I'm pretty sure Super Meat Boy was created in), the scheduler isn't always very accurate. The accuracy also depends highly on the environment. In the stand alone flash player, it might have sub-millisecond resolution. But when run in some web browsers, it's accuracy becomes that of the frame rate.

So the closest way you can get to decoupling the rendering and game logic loops is to have all movements be time based (and run each frame based on how much time elapsed since the last frame). That can introduce some more complicated mathematics (like having gravity be applied continuously, rather than adding to the velocity of an object at set intervals). Because the game could lag for a second and then your player would be moving 200 pixels in one step, collision detection and response can become even more complicated. If the programmer was doing frame based collision detection (checking for a collision each timestep), they would have to switch to time based collision detection too. And if they wanted it to feel natural, they would have to use the gravity method described above, which causes object movement be a curve (as opposed to a line), which makes determining the time of intersection between 2 objects even more difficult.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The original Meat Boy was a Flash game. Super Meat Boy is a C++ game. \$\endgroup\$
    – Archagon
    Dec 28, 2010 at 6:19
0
\$\begingroup\$

I don't think its to much to ask for 2D PC games to play at 60fps anymore. Even most 2D games are hardware accelerated now so personally I wouldn't worry about the fps requirement.

The real question is why wouldn't you use a pixel based, games are full of cheats and shortcuts.

If you are making a physics based game (bird throwing perhaps?) the answer is obvious, but a super mario clone? time based movement might be a bit much.

\$\endgroup\$
1
  • \$\begingroup\$ It's not hard to play them at 60fps, but displays with native refresh rates of 50Hz, 70-85Hz, and 120Hz are still easily found. \$\endgroup\$
    – user744
    Dec 29, 2010 at 0:05
0
\$\begingroup\$

To avoid strange behavior in the 2d physics they're using?

Honestly I can just guess. I'll try an explanation:

At heart of the game is the main game loop. Which basicly looks like this:

while(gameRunning)
{
  updateGame(timestep);
  renderGame(timestep);
}

updateGame updates the gameState: checks player input, applies player input to the game world and runs the physics simulation etc.

renderGame draws and animates the game.

This couples the physics update to the rendering. If you want to decouple it you would need use threads and properly synchronize each data access of the rendering and the gameUpdate thread to shared data e.g. player position. This can be done.

Another problem might be that the physics simulation requires a constant timestep to run stable. This depends on how supermeatboy calculates the movement (Again we can just guess how they've done it ;) ).

A naive approach would be (which I'm using in my game *sigh*):

position=position+speed*timestep;
speed=speed+acceleration*timestep;

This is called Euler Integration and is generally considered to be a bad idea. If the timestep is none-constant calculation errors occur which will make the simulation less stable. Object might move at excessive speeds or not all or fly through the walls off the screen. Even if the timestep is constant Euler Integration causes minor calculation errors. Better use another integration method like RK4 or use a physics engine.

Apart from that there can be problems doing the collision detection if the timestep gets too large. Since collisions are not checked between two gameUpdates, objects might pass through obstacles.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .