code of the Ninja();

// in search of swift, efficient, and invisible code

2012-12-31

Creating Old-School Palette Effects Using Pixel (Fragment) Shaders

Please note that the following only applies to Game Maker 8.0 using this shader extension. However, the principle can be applied to anything else that uses shaders.

Okay, time to get started. Let's say you have an image. It's made of pixels - obviously - and each pixel is a colour. Where things get interesting is how you choose to describe that colour, i.e what bits or bytes you use to signify it.

The simplest way is to use 1 bit per pixel - on or off. But that only gives you a monochrome image. What about colour? A very common way is to use 24 bits per pixel - one byte each for the red, green, and blue channels. This gives you 256 levels of intensity for each channel, allowing over 16 million vibrant colours, and indeed 24-bit colour is sometimes referred to as "true" colour.

The drawback to methods such as 24-bit true colour is that they use a large amount of memory. So, a common practice in old-school games was to use indexed colour: a palette contains the actual colours, while the pixels in an image are only described by a single value - the index (i.e. the address in the palette) of the colour to be used for that pixel. (Read more at Wikipedia.)

The indexing method, in addition to saving memory, has another big advantage. If you change a colour in the palette, any and all pixels that reference the index of that colour will change along with it. An otherwise static image can come to life in this way - lights can flash, water can flow, stars can twinkle - all without true animation of any kind. (See a beautiful example of this in action.)

As memory and CPU power improved, these little tricks largely fell by the wayside. Software such as Game Maker doesn't provide any functionality for palettes by default, which is bad news for anyone who wants to emulate the effects of old-school games.

Fortunately, LSnK has come to the rescue with his shader extension for Game Maker. (Sadly it is only compatible with version 8.0 of GM, but 8.0 is still a sufficient tool for making great games.) It allows one to use shaders in Game Maker with little more effort than setting the fog colour.

Shaders are quite a complicated subject, but for the purposes of palette effects (and this article) we will only be considering pixel shaders (also referred to as fragment shaders). You can think of a pixel shader as a tiny program that runs for each pixel that is drawn. If you activate a pixel shader and then use a drawing function, each pixel to be drawn is input to the shader, the shader runs, manipulating the pixel in some way, and finally the pixel is output to the screen.

There are a great many effects pixel shaders can achieve. A common example is drawing an image in greyscale: the red, green, and blue channels are used to determine the perceived brightness of the colour, and then that brightness value is output to all three channels, making the corresponding shade of grey.

Now, I'm not going to explain every little thing about how to use the shader extension or make a shader - there's plenty of instruction on how to do these things on its own page. Here I'm only concerned with explaining the idea behind emulating palette effects with a pixel shader. I'll also provide an example GMK at the bottom of the article to get you started.

So let's move on. First, we need a palette (any image that's one pixel in height with colours in horizontal sequence will do). Let's use Sonic's palette from Sonic 1 as an example.

We'll also need an image of Sonic.

The above image clearly won't do. It's already in colour; what we need is an image of Sonic where each pixel is an index in a palette. I've made a tool called Palettiser that lets you do exactly that. It'll analyse an image and replace all the pixels with shades of red - shades of red whose intensity corresponds to an index in a palette, for a max of 256 colours. Having completed that process one ends up with an image of Sonic that looks like this (since there are only about 16 colours in the palette, the shades of red are all very dark, almost black):

Now, both the palette image and the funky-looking converted image can be imported into Game Maker as a sprite or background resources.

The next step is to create a custom pixel shader. A shader that, when active, will perform the following operation on every pixel that is drawn:

  1. Get the amount of red in the pixel.
  2. Use that value as a horizontal coordinate, finding the colour at that position in the palette image.
  3. Draw a pixel of that colour instead.

By drawing the converted image with the shader active, the original Sonic image can then be recreated correctly. But this time it will palettised - any change to the palette image colours will be reflected in the Sonic image immediately.

But how to change the palette image colours? It's a background or sprite, right? Well, what's cool is that a shader can also use surfaces. If you make your palette a surface, you can draw anything to it, and in so doing animate the palette.

But talk is cheap. It's much cooler to see this happen and play around with it in real time. To that end, here is an example GMK. (Be sure and install the shader extension first, of course!)

Have fun!

2012-11-26

The Phantom Returns

This is a bit of weird - and undocumented - behaviour.

When you write scripts in Game Maker, you can have them return a value by using the return statement, like so:

What value does the script return if you don't have any return statement, though? Does it always return true, or false, or maybe something else? I wanted to know, and I learned something surprising when I looked into it.

At first I thought the answer was that the script would always return false, but this rule didn't always hold. What's more, the return values I was getting were seemingly random and unpredictable.

