Categories
Game Development

Oracle’s Eye Development: Frame Rate Independence

Last time I mentioned that I had made a stick figure to move around. I implemented four degrees of movement for it, but I still don’t have a timer to make it move at a sane rate. Since this project is late anyway, I figured I might as well learn about implementing frame rate independent movement.

I actually looked at my GiD entry and found that it was handling the timer code badly. Basically, the game would update every time an SDL Event occurred. Normally the event would just be the timer callback and would run fairly regularly. But if you pressed a key or released a key, an extra update and draw would occur. Now, I programmed it to allow you to hold the key down to move so it only speeds up when changing directions and may not be as noticeable; however, if you press keys multiple times, it becomes very obvious. For my first GiD, I suppose it isn’t that big of a deal.

For Oracle’s Eye, I decided to create frame rate independence. It basically means that the rendering happens independent of the game world updates. The game can go from 30 frames per second to 100 frames per second to 15 frames per second, but the game world will still update once every 10 milliseconds or whatever I want to set it to. It should result in smoother animation and movement.

When I started this project I didn’t think that I would be working on such an “advanced” topic. It sounded a bit complex and beyond my abilities. Well, screw that thinking. It can’t be THAT far beyond what I can currently do. In fact, when I think about it, making games in general is still a challenge I haven’t decisively overcome yet, so I’m charging forth. Screw you, Pessimism!

Luckily someone just posted about this topic on the SDL mailing list and so now I have a link: Game Physics: Fix Your Timestep!. Reading it gave me some idea about what needs to be done, but variable names like t and dt and functons that come out of nowhere make it hard to follow. I was able to find another article on gamedev.net called Achieiving Frame Rate Independent Game Movement. It is a bit shorter, more to the point, and easier to follow.

Problem # 1: It is a good thing that I haven’t gotten too far with my game project because implementing this feature is going to require a redesign. I originally envisioned moving my characters about by telling them to move so many pixels directly. For example,

player->moveX( moveSpeed );

should move the player sprite to the right by moveSpeed distance. If moveSpeed is 5, then the sprite will move to the right five pixels.

It would have been fine, but with FRI movement, I would need to do something different. As I understand it, I would have to know where the sprite started and where it will end up. Then I have to calculate at any given moment where it is along that path. Whereas before I would have moved the player sprite an arbitrary number of pixels, now I will need to determine how many pixels it moves each second then calculate how far to move it per frame. If a player should move 60 pixels per second, then the total movement of the sprite in all frames in that second should add up to 60 pixels. The trick is figuring out the movement each frame.

Problem #2: FRI movement works much better in 3D than in 2D. In 3D, the actual 3D model is just math. You can interpolate the animation of the model, and it will look smooth no matter how slow or fast you run it. I’m using sprites, and sprites have only as many frames of animation as I created. Let’s say I have three frames of animation for a walking sprite. Normally, I would just update every so often and make the animation step forward each time, but with FRI movement, how do I handle the partial movements AND animate at a normal pace? I can’t update each movement because then it looks like the player sprite is running way too fast. Do I have to figure out how far it should move before each frame gets updated? Does it even make sense to have FRI movement in a 2D game?

Starting this, I felt a bit overwhelmed. That’s a lot of things to take in, and all I wanted to do with Oracle’s Eye is make a simple game. Still, I forged ahead. I figured it is better to learn about it sooner rather than later.

I found a few more articles: Main Loop with Fixed Time Steps on Flipcode and Frame Rate Independent Movement on Gamedev.net. I also found a few threads on gamedev.net that discuss “time based movement”.

It actually doesn’t seem so bad now, at least for Problem #1. In fact, I don’t have to change my existing code all that much. I changed the moveX() and moveY() functions to take floats as arguments instead of ints. I added some timer variables: one for the delta, one for the current time, and one for the last time.

In my PlayState::update() function:

gTemp_currentTime = SDL_GetTicks();
gTemp_deltaTime = (gTemp_currentTime - gTemp_lastTime) / 50.0f;
gTemp_lastTime = gTemp_currentTime;

Then for each of the directions, I just change the code from:

gTemp_player->moveX( -gTemp_speed );

to

gTemp_player->moveX( -gTemp_speed * gTemp_deltaTime );

