The real problem is 'how do I keep motion looking constant at variable framerates' and room speed should really be set to 9999. There are two commonly implemented solutions to this problem: delta time, and one I shall call tweening because that's what I knew it as all my life.
Delta time is the worse looking out of the two and also the harder to implement in the long run. It works as follows:
a global clock tracks the instantaneous framerate of the game.
it divides the desired framerate clock time by this instantaneous rate to produce a coefficient that describes how many times faster or slower the game is running than the clock speed at which it is supposed to.
all moving objects then multiply their speeds by this coefficient in order to appear to move at the same speed on screen
Simple, yes? No. You can't just multiply the object's speed because then it will forget it's original speed. That means you need to keep two variables for speed. Then we have hspeed and vspeed, same problem. Motion add - needs to be rewriten with delta time in mind. Acceleration? Same thing. And after you've done all that, it will look rather jittery if the framerate changes too much over too short a period of time. If you pause the game (while say, moving the window) then the clocked fps will drop to almost zero and when unpaused, all the objects will try to compensate for this by approaching very high speeds (thus you get an explosion of sorts after moving the window around). An example of this, along with some other stuff can be found here
The second, tweening, is much more fun. In theory it should be both easier to implement, and much cleaner looking. The idea of it is to sepperate to run the game logic and graphics at two different clocks. The logic is forced to a constant say, 30 fps. And the graphics are floating taking up as much of the remaining time as possible. On each logic update, the x,y,xprevious, yprevious of all objects are updated. The drawing then uses this to draw the objects between it's current and previous location based on how far along it is to the next logic cycle. This means that if I ran a game using it with the logic locked to 5fps and made a ball chase the mouse, I would see it very smoothly glide over to the mouse position (sort of like more_towards_point) but it would only react to the mouse position at 5fps meaning that if i moved it constantly, it would move towards where I started moving it.
Implementing it goes as follows:
all references to the objects position in the draw event go from x and y to xprevious+dx*tween, yprevious*dy*tween, where dx and dy are the difference between the current and previous locations (thus at tween=0 the object is at the previous location and at tween=1, the current)
a global clock turns off automatic drawing
in the step event of the global clock, we run a while loop and repeat it as many times as possible until it has run for the duration of one logic frame (1/30 seconds usually). Esentially all this while loop does is lag the game just enough to make it run at 30 fps. Pointless huh? Not really. Inside the while loop, we continuously calculate how far along we are from the next logic update and pass it on to a global tween value between 0 and 1, and keep re-drawing the room. This will allow for a lot more than 30 rendering updates per second while the step events and everything else remains locked at 30. It's a wonderful method and you'll find an example of it here (test 0)
The problem? Take a look at the graphics clock. 100 fps? 80? GM alone can do that scene at 2000 on my computer. It turns out that screen_redraw is an extremely slow command. Not acceptable.
At this point I decided to try a slighly different approach with tweening. Instead of a while loop delaying the logic updates to 30 fps, I thought why not run a clock at 30 fps and every time it ticks, tell all the objects to update their locations (thus limiting logic updates to that speed once again) while in their draw event they do pretty much what they did before. It worked, I was now running the demo at around 2000fps but couldn't help notice the occasional jitter in the movement of the objects. What's going on - I'm still not entirely sure. I believe it's because the logic clock isn't synched to the graphics clock in this scenario and you can have small differences. This effect becomes really obvious if you reduce room speed to 30 fps (press space) and see that the ball appears to move at perhaps 15. The reason is that the the logic clock and GMs event clock are triggering at different times and when they don't coincide, the reaction is delayed by up to a full frame.
A demo of this is in the same file you downloaded above. It's called test1.
I'm posting here to show two working methods to people (the first and the second of these. The second one should be perfect for smaller games that don't mind the speed drop). And in hopes that someone knows other ways to approach this or how to get around the jitteryness in the last example.
Although seriously, this is something that's in there by default with most game engines. Why has Mark overlooked it for so long when implementing it so crazily simple at engine level.
Edited by xot, 13 April 2008 - 06:23 AM.
** Old Experts Topic **