Finally I discovered what was going on. A script returns the value of the most recent equation.

What does that mean exactly? Well, for example, a script containing only this line:

...will return 10. And, likewise:

...will return 20. Whatever the result of the most recent equation is becomes the return value!

This holds true for math operators like *=, +=, and so on. This:

...will return the square of argument0.

How bizarre! Even if you leave out the return statement, you will still get "phantom" return values... I guess this might be the cause of odd behaviour once in a while, so it's good to know about.

Until next time, happy coding!

2012-11-24

Prepare To Be Floored (Correction)

This is a correction of a mistake in my last post.

The last section said this:

This is all very well and good for rounding, but what about flooring or ceiling a number? This trick always rounds up with a fractional part of 0.5 or above, and rounds down below that. In Game Maker, you can use the floor() function to always round down, and the ceil() function to always round up.

You're in luck, because you can do code like this:

These will still be very nearly twice as fast as their function equivalents!

The trouble is that only works if your number actually has a fractional part. If you try to floor or ceil an integer that way, you'll get the integer -1 and the integer +1, respectively.

I can still pull my fat out of the fire, though. Instead of using 0.5 as the value to be subtracted (for flooring) or added (for ceiling), you can use a constant that's just ever so slightly less than 0.5, such as:

Just set this up as a constant (call it something like MATH_CEIL) and then make a second constant that's the negative of it (e.g. MATH_FLOOR = -MATH_CEIL). Then you can do:

And everything I said still holds. You'll still get the job done twice as fast as using the function equivalents. (The use of constants doesn't slow it down at all.)

I suppose you might still technically run into a problem if you're using numbers that require a precision greater than power(2,-43), but for most purposes that'll never happen. Again, this is merely a trick to be used in code that requires optimisation at all costs, not everywhere in your program.

2012-11-05

Prepare To Be Floored

This post is nothing too special or groundbreaking, but it might be of interest to anyone who is as huge of a nerd as I am.

I noticed long ago that Game Maker automatically rounds numbers and variables when they are used as array indices. So, for example array[3.6] is precisely equivalent to array[4].

I also noticed that the same thing happens when performing binary operations:

is precisely equivalent to . The same principle holds for ^ and |.

is precisely equivalent to . The same principle holds for .

Knowing this is certainly useful; it can rid your code of unnecessary calls to the round() function.

But I got an evil thought - what would happen if I tried bit shifting a number by zero, e.g. or ? Mathematically, a bit shift of zero should leave the number unaffected, but would Game Maker go ahead and round it anyway?

The answer is yes! is equal to 32. Therefore this code:

Has the identical effect as this code:

An interesting quirk; a titbit of trivia. So what?

Well, I suspected that it might be a faster operation than the calling of the round() function, and so I tested this hypothesis. The result?

Bit shifting by zero is twice as fast as using round(). Now, that function is hardly going to break the bank, but if you have code that relies on it heavily this is definitely something to consider with regard to optimisation.

For the same effect you could also with ~1, as in this code:

It also rounds the number much faster than round(), comparable to the speed of the bit shifting method. I just don't like the readability as much; the bit shift method > 0--> looks like it's knocking off digits past zero, which is a reasonable mnemonic for rounding.

This is all very well and good for rounding, but what about flooring or ceiling a number? This trick always rounds up with a fractional part of 0.5 or above, and rounds down below that. In Game Maker, you can use the floor() function to always round down, and the ceil() function to always round up.

You're in luck, because you can do code like this:

These will still be very nearly twice as fast as their function equivalents!

(EDIT: The above about flooring and ceiling isn't perfect; be sure to read my correction!)

Okay, so maybe in practice this will make your code more confusing and less readable, but like I said: "huge nerd". =P

2012-03-17

Rogue Operators in GML

I've recently discovered a clutch of "rogue" operators in GML: operators that are fully functional but totally undocumented in the help file. While I wouldn't recommend using any of them (they might make your code less portable), they might be interesting to be aware of.

:=

When first n00bishly using GML, I did what I'm sure a lot of others did: I used the = operator for comparisons, e.g. if (a = b), as well as assignment, e.g. a = b. Turns out this is really bad practice if you ever plan on learning other languages (like, say, javascript), because they treat the two very differently. Assignments in javascript actually return the right-hand value, not true/false; so if you were to say if (a = 0) the conditions would never be true, just as if you'd said if (0). The solution, of course, is to use the comparison operator == for condition testing, e.g. if (a == b), and use = only for assignments.

So where does := come into all this? If GML matched other languages, it should be purely an assignment operator, e.g. a := b and not if (a := b). But since GML is special, it's merely a synonym for =. Yep, you can say if (background_color := c_blue) and it'll do the exact same thing as if (background_color = c_blue) or if (background_color == c_blue) in GML.

Dumb. Like I said, these aren't recommended.

<>

This is just a straight synonym for !=. It returns true if the left-hand and right-hand expressions are not equal.

!<, !>

You would think these were cute alternatives for the and operators: whereas you might say to test if a is less than or equal to b, you could also say to test if a is not greater than b for the identical result. However, you would think wrong, even though there are some places around the net that suggest it's true. In GM 8.0, at least, these do not work; they throw a syntax error if used in code. (Though, oddly, they'll just be ignored if used as part of watchers in debug mode: will just return a no matter the right-hand variable is.)

