Make your sprites flash

Do you want to know how to make your sprites flash a solid color, like in SNK games or the like? Have you spent a ton of time combing through tutorials on ways to accomplish this, only to find that most of them didn't describe shaders in GMX properly or they tried to have you use D3D fog or they instruct you to use surfaces to copy images and you have no idea how that actually works well? Well you're in luck!

This tutorial was borne from our  efforts in trying to accomplish this effect but not finding any truly comprehensive tutorial or explanation as to how to do it. It took some work, but we figured out possibly the easiest way to flash those sprites.

The first thing to note is this: to use a shader with a sprite, you're going to want to do a Fragment shader instead of a Vertex shader. When creating a new shader, click on the Fragment tab and ignore the Vertex tab. 

What this fragment shader does, mechanically, is do something to each pixel that it is called upon to address. So if you have a 10x10 sprite and call it, it will run 100 times in the shader engine. You can do the math on how this can be expensive if you start using them on giant and/or numerous sprites, but that's why the GPU handles calculations for shaders separately from the CPU. You also have multiple types of shader engines to use, but in this case I am using the default GLSL ES engine.

 Note that in the shader scripting window, you are then writing in OpenGL code, rather than in the GML script. It's a lot more strict than GML. For example, you can't use integers when defining the RGB and alpha values; only floats that must utilize decimals. The RGB values are also from 0.0-1.0, as opposed to 0-255 like in GML.

 Here is the shader we are using:

//

// Simple passthrough fragment shader

//

varying vec2 v_vTexcoord;

varying vec4 v_vColour;

void main()

{

    //pull original color from the image

    vec4 OriginalColor = texture2D(gm_BaseTexture, v_vTexcoord);

    //pull the individual color and alpha levels from the current pixel from the image

    float Red = OriginalColor.r;

    float Green = OriginalColor.g;

    float Blue = OriginalColor.b;

    float Alpha = OriginalColor.a;

    //if the pixel in the image is clear, don't draw it. If so, make it white

    if (Alpha == 0.0)

    {       

        gl_FragColor = vec4(Red, Green, Blue, 0.0);

    }

    else

    {       

        gl_FragColor = vec4(1.0, 1.0, 1.0, Alpha);

    }

}

Simple, right? And to trigger it, we created a variable called useShader in the object and set it to false in the Create event.

In the Step event, we continued to set useShader to false to reset it every frame. We probably don't need to initialize it in the Create event, but we like to keep my variables in one place.

 In a Collision event (with my hero's tough bullets), we set useShader to true.

In the Draw event, we then use this code:

if (useShader = true)

{      

        shader_set(sh_whiteout);

        if (facingDirection = 1)

        {

            draw_sprite_ext(sprite_index, sprite_index, x, y, -1, 1, 0, c_white, 1);

        }

        else

        {

            draw_sprite_ext(sprite_index, sprite_index, x, y, 1, 1, 0, c_white, 1);

        }

           shader_reset();

}

else

{   

    draw_self();   

}

The important part to note is that the possibility for useShader to be true has to be AFTER the assignment in the Step event where it sets it to false. This will give you a really tight 1 frame flash of white. Of course you can tweak this as you see fit (setting variables to make the character flash twice, or maybe on an increasing interval as they lose health).

And that's it! we have been looking for this kind of simple step-by-step guide for years, and couldn't find it. Maybe it's us being an idiot! That's probably the real answer!

 Anyway, enjoy your flashy games!