The 50.0f is fairly arbitrary. The code I got it from used 1000.0f to convert from milliseconds to seconds, but I found that the delta almost never became anything greater than 0, which meant that nothing moved. Using 50.0f seems to be fairly fast and smooth on my system. Of course, it depended on gTemp_speed which is in pixels per second. If I set it to 50, it ran quickly. Setting it to 25 slowed it down quite a bit, but it was also jerky, and setting it to 100 made it too fast.

It also didn’t take me too long to implement it, so I got suspicious that I did something wrong. After all, it shouldn’t matter how fast the sprite is moving. I will likely have sprites moving at different speeds, so what gives?

I found yet another tutorial, and this one actually made use of SDL. It turns out that I don’t do much differently. I ended up having to add SDL_Delay( 10) to the draw() function to get it to slow down enough, but I think that is a bad kludge. I believe that the reason it won’t move the sprites between each frame is because there isn’t enough to do between frames. The time between frames looks like 0.0 and so nothing happens. The delay allows changes to happen, but there is still the ugly jerkiness every once in awhile.

The next day, I tried again. I changed it so that it will constantly loop until deltaTime is something other than 0. It worked and looked great, but I found out that I forgot to remove the SDL_Delay() line. When I removed it, it ran incredibly slowly again.

So I changed the loop. I basically checked to see if the start and end times were 1/30th of a second apart since I wanted the game to update game logic at 30 frames a second. If the difference was less than that time, I delayed. It seems to work out well. 1/60th of a second looks even nicer, but I’ll have to do more testing to verify.

Unfortunately the use of floats/doubles means that when movement gets converted to ints for Kyra’s sprite movement the precision gets lopped off. I think this loss of precision is the reason why some of the movement might look a bit jerky. Of course, Problem #2 might be a tougher issue, but I’ll have to tackle both of them another time.

I am fairly pleased with what I have done in a few hours over the course of a couple of days. To think that I originally believed that I wasn’t up to the task and would have skipped it. I win.

5 replies on “Oracle’s Eye Development: Frame Rate Independence”

Good on you for tackling the hard stuff!

I’m curious, though. 2D is (can be) just a special case of 3D. If 3D is so much easier for FRI, why not skip playing around with sprite frames and just make the player a flat “3D” model? Or would the extra math work over animating 3D in the first place offset the easier FRI?

Thanks!

2D is a special case of 3D…if you are using 3D methods. Like, if I used OpenGL to just make 2D models. Mathematical models can be manipulated in all sorts of ways, so it would be easy to animate things at variable rates and make them look fine. For instance, I can specify the start position of an arm and the end position, and the math will rotate the arm each frame appropriately.

I’m using the Kyra Sprite Engine, and sprite animation is just a series of images that get updated, like a cartoon. In order to make it look better, I would have to be able to anticipate which frame of animation should be showing at any point in time. I suppose it shouldn’t be too hard to do, but at the moment I think I would have to add more information to my sprite that Kyra’s sprite class doesn’t know about and then I would have to update the sprite manually at the right times, but it seems like it would be a hack to get Kyra to work correctly. I likely don’t know about a feature of Kyra that would help me here. Prior to using FRI, I would just update the movement and the frame of animation for each draw call, but the draw was happening at variable rates and so wouldn’t look right. Now, the transposition might look right, but the actual image might look jerky. I haven’t tried with an animated image yet, but that might be the next thing I mess around with.

Right, I’m familiar with the differences between 2D and 3D, and mesh vs. sprite. My question is, why use the Kyra sprite engine and have to play around with the FRI issues, when you could just use OpenGL or SDL or whatnot and do a flat “3D” model instead, in which case, as you said, the FRI is essentially free.

Or am I underestimating the other difficulties and complexities of using flat-3D for 2D animation? (All the desktop dev guys are saying that’s the future, as 2D hardware cards will go away, but I don’t know how that maps to games.)

Partly because the future isn’t here yet and most people don’t have OpenGL compatible video cards. Partly because I couldn’t find too many cross-platform game APIs. Torque 2D, as I understand it, actually makes use of OpenGL to do rotations and scaling, but as I understand it Kyra will also add OpenGL support and it is licensed under an open source license. I plan on making games with open source code and proprietary data, so Torque 2D is out of the question on that count.

Still, you bring up good points, and making 2D games using 3D engines would be interesting.

For posterity, I just want to point out that when I asked someone else on the Kyra Sprite Engine forums, I learned that 2D sprites should be created to a specific frame-rate. If the sprites move at 30 frames per second, then that is how fast the game should try to update them.

Comments are closed.