|=, &=, ^=

Okay, so these are documented in the help, but not in the operators section, and there's also a confusing typo where they're listed (suggesting that one of them is ). But they are very useful if you know them; they're the bitwise brethren to the +=, -=, *=, and /= operators. For example, a |= b is equivalent to a = a|b.

2012-01-08

Simple Animation System

Hello again, Code Ninjas!

I'm afraid I have been a little too silent and invisible lately. Upheavals in personal life and multiple projects with disappointingly slow progress have kept me from posting since August, which I'm sure one needn't be told is less than ideal.

But now that the silence has been broken, I'd like to show off the animation system I'm using in my Game Maker Sonic engine, AeStHete.

The Problem

You see, Game Maker has the rudiments of an animation system - all you have to do is set the animation speed for an object, and its sprite will step through all its subimages, looping when it reaches the end and even triggering an event when it does so. But there are huge drawbacks to this system, and it's not even powerful enough to be comparable to the animation system used by the original Sonic the Hedgehog, a 16-bit game that's over 20 years old.

The largest drawback by far is the fact that animations can't be frame lists; if you want to show the same subimage more than once during the animation, you're forced to store two copies of it in the sprite, potentially wasting large amounts of memory, increasing load times, and making your sprites harder to work with.

You also have no ability to vary the animation speed on a frame by frame basis, so if you desire a certain frame to be shown for longer than another, you're out of luck, unless - again - you duplicate it in your original sprite.

Alright, so there are workarounds to these problems, using timelines, or scripting, but they are bothersome and time-consuming to put together. It would be really nice if you could just tell your object to play an animation with a simple command that takes as few arguments as possible while still allowing the features that we'd really like.

Fortunately I've devised a way to do this using scripts, but before I go into it I want to complain about another problem with Game Maker's built-in animation that, while terribly obscure, bothers me no end: If you happen to be using the draw_sprite() function (or one its relatives like draw_sprite_ext()) instead of relying on the default draw event, and use image_index as the subimage argument, it is rounded improperly. So if your image_speed is 0.5 and you are expecting each subimage to be shown for 2 steps, you can get an unpleasant surprise: sometimes they'll be shown for 1 step, or 3... yes, on average the speed is correct but it is not stable, and it looks wrong to the eye, especially for flashing animations that require a steady framerate.

The Solution

So let's avoid all these annoyances by writing scripts that handle animation a lot more like a proper video game would.

The first order of business is to set the image_speed of your object to 0, so that Game Maker will not change the image_index on its own. You want to change it manually, by calling a script which we'll name AnimUpdate().

AnimUpdate()

Let's build up the script step by step, explaining the lines as we go.

Instead of image_speed we'll be using our own variable called animSpeed. Unlike image_speed it will not be a factor (i.e. 1 changes the frame each step, 0.5 changes every other step, etc) but the literal number of steps each frame should be shown until it changes. So if you want an animation that changes frame each second, animSpeed should be equal to your room_speed.

Anyway, if animSpeed is zero or below, we'll exit the AnimUpdate() script altogether; This means you can stop an animation in its tracks by setting animSpeed to 0, or even pause and unpause an animation by multiplying animSpeed by -1 (a neat trick).

This code simply decrements the timer; when the timer reaches zero, the frame will change:

Why use "less than or equal to" instead of just "equal to"? That way, if animTimer is already zero when the script is run, the frame will still change correctly rather than breaking the animation. In fact, this means when we start animations we can initialise animTimer at 0, which makes a little more sense than setting it to 1, and can also be used by other code to check if the animation has just been started but has not updated yet. It's just a little nicety.

The frame number is increased. Why use animFrame and not directly increment image_index? It will become clear in time.

Another nicety that isn't strictly necessary, this allows you to run a custom script each time a frame changes; while this will rarely be used, it is incredibly useful in complicated animations. For instance, Sonic might run a script in his walking animation that calculates the animation speed based on his actual walking speed, and sets animSpeed accordingly. The current frame is given as argument0.

