Time1 = gettickcount (); frametime = 0;Int Numloops = 0; While (Time1-time0)> tick_time & numloops
This portion is the game logic update sequence that forces the game logic (physics updates, object motion, animation indexing ing, Etc ...) to update a set number of times per second. this rate is controlled byTick_timeConstant, which specifies the number of milliseconds the logic update is supposed to represent in real time. it probably won't take that long to perform, in which case the update won't be passed Med again until enough time has passed. for example,Tick_time = 40, Each logic represents 40 milliseconds, thus forcing the code to update game objects at a rate of 25 times per second.
This part of the code processes game logic updates and forces the game logic to execute a fixed number of times per second.
Game logic processing includes physical updates, object behavior, and animation loops. The update rate is specified by the tick_time constant, which indicates the interval between two logical updates. That is, the update should be performed again after tick_time, rather than the duration of a logical update.
For example, tick_time = 40 indicates that the performance of each game logic update is 40 milliseconds, which makes the game objects updated 25 times per second.
The logic is encapsulated in it's own while loop. it is possible during a given frame that game logic will take too long. if a logic update cycle goes overtime, we can delay rendering for a bit to give ourselves a little extra time to catch up. the while loop will continue to process game logic updates until we are no longer overtime, at which point we can go ahead and continue on with drawing the view. this is good for handling the occasional burp in logic updating, smoothing out the updates and keeping them consistent and deterministic; but in the case that the logic repeatedly goes overtime, it is possible to accumulate more time-debt than the loop can handle. thus, Max_loops Constant is in place to dictate a maximum number of times the loop can repeat to try to catch up. it will force the loop to dump out periodically to handle other tasks such as input handling and rendering. A loop that is constantly running at Max_loops Limit runs like hell and is about as responsive as a tractor with four flat tires, but at least it keeps the Loop Operating, allowing the user to pass input to terminate the program. Without Max_loops Failsafe, it wocould be entirely possible for a slow computer to lock up with no way to exit as it chokes on the loop, trying to catch up but getting further and further behind.
The logic update code is wrapped in its own while loop.
In a frame, the processing time of the game logic may be very long or even time out. In this case, we can pause the screen rendering a little, this allows game logic updates to catch up during this period.
This while loop is used to keep the game logic updated until we no longer time out. Then we continue the main loop of the game and perform screen rendering. This can well handle sudden logical update timeouts, make our updates smoother, and ensure logical consistency and predictability.
However, if the game logic processing times out continuously and even makes the main loop unable to be processed, max_loops will play a role, and he will make the game control jump out of the logic update, execute other tasks such as input processing and screen rendering.
The max_loop constant limits the maximum number of times a while loop can repeat when it is used to catch up with the logical processing time. In this way, when the game is unable to process the logic update, the user also has the opportunity to end the program.
Without max_loop detection, it is likely that a very slow computer will try to catch up with the logic processing time, but it will get farther and farther, and has no chance to exit the process, finally stuck in this endless loop ......
Independenttickrun (frametime );
This section is where input is gathered, events are pumped from the event queue, interface elements such as life bars are updated, and so forth. javier allows for passing how much time the logic updates took, which can be used for updating on-screen clock or timer displays and the like if necessary. I 've never found occasion to use it, but I regularly pass it anyway on the off-chance I'll need it someday.FrametimeBasically gives the amount of time that was spent in the logic loop refreshing updates.
This part of the code is used to process the capture of user input. events will be retrieved from the event queue for processing. interface elements, such as blood records, will be updated here, and other similar processes.
Javier has a frametime parameter to indicate the time spent in logical update. You can use this value to update similar information such as the clock or timer on the game screen.
Although I haven't found a chance to use it yet, I still habitually take it with me. Maybe I will need it one day.
In order for the game loop to run predictably, you shocould not modify anything in this step that will affect the game logic. this portion of the loop does not run at a predictable rate, so changes made here can throw off the timing. only things that are not time-critical shocould be updated here.
To make the game loop run predictable, you should not modify anything that may affect the game logic here, because the number of executions of this Part in the main loop is unpredictable, therefore, only time-independent updates can be made here.
// If playing solo and game logic takes way too long, discard pending time.If(! Bnetworkgame & (time1-time0)> tick_time) time0 = time1-tick_time;
This is where we can shave off our time debt if Max_loops Causes us to dump out of the logic loop, and get things square again -- as long as we are not running in a network game. if it is a single-player game, the occasional error in the timing of the game is not that big of a deal, so sometimes it might be simpler when the game logic overruns It's alloted time to just discard the extra time debt and start fresh. technically, this makes the game "fall behind" where it shoshould be in real time, but in a single player game this has no real effect. in a network game, however, all computers must be kept in synchronization, so we can't just cavalierly discard the pending time. instead, it sticks around until the next time we enter the logic update loop, where the loop has to repeat itself that gets more times to try to catch up. if the time burp is an isolated instance, this is no big deal, as with one or two cycle overruns the loop can catch up. but, again, if the logic is consistently running overtime, the performance of the game will be poor and will lag farther and farther behind. in a networked game, you might want to check for repeated bad performance and logic loop overruns here, to pinpoint slow computers that may be bogging the game down and possibly kick them from the game.
When the logic loop exists because the max_loop condition is met, You can subtract more tick_time time here and only do this in standalone games.
In a single-host game, occasional time errors do not cause any major problems. Therefore, when the game logic execution times out, it does not matter much, we simply cut the extra time and start over again. Technically speaking, this will make the game lag behind for a little time, but it does not have any practical impact in standalone games.
However, this does not work in online games. All connected computers must maintain time synchronization.
In online games, if a computer lags behind, he should keep it backward. Then, when entering the logic update loop, he should repeat himself several times, to catch up.
If the time delay is just an isolated event, there will be no major problem. After one or two speeding events, it will catch up. However, if the game's logic update always times out, the performance will be very bad, and will eventually lag behind.
In online games, you may need to check out these computers that have consistently timed out and are always poorly performing, and kick out those computers that may have slowed down the entire game environment.
// Account for numloops overflow causing percent> 1.FloatPercentwithintick = min (1.f,Float(Time1-time0)/tick_time); gamedrawwithinterpolation (percentwithintick );
This is where the real magic happens, in my opinion. This section performs the rendering of the view. In the case of a loop whereTick_time = 40, The logic is updating at 25 FPS. however, most video cards today are capable of far greater framerates, so it makes no sense to cripple the visual framerate by locking it to 25 FPS. instead, we can structure our code so that we can smoothly interpolate from one logic state to the next.PercentwithintickIs calculated as a floating point value in the range of [0, 1], representing how far conceptually we are into the next game logic tick.
Here we will plot the screen.
When tick_time = 40, the frame rate of logical update is 25fps, but most video cards now support a higher frame rate, so we do not need to lock the rendering frame rate to 25fps.
We can organize our code so that we can smoothly perform interpolation from a logical state to the next state. Percentwithintick is a floating point number between 0 and 1, which indicates how far we should go to the next logical frame.
Every object in the game has certain State regardingLasttickAndNexttick. Each object that can move will haveLastpositionAndNextposition. When the logic section updates the object, then the objectsLastpositionIs set to it's currentNextpostionAnd a newNextpositionIs calculated based on how far it can move in one logic frame. Then, when the rendering portion executes,PercentwithintickIs used to interpolate between these last and next positions:
Each movable object has lastposition and nextposition. The code of the logic update part sets the lastposition of the object to the current nextposition during execution, and calculates the nextposition based on the distance that each frame can move.
Then, when rendering an object, you can use percentwithtick to perform interpolation between the last and next positions.
:
Time0 is the time point of the last logical frame, time1 is the current actual time, (time1-time0)/tick_time indicates the percentage of the current time exceeds the time of the last logical frame, use this percentage to perform Interpolation on the next logical frame.
If the machine is faster, screen rendering is performed multiple times between two logical update points, which makes interpolation effective. At this time, time0 remains unchanged and time1 continues to grow. You can calculate the length of the animation from the last logical update position to the next logical update position based on the percentage of increase.
That is, as mentioned above, interpolation is performed between the last and next positions. The actual position after interpolation, that is, the calculation method of drawposition is as follows:
The Interpolation of animation playback is similar.
Drawposition = lastposition + percentwithintick * (nextposition-lastposition );
The main loop executes over and over as fast as the computer is able to run it, and for a lot of the time we will not be using Ming logic updates. during these loop cycles when no logic is saved med, we can still draw, and as the loop progresses closer to the time of our next logic update,PercentwithintickWill increase toward 1. The closerPercentwithintickGets to 1, the closer the ctualDrawpositionOf the object will getNextposition. The effect is that the object smoothly moves from last to next on the screen, the animation as smooth as the hardware framerate will allow. without this smooth interpolation, the object wocould move in a jerk from lastposition to nextposition, each time the logic updates at 25fps. so a lot of drawing cycles wocould be wasted repeatedly drawing the same exact image over and over, and the animation wocould be locked to a 25fps rate that wowould look bad.
The main loop of the game keeps running at the maximum speed that the computer can achieve. In most of the time, we do not need to perform logical updates.
However, in these cycles, we can still execute screen rendering. When the cyclic process approaches our next logical Update Time, percentwithintick approaches 1. The closer percentwithintick is to 1, the closer drawposition is to nextposition.
The final effect is that the game object moves slowly and smoothly from the last position to the next position on the screen, and the action will be as smooth as possible with the hardware frame rate.
Without this smooth interpolation process, the object position will jump directly from the lastposition of the previous frame to the position nextposition of the next frame. A large number of rendering cycles are wasted on repeatedly rendering objects to the same position, and the animation can only be locked at 25 FPS, making it very ineffective.
With this technique, logic and drawing are separated. it is possible to perform updates as either as 14 or 15 times per second, far below the threshold necessary for smooth, decent looking visual framerate, yet still maintain the smooth framerdue to interpolation. low logic update rates such as this are common in games such as real-time strategy games, where logic can eat up a lot of time in pathfinding and AI calculations that wocould choke a higher rate. yet, the game will still animate smoothly from logic state to logic state, without the annoying visual hitches of a 15fps visual framerate. pretty danged nifty, I must say.
After using this technology, the logic update and screen rendering are separated.
This will allow us to reduce the Frame Rate of the logical update to 14 or 15 FPS, which is much lower than the frame rate required for smooth animation rendering, however, animation interpolation can still maintain a smooth rendering frame rate.
In real-time strategy games, such a low frame rate of logical update may be used. Here, logical update takes a lot of time for path finding and AI computing, in this case, the use of a High logical update frame rate obviously does not work.
However, the game can still perform smooth animation transitions between different logic states, without the annoying animation jumps due to the rendering frame rate of only 15 FPS.
Very beautiful, I have to say.
I 've created a simple program in C to demonstrate this loop structure. It requires SDL (http://www.libsdl.org) and OpenGL. It's a basic bouncy ball program. The controls are simple: PressQTo exit the program or pressSpaceTo toggle Interpolation on and off. With Interpolation on, the loop executes exactly as described to smooth out the movement from one logic update to the next. With interpolation off, the interpolation factorPercentwithintickIs always set to 1 to simulate drawing without interpolation, in essence locking the visual framerate to the 25fps of the logic update section. in both cases, the ball moves at exactly the same speed (16 units per update, 25 updates per second), but with interpolation the motion is much smoother and easier on the eyes. compile and link with SDL and OpenGL to see it in action: http://legion.gibbering.net/golem/files/interp_demo.c