Title: Drawing Transparent Pictures
Question: Drawing transparent images/sprites for games/interfaces...
Answer:
You need to have to pictures:
1: the sprite you want to draw
2: the mask of the sprite
The sprite needs to have the transparent areas filled with black. The mask of the sprite is a monochrome bitmap painted with black in the areas you need to draw, and white in the transparent areas.
$$####$$$ WWBBBBWWW
$$$####$$ WWWBBBBWW
$$$$####$ WWWWBBBBW
$$$####$$ WWWBBBBWW
$$####$$$ WWBBBBWWW
SPRITE MASK
$ - black
# - another color
W - white
B - black
HINT: If you design your own sprites, in programs such as 3D Studio MAX, Photoshop, or any other program that uses antialising, you have to assure that the background color is black. If you have a yellow antialised circle and a red background, when you create your mask you'll use a Magic Wand Tool or something like that to get the background. Some parts of the background whill be shaded with the sprite (antialising) and that parts will not be selected. Finally, drawing the circle transparent you'll obtain a yellow circle with a red border. Now, think that the sprite is a truck, or car and you draw that on a road. You get a nasty red border. If you use a black background, it wouldn't be so obvious. I don't know if you understood anything, but don't use colored backgrounds with programs that mixes colors (resizing images is done with color mix by "cool" programs)
If you work with many sprites, you may need to build a tool for creating the mask. It is a simple routine that checkes a image for a certain color. Check out the next procedure. This procedure could be optimized(using scanline) and then used realtime, when loading images (if you don't bother waiting).
procedure TForm1.CreateMask;
var i,j:integer;
TransparentColor:TColor;
begin
TransparentColor:=Rgb(0,0,255);
// loop through the entire sprite
for i:=0 to Sprite.Width do
for j:=0 to Sprite.Height do
// if the pixel is the transparent color
If Sprite.Canvas.Pixels[i,j]=TransparentColor
then begin
// make black that pixel in the sprite
Sprite.Canvas.Pixels[i,j]:=0;
// and white in the mask (white=transparent)
Mask.Canvas.Pixels[i,j]:=Rgb(255,255,255);
end
// if the pixel aint transparent
// put black in the mask (black=solid)
else Mask.Canvas.Pixels[i,j]:=Rgb(0,0,0);
end;
The transparent drawing is done with the BitBlt function:
BitBlt(
DestDC: HDC, // handle of the destination canvas (Canvas.Handle)
X: Integer, // x-coord. of destination rectangle's upper-left corner
Y: Integer, // x-coord. of destination rectangle's upper-left corner
Width: Integer, // width of destination rectangle
Height: Integer, // height of destination rectangle
SrcDC: HDC, // handle of the source canvas
XSrc: Integer, // x-coordinate of source rectangle's upper-left corner
YSrc: Integer, // y-coordinate of source rectangle's upper-left corner
Rop:Cardinal ); // raster operation code (AND, NOT, INVERT, COPY...)
Enough with the talking... Let's go into THE THING:
BitBlt(Form1.Canvas.Handle ,X ,Y ,Sprite.Width ,Sprite.Height,
Mask.Canvas.Handle ,0 ,0 ,SrcAnd);
BitBlt(Form1.Canvas.Handle, X ,Y ,Sprite.Width ,Sprite.Height,
Sprite.Canvas.Handle ,0 ,0 ,SrcInvert);
Yeah... with those two lines and a mask you can draw transparent image. That is FAAASSSTTTTT:::::
If you want a demo to that, write me at: cristim@elsaco.com , and i'll give it to you. Later i'll post a note at the address where you can get it.
You can use this technique to draw game sprites, interfaces, etc. I used this technique to make a RTS game :drawing units, animating them, drawing cursor, game interface, menus,... but the possibilities are unlimited.
I'll post another article about animations and states with BitBlt (you'll love this word)
If you have any questions, thoughts or demos you'll like to share please mail me: cristim@elsaco.com