This line checks if the animation has "finished", i.e. whether the frame number is equal to (or greater than) the length of the animation. Why check if it's greater than, also? Because if the animScript changes the current animation for some reason, and the new animation is shorter than the old, the animation won't break. This is a one character change, but it prevents the need to check for such eventualities in your animScript.

This line simply returns the frame number to 0, causing the animation to loop. While this is what we want in most cases, wouldn't it be nice if we had a few more options? So let's replace that line with a switch statement that checks a variable called animEnd and does different stuff.

It will loop only if animEnd is 0, which is what we want most often; -1 will stop the animation; -8192 will cause the instance to destroy itself, which is convenient for simple objects like explosions or other effects which should disappear when their animation has finished; and any other value will simply be added to the frame number so you can, for instance, use -2 to loop the final two frames (as Sonic does when tapping his foot in his boredom animation).

(Ideally we would define constants for these values in GM's constants form, e.g. ANIM_LOOP = 0, ANIM_DESTROY = -8192, etc.)

Onward!

Here we simply reset the timer so that it can count down until the next frame change.

Here, we check a variable called animData to see if it's an empty string. If it is, the image_index should be the current frame number, plus an offset value. The offset value allows us to, for example, have a single sprite which contains every image of the player character. By setting the offset to the index of the subimage where the animation you want to play starts, you can have more than one animation per sprite, seriously cutting down the number of sprites needed. This is part of the reason why we didn't increment the image_index directly earlier, but used a custom variable called animFrame. The second part of the reason is in the next line:

This line is only done if animData is not an empty string but contains some data. This data should always be in the format of a string of digits, e.g. "0102030405198042". This is used as a frame list; the real(string_char_at()) is used to get a frame number from the frame list instead of using animFrame itself, which always counts up in sequence. By using a frame list, you can jump around in the sprite at will, or repeat frames as many times as you want.

Now, you'll notice that you are not allowed with this system to have a frame list that contains values greater than 9, so you can only use 10 different subimages for any animation with a frame list supplied. But this is not usually an issue in classic-style games (it never becomes an issue in Sonic, for one), and if needed you can always add an animScript which changes the offset when needed for especially complex animations.

The frame list is also our way to create variable animation speed. It's not perfect, but by repeating subimages you can achieve almost all effects ever needed, and certainly any needed by a Sonic game.

The last line merely closes the if (animTimer<=0) { block we started, and that does it for the AnimUpdate() script.

AnimPlay()

Now we need to write a script called AnimPlay() that will start animations running. It needs to be supplied with several arguments, most of which are optional. This is how all those variables we were using in AnimUpdate, such as animEnd, animScript, and animData get their values.

There are 5 arguments. The first is animData, which should either be a string like "3120" if you want to use a frame list, or a real number like 4 if you just want to specify the length of a sequential animation.

If argument0 is a string, we know you want to use a frame list, so animData is set to equal argument0 (well, only the digits of the string, anyway, to protect from errors in the real() function later on) and animLength is derived from the length of the string.

If argument0 is a real, however, animData is set to be an empty string and the animLength is set to argument0 directly.

The animSpeed (remember, the number of steps each subimage should be shown before changing) is set to argument1, the only other required argument.

Here, the animOffset is set. It will default to 0 if no argument2 is given, so your animation will start from the first subimage of the sprite being used.

The animEnd is set to argument3. Remember this value specifies the behaviour of the animation when it reaches its end. 0, the default, is loop.

The animScript is set to argument4. If no argument4 is given, it will be 0 so no script will bother to run. (Technically, 0 is a valid script index, but chances are - since the first script you ever create in your game project has the 0 index - it won't be a useful animation script. If you wish to modify this, it's a simple enough matter to tweak this and also AnimUpdate() but you're on your own with it, since I prefer the elegance of doing it this way.)

The animTimer is set to 0 so that when AnimUpdate() is called next (preferably in something like the End Step Event) the animation will initialise at the first frame. The animFrame is set to -1; it will be incremented to 0 when the animation starts.

Conclusion

So that's all that it takes to make a reasonably robust animation system with far more power than Game Maker's simple image_speed implementation. You may download the GML scripts from this tutorial here.

As a fun exercise, you can modify this system easily to use a delta value when decrementing the animTimer:

If the delta is a global value, you can slow all animations by any factor simultaneously, allowing you to create all kinds of cool slow-motion effects. Some problems will arise if the delta is greater than 1, but it wouldn't be an exercise if you didn't have to figure out how to solve something on your own. (Don't worry, it's not too difficult.)

I'd explain it all right now, anyway, but I've got to get back to coding my AeStHete engine. Until next time, happy coding!