• # Achieving Frame Rate Independent Game Movement

General and Gameplay Programming

[size="5"]Introduction

I often come across the common question, "How do I allow for movement speed in games that is unaffected by frame rate?" While pondering this same question, I recognized the same problem in some games I have written where the object movement has always been too fast when the frame rates were really high. This article is aimed at showing a simple way around this problem. There may be plenty of examples and articles like this already available, but in this article I will offer my own approach to the solution.

In solving the movement problem, there are different methods you can use. One such common approach has been to implement delays to use up extra game cycles on faster computers. An example would be:

while (GetCurrentTime()-starttimeThis code would loop without doing anything until the difference between the last time taken and the current time is equal to how long you want to delay for. This method can in fact slow down your game, but you would still see some speed differences on faster computers. Also, it can cause games to become choppy on certain machines. [size="5"]Limiting Movements A better approach is to change the movement based on how many frames are being rendered every second. To demonstrate this solution, I have modified NeHe's Tutorial Number 23, which I hope many of you will be familiar with. This particular NeHe tutorial already uses a function for determining time, so we won't need to perform a large number of modifications to the code. The basic idea is to determine how much time has elapsed between frames and then change how much we want to move accordingly. As an example, in NeHe Lesson 23 you are walking around a small structure. To move you may want the character to move 2 blocks every second. To move those 2 blocks, all the movements for all the frames you are rendering in one second would have to add up to two. Thus, you must determine how much time is passing between your frames to get the frame rate. First you must remove the old timer code from the program. //while(TimerGetTime()The next step is to define some variables in the main function. These are to be put at the top of the WinMain function. float timer; //used to check the current time float timerdiff; //used to determine the time elapsed float secsperframe; //used to hold the value for how many seconds have elapsed between frames float desireddistance; //desired distance to move in a second float movementvalue; //value to move by each frameNext, set the desired distance value to move over the course of a second. I found 2 to be a good number. desireddistance=2.0f;If you are getting 80 frames a second then you would want your character to move .025 units every frame since 80*.025 = 2. What you first must do is figure out how much time has elapsed since the last frame. To do this, take the current time before the main loop starts for the first time. timer = TimerGetTime(); [size="5"]Determining Time Differences After rendering the scene, compare the current time with the one you last took. We will store this in the secsperframe variable. //first determine how many seconds elapsed timerdiff = TimerGetTime()-timer; //the function reads in milliseconds so convert to seconds by dividing by 1000 secsperframe=(float)(timerdiff/1000.0f);Let's say the number comes out to be .0125. To get the frame rate, simply divide 1 second by that .0125. This gives you an answer of 80, since 80 times that .0125 is equal to 1 second. To determine how much to move, you simply take the desired distance and divide by the frames per second. [bquote] Movement = (desired distance)/(frames a second)[/bquote]In this example, that would be 1 divided by 80 which would give you .0125 as stated above. The equation can be changed, though, if we substitute in the equation for frames per second. Now it reads: [bquote] Movement = (distance desired)/(1/seconds per frame)[/bquote]This can be further simplified to: [bquote] Movement = (distance desired)*(seconds per frame)[/bquote]I find this equation to be the easiest to use. In NeHe Lesson 23, this looks like: //now compute the movement value movementval = (float)(desireddistance*secsperframe); //get the new time timer = TimerGetTime(); [size="5"]Moving the character Now that we have our current movement value, it's time to put it into the by replacing the old movement code with the new. if ( buffer[DIK_UP] & 0x80 ) { //old code //xpos -= (float)sin(heading*piover180) * 0.05f; //zpos -= (float)cos(heading*piover180) * 0.05f; //new code xpos -= (float)sin(heading*piover180) * movementval; zpos -= (float)cos(heading*piover180) * movementval; ... }These changes can easily be applied for moving in all directions. [size="5"]Modifying head movement As a final change, I also changed the speed of the head bob. The default change is 10 units every frame, so at 80 frames a second, the movement is 800 degrees per second, which is quite a few of cycles (360 degrees in a circle). At a reasonable frame rate of 40 frames per second the head would bob only 400 degrees. The goal is to vary how much the angle is changed every frame based on the frame rate. To accomplish this, multiply the number of degrees you want the bob movement to change in one second by the number of seconds between frames. At 80 frames per second, there are .0125 seconds between each frame (as previously mentioned). If you want the head to move 400 degrees every second, then multiply 400 degrees by the .0125 seconds between each frame, and you arrive at the number of degrees to perform the head bob movement for the frame. walkbiasangle+=(400.0f*secsperframe);In this example the change in the angle would be 5 degrees every frame. At 80 frames per second, the total degrees would be 400 degrees every second. In conclusion, I cannot say if this is the absolute best way to handle character movement, but it's a method that has worked for me thus far. I would like to thank Jeff Molofee and Justin Eslinger for their work on the original tutorial. If you have any questions or comments, feel free to e-mail me at [email="ricart3@tcnj.edu"]ricart3@tcnj.edu[/email].
 
 0   Report Article 
 Sign in to follow this   Followers 0 Go to articles General and Gameplay Programming 
 User Feedback 0 Comments 0 Reviews There are no comments to display. Create an account or sign in to comment You need to be a member in order to leave a comment Create an account Sign up for a new account in our community. It's easy! Register a new account Sign in Already have an account? Sign in here. Sign In Now 
•  
 
 Advertisement 
 Advertisement What is your GameDev Story? In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us. (You must login to your GameDev.net account.) Share My Story Latest Featured Articles 0 Developing an Isometric Plugin for Unity3D By MATov Sunday at 12:43 PM 4 A Practical Approach to Managing Resource States in Vulkan and Direct3D12 By DiligentDev January 13 0 Getting the Best from Writers By GameDev.net January 7 0 How Dragon Quest Builders Brings a Ludus-centric Design to a Paidia-centric Mechanic By Christopher King December 16, 2018 0 Improbable's SpatialOS GDK for Unity By GameDev.net November 30, 2018 Featured Blogs Post-Mortem Of The Dungeon Crawler Challenge By Hermetix in The Zen of Game Programming    3 Some Handy Procedural Methods (Placing objects on the ground in circle/grid patterns or individually) By Septopus in Unsettled World    0 GameDev - Dungeon Crawler Challenge - Part 1 By Rutin in Rutin's Dev Blog    4 Playing with water physics By lawnjelly in Lawnjelly's Journal    3 SlingBots - First Playable Arena Level & The SuperLoop! By Septopus in Unsettled World    0 Advertisement Popular Now 15 DX12 D3D12 Fence and Present By acerskylineStarted Monday at 07:00 AM 10 Malware is compiled into my exe... (but only for one project) By sulimanStarted Sunday at 08:04 PM 11 C++ Virtual Machine Questions By JosheirStarted Sunday at 06:57 PM 9 Lighting: Inside faces are getting lighted too? By babaliarisStarted Sunday at 06:44 PM 9 Windows 10 makes old games crash fullscreen By Sound MasterStarted Sunday at 03:18 PM GameDev.net GameDev.net Articles GameDev.net Event Coverage GameDev.net Forums GameDev.net Blogs GameDev.net Gallery GameDev.net News GameDev.net Projects GDNet Chat All Activity Search In Everywhere This Category This Article More options... Find results that contain... All of my search term words Any of my search term words Find results in... Content titles and body Content titles only Home Articles Programming General and Gameplay Programming Achieving Frame Rate Independent Game Movement 
 
 
 × Existing user? Sign In Sign Up Browse Back Articles & Tutorials Back All Categories Audio Business Game Design Industry Programming Visual Arts Columns Back GameDev Unboxed Event Coverage Back All Events Game Developers Conference Power Up Digital Games Conference GameDev.Market Links News Podcasts Back All Podcasts Game Dev Loadout Archive Community Back Beginners Back Beginners Group Beginners Forum Beginners Resources Blogs Calendar Chat Forums Back All Forums Audio Business Game Design Programming Visual Arts Community GameDev Challenges Affiliates Topical Workshops Gallery Groups Back For Beginners GameDev Challenges All Groups Projects Back All Projects Games Game Assets Game Mods Developer Tools Store Forums Back All Forums For Beginners Audio Back Music and Sound FX Games Career Development Business Back Games Career Development Production and Management Games Business and Law Game Design Back Game Design and Theory Writing for Games Programming Back Artificial Intelligence Engines and Middleware General and Gameplay Programming Graphics and GPU Programming Math and Physics Networking and Multiplayer Visual Arts Back 2D and 3D Art Critique and Feedback Community Back GameDev Challenges GDNet Lounge GDNet Comments, Suggestions, and Ideas Coding Horrors Your Announcements Hobby Project Classifieds Indie Showcase Affiliates Back NeHe Productions AngelCode Topical Workshops Careers Back Contractors Hobby Projects Game Jobs Back Browse on GameDev.Jobs Post a Job Members Back Subscriptions Chat Guidelines Leaderboard Online Users Awards Search Back All Activity My Activity Streams Back Latest Topics Featured Blogs Search Important Information By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.   I accept GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry. Sign me up! 
 $('body').click(function (e) { var container =$("#pagecontainer"); if (($(e.target).parent().prop('nodeName') == 'BODY') && (container.has(e.target).length === 0) && (e.button == 0) && (!$(e.target).hasClass('ipsDialog'))) { window.open('https://ad.doubleclick.net/ddm/trackclk/N129002.1825GAMEDEV.NET/B11085475.236262913;dc_trk_aid=433791501;dc_trk_cid=90245747;dc_lat=;dc_rdid=;tag_for_child_directed_treatment=;tfua='); ga('send','event','Advertisement','Click','3q_fb_gamedev_skin_2019_1'); } }); $(document).ready(function() { setInterval(function() { window.googletag.pubads().refresh(); }, 30000); });$(document).ready(function() { if (ipsSettings.memberID > 0) { ga('send','event','User','View','Member'); } else { ga('send','event','User','View','Guest'); } });