Insane Number Run (Made with GameMaker)

Insane Number Run

Available on iOS, Android, and Kongregate.

I recently finished up work on a new game, Insane Number Run, for Happy Bacon Studios.  It is a relatively simple game where you must, counting up, reveal all hidden numbers in order.  Its development started with the intent to make a small game with a quick production cycle but, like many projects, it took longer than expected to polish things and have it feel “just right”. For those curious, it was created using GameMaker: Studio, which generally makes development an enjoyable experience.

Feel free to check it out. Reviews are appreciated! :)

screen_3screen_1screen_2

TweenGMS Pro Goes Free!

TweenGMSAs of February 13, 2016, I will be making TweenGMS Pro permanently free. I have made the choice with careful consideration, deciding that I want as many people as possible to have access to it. (As of writing this, TweenGMS Pro is only $1 on the GameMaker marketplace. If you feel like chipping in a dollar, last minute, feel free to do so!)

Those who have purchased TweenGMS Pro, please contact me with your NAME/TWITTER/SITE/etc (as you want it seen by others) so that I can add you to an official supporter list included with future versions. *** A purchase order # from your marketplace purchase history would be helpful to validate ***

With more nifty features on the way, I will be continuing to update and support TweenGMS. It has been a fun experience working on it, and I don’t plan to stop!

TweenGMS Lite will also continue to be updated. It will remain as an alternative for those who want a stripped down version of the engine without all the extra advanced functionality.

On a personal side note, I am considering taking on freelance work for GameMaker project optimisation. If you are needing to push out higher frame rates with your GameMaker games, feel free to give me a shout and we can discuss details!

-Stephen

 

[GameMaker] YYC Optimisation – Direct Value Access

(This does not benefit standard VM exports or HTML5/JS exports but will make them perform slower)

Recently, I stumbled across a nifty optimisation for GameMaker’s YYC (C++) compiler. In my tweening engine, I had noticed that some “simpler” easing scripts were performing much slower than more complicated ones.

For example…

/// EaseLinear()
return argument2 * argument0 / argument3 + argument1;

…was performing much slower than…

/// EaseInOutQuad()
var _arg0 = argument0/(argument3 * 0.5);
if (_arg0 < 1){ return argument2 * 0.5 * _arg0 * _arg0 + argument1; }
return argument2 * -0.5 * (--_arg0 * (_arg0 - 2) - 1) + argument1;

This had me baffled. So, I tweaked various parameters, attempting to find what was driving the non-sensical performance difference. Eventually, I noticed the unique thing EaseInOutQuad had which EaseLinear didn’t:

operations involving a numerical constant

What I learned is that, under the hood, GameMaker seems to handle variables as a general data type which can be safely passed around to various expressions, functions, and scripts. I assume that these general types will then fetch and return their actual data type when needed, which may be a real number, string, array, or some other type. Apparently, this can lead to extra overhead when checking for a variable’s data type at runtime.

Now, what does this have to do with numerical constants helping speed things up? Well!

When you write an operation explicitly involving a numerical constant, it can be assumed that other variables interacting with the numerical constant are (should be) real numbers, or at least know how to deal with them. In the right places, this can enable GameMaker to optimise things by directly accessing a variable’s real value instead of accessing its general “packaged” data type first.

For example, in the most simplest form:

x = a;      // What is ‘a’?

x = 0+a; // Compiler can assume ‘a’ is a real number

In the example above, GameMaker will first access (a) as a general type before assigning its actual value to (x). With (0+a), however, the real value from (a) will be directly accessed since the numerical constant (0) makes it safe to assume the intention of the operation. This can lead to speed gains, even with the (possible) slight overhead from the “+0″ operation. Stripped down, the compiled C++ output would basically look like this (but much messier)…

x = a; // Access ‘a‘ and find which type to assign x

x = 0 + a.val; // Directly assign the real value of ‘a‘ to x

Despite appearing more complex, the second line is faster as its real value is being directly accessed by the C++ code. The operation involving a numerical constant allows this to occur.

Now! To get the most out of this technique, we need to utilize the Order of Precedence.

x = a + 0 + b * c; // We can do better!

In the above example, I have attempted to directly access the real values of all variables in the expression by adding (+ 0). However! Because (b * c) has a higher predence and will be executed first, b and c will fail to get the intended optimsation of having their values directly accessed. Instead, we need to wrap brackets around the first executed variable and add a constant zero to it.

x = a + (0+b) * c; // That’s better!

Now, (0 + b) will be executed first, with (b) directly accessing its value. Because (b) is now assumed to be a real value, (c) can also assume it is real. And because ( (0+b) * c ) is assumed to be real, (a) can ALSO assume it is real when it is accessed last. As a result, all values will be directly accessed by the C++ code:

x = a.val + (0 + b.val) * c.val; // YAY!

Note that this trick also works when multiplying or dividing by constant values:

x = a + 0.5 * b * c; // Divide and conquer!

Note that using this technique directly with script/function parameters can sometimes do more harm than good. Script and function parameters may require general data types to be passed as arguments. Remember that the general type is safer to pass around?

x = AddValues(a+0, b+0, c+0); // Probably BAD

x = ShowNumber (a + (0+b) / c); // Probably GOOD

In the first example above, because of how the YYC works, the numerical constant (+0) would force all 3 parameter values to first be pre-calculated and assigned to 3 temporary “general” variables. This creates extra overhead and can slow things down. However, with the second example, the optimsation benefits for the single argument would likely speed things up, as the single parameter involves a more complex calculation, allowing direct access to ‘a’, ‘b’, and ‘c’ in a single expression. The cost of the “extra overhead” would likely be outweighed.

In regards to the easing algorithms I had mentioned at the start, placing ( 0 + argument0) at the start of EaseLinear was all that was needed to greatly boost its speed!

return (0+argument2) * argument0 / argument3 + argument1; // Huzzah!

Anyhow! There’s no sure way to know how this could help speed up your own code until you try. Check to see where it helps and where it doesn’t. Experiment and benchmark the results!

Also, be sure to check out the outputed C++  code for your project in the Asset Cache Directory. You can find the directory by going to File -> Preferences.