02 March 2011

Code of the Ninja - Partially Erasing Surfaces in GM

If you haven't already, read the Code of the Ninja: Introduction

Hey there, Code Ninjas!

One of the cool things about Game Maker 8 is the ability to export PNGs with an alpha channel for transparency. There's no separate functions for doing so, though; if you want to be sure the exported image is in PNG format, you have to make sure the extension is explicitly ".png", like so:

Code:

sprite_save("sprite.png");
screen_save_part("screenie.png",320,224);

It's especially cool to create partially transparent surfaces and export them. After creating a surface, you can use the draw_clear_alpha() function to make it completely transparent:

Code:

surface_set_target(surface);

draw_clear_alpha(c_black,0); // clear the entire surface with fully transparent colour

surface_reset_target();

One thing that's annoying, though, is the way that drawing with a partial alpha to a surface works. Instead of blending with the colour underneath, the colour is completely replaced, alpha and all. Effectively this punches "holes" in the surface image.

You'd think this could exploited to create some kind of eraser tool. Draw pixels with an alpha of 0 to the surface to erase pixels that are already there, leaving fully transparent pixels behind.

This doesn't work, though, for some reason. Very low alpha values such as 0 or 0.01 function exactly as you'd normally expect when drawing to the screen, even though higher values such as 0.7 differ when using surfaces.

So much for the ability to erase pixels from a surface using that method... But there is another way.

Set the blend mode to bm_subtract before drawing to the surface and you'll effectively be able to erase from the image:

Code:

surface_set_target(surface);

draw_set_blend_mode(bm_subtract);
draw_set_color(c_white); // color doesn't actually matter
draw_set_alpha(1); // alpha must be 1 to fully erase pixels

// erase an "X" across the surface
draw_line(0,0,surface_get_width(surface),surface_get_height(surface));
draw_line(surface_get_width(surface),0,0,surface_get_height(surface));

draw_set_blend_mode(bm_normal);

surface_reset_target();

This trick may come in handy on occasion, especially when making games where the user is allowed to paint custom textures for things - an erase tool is essential.

Until we meet again, happy coding!

If you use my code or scripts in your game or engine, no credit is necessary. But I'd love to hear about your project if you do! Just drop me a comment below, or e-mail me at us.mercurysilver@gmail.com

No comments:

Post a Comment