1 /*
2  *    Example program for the Allegro library, by Shawn Hargreaves.
3  *
4  *    This program demonstrates how to use the 32 bit RGBA
5  *    translucency functions to store an alpha channel along with
6  *    a bitmap graphic.  Two images are loaded from disk. One will
7  *    be used for the background and the other as a sprite. The
8  *    example generates an alpha channel for the sprite image,
9  *    composing the 32 bit RGBA bitmap during runtime, and draws
10  *    it at the position of the mouse cursor.
11  */
12 
13 
14 #include <allegro.h>
15 
16 
17 
main(int argc,char * argv[])18 int main(int argc, char *argv[])
19 {
20    char buf[256];
21    BITMAP *background;
22    BITMAP *alpha;
23    BITMAP *sprite;
24    BITMAP *buffer;
25    int bpp = -1;
26    int ret = -1;
27    int x, y, c, a;
28 
29    if (allegro_init() != 0)
30       return 1;
31    install_keyboard();
32    install_mouse();
33    install_timer();
34 
35    /* what color depth should we use? */
36    if (argc > 1) {
37       if ((argv[1][0] == '-') || (argv[1][0] == '/'))
38 	 argv[1]++;
39       bpp = atoi(argv[1]);
40       if ((bpp != 15) && (bpp != 16) && (bpp != 24) && (bpp != 32)) {
41 	 allegro_message("Invalid color depth '%s'\n", argv[1]);
42 	 return 1;
43       }
44    }
45 
46    if (bpp > 0) {
47       /* set a user-requested color depth */
48       set_color_depth(bpp);
49       ret = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);
50    }
51    else {
52       /* autodetect what color depths are available */
53       static int color_depths[] = { 16, 15, 32, 24, 0 };
54       for (a=0; color_depths[a]; a++) {
55 	 bpp = color_depths[a];
56 	 set_color_depth(bpp);
57 	 ret = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);
58 	 if (ret == 0)
59 	    break;
60       }
61    }
62 
63    /* did the video mode set properly? */
64    if (ret != 0) {
65       set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
66       allegro_message("Error setting %d bit graphics mode\n%s\n", bpp,
67 		      allegro_error);
68       return 1;
69    }
70 
71    /* load the background picture */
72    replace_filename(buf, argv[0], "allegro.pcx", sizeof(buf));
73    background = load_bitmap(buf, NULL);
74    if (!background) {
75       set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
76       allegro_message("Error reading %s!\n", buf);
77       return 1;
78    }
79 
80    /* make a copy of it */
81    set_color_depth(32);
82    sprite = create_bitmap(background->w, background->h);
83    blit(background, sprite, 0, 0, 0, 0, background->w, background->h);
84 
85    /* load the alpha sprite image. Note that we specifically force this
86     * to load in a 32 bit format by calling set_color_depth(). That is
87     * because the disk file is actually only a 256 color graphic: if it
88     * was already a 32 bit RGBA sprite, we would probably want to use
89     * set_color_conversion(COLORCONV_NONE) instead.
90     */
91    replace_filename(buf, argv[0], "mysha.pcx", sizeof(buf));
92    alpha = load_bitmap(buf, NULL);
93    if (!alpha) {
94       set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
95       allegro_message("Error reading %s!\n", buf);
96       return 1;
97    }
98 
99    /* normally we would have loaded an RGBA image directly from disk. Since
100     * I don't have one lying around, and am too lazy to draw one (or I could
101     * rationalise this by saying that I'm trying to save download size by
102     * reusing graphics :-) I'll just have to generate an alpha channel in
103     * code. I do this by using greyscale values from the mouse picture as an
104     * alpha channel for the Allegro image. Don't worry about this code: you
105     * wouldn't normally need to write anything like this, because you'd just
106     * get the right graphics directly out of a datafile.
107     */
108    drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
109    set_write_alpha_blender();
110 
111    for (y=0; y<sprite->h; y++) {
112       for (x=0; x<sprite->w; x++) {
113 	 c = getpixel(alpha, x, y);
114 	 a = getr(c) + getg(c) + getb(c);
115 	 a = CLAMP(0, a/2-128, 255);
116 
117 	 putpixel(sprite, x, y, a);
118       }
119    }
120 
121    destroy_bitmap(alpha);
122 
123    set_color_depth(bpp);
124 
125    /* darken the background image down a bit */
126    drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
127    set_multiply_blender(0, 0, 0, 255);
128    rectfill(background, 0, 0, background->w, background->h,
129 	    makecol(32, 16, 128));
130    solid_mode();
131 
132    /* create a double buffer bitmap */
133    buffer = create_bitmap(SCREEN_W, SCREEN_H);
134 
135    /* scale the background image to be the same size as the screen */
136    stretch_blit(background, buffer, 0, 0, background->w, background->h,
137 		0, 0, SCREEN_W, SCREEN_H);
138 
139    textprintf_ex(buffer, font, 0, 0, makecol(255, 255, 255), -1,
140 		 "%dx%d, %dbpp", SCREEN_W, SCREEN_H, bpp);
141 
142    destroy_bitmap(background);
143    background = create_bitmap(SCREEN_W, SCREEN_H);
144    blit(buffer, background, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
145 
146    while (!keypressed()) {
147       /* draw the alpha sprite */
148       x = mouse_x - sprite->w/2;
149       y = mouse_y - sprite->h/2;
150 
151       set_alpha_blender();
152       draw_trans_sprite(buffer, sprite, x, y);
153 
154       /* flip it across to the screen */
155       blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
156 
157       /* replace the background where we drew the sprite */
158       blit(background, buffer, x, y, x, y, sprite->w, sprite->h);
159    }
160 
161    clear_keybuf();
162 
163    destroy_bitmap(background);
164    destroy_bitmap(sprite);
165    destroy_bitmap(buffer);
166 
167    return 0;
168 }
169 
170 END_OF_MAIN()
171