The every event (and speed)
Submitted:|| 8th October, 2004
The problems of 'Every' events
Every events are an integral part of any Click game. There's no doubt it's an incredibly useful event. Every events trigger every certain amount of time - of course - but therein lies the problem.
The problems of Every
So what could possibly be wrong with such a basic, simple and important event? Let's take the event "Every 1 second". Every time 1 second has gone by, the event will run. The main problem is, what if your game was not running at the normal 50 frames per second? If your game had dipped to 25FPS, then it would actually take two human seconds for the game to complete a normal "second" of 50 frames. But the event would still be triggering once every human second, no matter what.
If you had a gun which fired a bullet once a second using an Every event, you could have a bug, or at least an imbalance, to deal with. Say the bullet travels 1 pixel a second, and on one computer the game runs at 50FPS, whilst a slower one runs at 25FPS. On the faster machine, the bullets would be 50 pixels apart. On the slower one, they would be only 25 seconds apart. If you recorded a video of the slower computer and sped it back up to 50FPS, the gun would be firing twice as fast! This could have made the game much more difficult, or even impossible.
Further problems can arise if the bullet causes some slowdown itself. If it was a reasonably large object with an ink effect, say, then creating a new bullet would slow the computer down further. So the next bullet would come fewer and fewer frames apart until 1FPS when it would come every single frame! Imagine this at 50FPS, it would be a machine gun - a significant change in your game. Plus the player would get frustrated and quit at 1FPS.
The 'Machine independant speed' option is worth mentioning here. To clarify, 'Machine independant speed' will skip drawing the screen if it can't do it 50 times a second, in order to make sure it can read the events 50 times a second. If your events run 50 times a second, you therefore avoid any Every event problems. The disadvantage though is that on slower computers if the game slows down a lot, the framerate can become VERY choppy. Additionally there seem to be some graphic glitches when using this option, and you still can't guarantee 50FPS. I tend to prefer not to use this option.
How to solve
There's an easy workaround to the Every problem. Just trigger the event every certain number of MMF loops, instead. So if the game slows down, it's still the same number of frames between triggers.
You can either use the TimeX object to trigger once every N MMF loops, or the simple counter approach. All you do is always add 1 to a counter. Now your replacement for an every event is, using Compare 2 general values:
Counter mod 50 = 0
Mod is the remainder of division, e.g. 10 mod 3 = 1 (10 divided by 3 is 3 remainder 1). So the counter holds number of frames so far, and mod 50 makes this a value between 0 and 49. When the counter equals 0, you have reached a new multiple of 50, which means 50 frames have gone by, and the event runs. Remember MMF tries to run your app at 50 frames per second, so Counter mod 50 = 0 would be the equivalent to "Every 1 second". The crucial thing is that it slows down WITH your application.
General tips on speeding up your game
Turn on DirectX and VRAM. This effectively enables limited hardware support - graphics, where possible, are stored in your video card's memory so the video card can do fast blitting (copying) of images. However, although graphics cards can do amazing 3D really fast, and copy 2D images quickly too, suprisingly they simply can't set individual pixels very fast. Specifically why this is still perplexes me, but the point is ink effects are achieved in MMF by setting each pixel, using a formula. So DirectX and VRAM with ink effects can actually even be slower than if DirectX and VRAM were both off. Basically, try to have DX and VRAM on unless you have ink effects, but always experiment to see which combination is fastest (high-resolution scrolling without VRAM can be very slow), since you can often get away with small ink effects.
So if you design your game trying to avoid ink effects, you can get it running very fast. There are lots of ways for optimising events too, but event-based slowdown usually is marginal compared to screen rendering based slowdown: drawing the screen is the longest, slowest operation MMF has to do. In a recent project, I found that a game running at 20FPS had been slowed down 25FPS due to screen rendering and 5FPS due to the events. Optimising your events is definitely a good idea though and good practice, and will help keep things top-speed too.
The final major factor I can think of is number of active objects: MMF seems to have trouble handling large numbers of actives, even small ones. Be careful of particle effects and so on, the existance of many actives can slow MMF down quite a bit.
I think a lot of stuff these days is optimised for 16-million (24-bit) graphic modes, so I don't think setting the colours down will make TOO much of a difference, except make your game look uglier. If you still can't figure out why your game runs slow it's worth a try.
I think that covers everything... my first article in quite a while.