I'm struggling with transparency. I'm trying to draw a bitmap (that I do not load from a file), called fog, onto the screen, but it's not working! What I have is something like this:
//Create the fog BITMAP *fog; fog=create_bitmap(640,480); clear_bitmap(fog); //Now randomly place a few circles for the fog for(int i=0;i<10;i++) circlefill(fog,rand()%640,rand()%480,rand()%50,makecol(255,255,255)); //Now draw the scene to the screen with out fog //... //Draw fog set_trans_blender(0,0,0,255); draw_trans_sprite(screen,fog,0,0);
What I would like to happen is for the areas that are covered by the white circles to show completely, with a circle of color makecol(128,128,128) greying the pixels underneath, and the black areas of the fog to completely blot out whatever is under them, so you only see black. So far, I only get the fog covering everything on the screen. Any suggestions on how to do this?
Draw the circles with makecol(255,0,255) so they dont occlude whats beneath them. Then I guess you would have to set the alpha value of the grey circles to less than 255 so that they are translucent.
It seems to work well; thank you for a solution. However, I'm still confused: what is special about the color makecol(255,0,255) that fixed it so that the circles worked? Also, if I wanted to have a translucent part of the fog, say, have the center of the circle be completely transparent and the other rims increasingly dimmer, how could I do that? And how do I set the alpha value of a pixel in a bitmap (right now I'm using 16 bit color)?
It is called "magic pink." It is defined in allegro as invisible.
Oh, sorry. I should have thought of that.
Does anyone know how to do the fog effect, but with not 100% transparent fog, but with the center all the way clear and the edges less clear?
Alpha blending.
I'm not sure how to use alpha blending with Allegro. I think what I need is a 32-bit bitmap called fog, so I could do something like:
BITMAP *fog=create_bitmap_ex(32,640,480);
After that, I need some way of setting the alpha part of each pixel in the image, which I was unable to find in the Allegro manual (so please don't tell me to rtfm!). Then, I need to just blit the fog onto the image like normal, right? Or am I missing something here?
blit() does not take into account any alpha channel!
You basically need look into the manual and try to write your own. I made my own translucent sprite drawing function, here:
1 | int color_shift(int col1, int col2, int percent) |
2 | { |
3 | int ipercent = 100 - percent; |
4 | int n_col, rn, gn, bn; |
5 | int r1, g1, b1, r2, g2, b2; |
6 | //get colors |
7 | r1 = getr(col1); |
8 | r2 = getr(col2); |
9 | g1 = getg(col1); |
10 | g2 = getg(col2); |
11 | b1 = getb(col1); |
12 | b2 = getb(col2); |
13 | //shift |
14 | rn = ((r1*percent)/100)+((r2*ipercent)/100); |
15 | gn = ((g1*percent)/100)+((g2*ipercent)/100); |
16 | bn = ((b1*percent)/100)+((b2*ipercent)/100); |
17 | //create |
18 | n_col = makecol(rn, gn, bn); |
19 | //return |
20 | return n_col; |
21 | } |
1 | void trans_draw(BITMAP *dest, BITMAP *source, int x, int y, int percent) |
2 | { |
3 | int w = source -> w; |
4 | int h = source -> h; |
5 | int w2 = dest -> w; |
6 | int h2 = dest -> h; |
7 | for (int sx = 0; sx < w; sx++) |
8 | { |
9 | if ((x + sx >= w2)||(x + w < 0)) |
10 | return; |
11 | while (x + sx < 0) |
12 | sx++; |
13 | for(int sy = 0; sy < h; sy++) |
14 | { |
15 | if ((y + sy >= h2)||(y + h < 0)) |
16 | break; |
17 | while (y + sy < 0) |
18 | sy++; |
19 | int col1 = _getpixel32(source, sx, sy); |
20 | if (col1 != MASK_COLOR_32) |
21 | { |
22 | int col2 = _getpixel32(dest, sx+x, sy+y); |
23 | int col3 = merge(col1, col2, percent); |
24 | _putpixel32(dest, x+sx, y+sy, col3); |
25 | } |
26 | } |
27 | } |
28 | return; |
29 | } |
You can use it as you want. Basically, just use it like draw_sprite(), only give it the last parameter to tell it how much to blend the image into the background.
[EDIT]
Almost forgot! This function only works with 32-bit color depth.
Thanks! The code you posted is great, but as you said, it requires 32-bit color depth. I wrote my own just now, which accepts an 8-bit bitmap which contains the alpha part and anouther bitmap, as well as the position (x,y) of where to place the alpha part on the other (truecolor) bitmap; so far, it works. Here is my alpha-blending function:
1 | void drawAlpha(BITMAP *alpha,BITMAP *destination,int x,int y) |
2 | { |
3 | int r,g,b; |
4 | float alphaPart; |
5 | int rx,ry; |
6 | int color; |
7 | //Out of bounds? |
8 | if(x>=destination->w || y>=destination->h || x+alpha->w<0 || y+alpha->h<0) |
9 | return; |
10 | |
11 | for(rx=0;rx<alpha->w;rx++) //rx for relative x |
12 | for(ry=0;ry<alpha->h;ry++) //See above |
13 | { |
14 | alphaPart=_getpixel(alpha,rx,ry)/255.0; |
15 | color=getpixel(destination,x+rx,y+ry); |
16 | r=alphaPart*getr(color); |
17 | g=alphaPart*getg(color); |
18 | b=alphaPart*getb(color); |
19 | putpixel(destination,x+rx,y+ry,makecol(r,g,b)); |
20 | } |
21 | } |
Now the fog of war really does look like fog!
I wrote a whole header of cool functions, and I will probably release it sometime. Good that you solved you problem!