📄 exlights.c
字号:
out2 = rgtable[in2>>16] |
brtable[in3&0xFFFF] |
(gbtable[in3>>16] << 16);
bmp_write32(addr, out1);
bmp_write32(addr+4, out2);
addr += 8;
}
}
bmp_unwrite_line(screen);
}
#elif defined ALLEGRO_BIG_ENDIAN
/* lookup tables for speeding up the color conversion */
unsigned short bgtable[65536];
unsigned long rbtable[65536];
unsigned short grtable[65536];
/* builds some helper tables for doing color conversions */
void generate_conversion_tables(void)
{
int r, g, b;
int cr, cg, cb;
/* this table combines a 16 bit b+g value into a screen pixel */
for (b=0; b<256; b++) {
cb = (b&31) * (b>>5) * 255/217;
for (g=0; g<256; g++) {
cg = (g&31) * (g>>5) * 255/217;
bgtable[b+g*256] = makecol(0, cg, cb);
}
}
/* this table combines a 16 bit g+r value into a screen pixel */
for (r=0; r<256; r++) {
cr = (r&31) * (r>>5) * 255/217;
for (b=0; b<256; b++) {
cb = (b&31) * (b>>5) * 255/217;
rbtable[r+b*256] = makecol(cr, 0, 0) | (makecol(0, 0, cb) << 16);
}
}
/* this table combines a 16 bit r+r value into a screen pixel */
for (g=0; g<256; g++) {
cg = (g&31) * (g>>5) * 255/217;
for (r=0; r<256; r++) {
cr = (r&31) * (r>>5) * 255/217;
grtable[g+r*256] = makecol(cr, cg, 0);
}
}
}
/* copies from our magic format data onto a normal Allegro screen bitmap */
void blit_magic_format_to_screen(BITMAP *bmp)
{
uintptr_t addr;
uint32_t *data;
unsigned long in1, in2, in3, temp1, temp2, temp3;
unsigned long out1, out2;
int x, y;
/* Warning: this is the big-endian version of the routine above. We need
* a different lookup tables arrangement and we also need to shuffle the
* bytes order before doing the lookup.
*
* Here is a (rather confusing) attempt to diagram the logic of the
* lookup table lighting conversion from 24 to 16 bit format in big-
* endian format:
*
*
* inputs: | (dword 1) | (dword 2) | (dword 3) |
* pixels: | (pixel1) | (pixel2) | (pixel3) | (pixel4) |
* bytes: | r2 b1 g1 r1 g3 r3 b2 g2 b4 g4 r4 b3 |
* bytes2: | b2 g2 r2 b1 g1 r1 b4 g4 r4 b3 g3 r3 |
* | | | | | | | |
* lookup: | bgtable rbtable grtable bgtable rbtable grtable |
* | | | | | | | |
* pixels: | (pixel2) | (pixel1) | (pixel4) | (pixel3) |
* outputs | (dword 1) | (dword 2) |
*/
bmp_select(screen);
for (y=0; y<SCREEN_H; y++) {
addr = bmp_write_line(screen, y);
data = (uint32_t *)bmp->line[y];
for (x=0; x<SCREEN_W/4; x++) {
in1 = *(data++);
in2 = *(data++);
in3 = *(data++);
/* trust me, this does make sense, really :-) */
temp1 = (in1 << 16) | (in2 >> 16);
temp2 = (in1 >> 16) | (in3 << 16);
temp3 = (in3 >> 16) | (in2 << 16);
out1 = bgtable[temp1&0xFFFF] |
rbtable[temp1>>16] |
(grtable[temp2&0xFFFF] << 16);
out2 = bgtable[temp2>>16] |
rbtable[temp3&0xFFFF] |
(grtable[temp3>>16] << 16);
bmp_write32(addr, out1);
bmp_write32(addr+4, out2);
addr += 8;
}
}
bmp_unwrite_line(screen);
}
#elif !defined SCAN_DEPEND
#error Unknown endianess!
#endif
int main(int argc, char *argv[])
{
BITMAP *tmp;
PALETTE pal;
char buf[256];
int x, y, xc, yc, xl, yl, c, l;
if (allegro_init() != 0)
return 1;
install_keyboard();
install_timer();
install_mouse();
set_color_conversion(COLORCONV_NONE);
/* set a 15 or 16 bpp video mode */
set_color_depth(16);
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
set_color_depth(15);
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Error setting a 15 or 16 bpp 640x480 video mode\n%s\n", allegro_error);
return 1;
}
}
/* create the double buffer, 8 bpp and three times as wide as the screen */
buffer = create_bitmap_ex(8, SCREEN_W*3, SCREEN_H);
/* load the first picture */
replace_filename(buf, argv[0], "allegro.pcx", sizeof(buf));
tmp = load_bitmap(buf, pal);
if (!tmp) {
destroy_bitmap(buffer);
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Error reading %s!\n", buf);
return 1;
}
/* convert it into our special format */
image1 = get_magic_bitmap_format(tmp, pal);
destroy_bitmap(tmp);
/* load the second picture */
replace_filename(buf, argv[0], "mysha.pcx", sizeof(buf));
tmp = load_bitmap(buf, pal);
if (!tmp) {
destroy_bitmap(buffer);
destroy_bitmap(image1);
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Error reading %s!\n", buf);
return 1;
}
/* convert it into our special format */
image2 = get_magic_bitmap_format(tmp, pal);
destroy_bitmap(tmp);
/* create the light map image */
lightmap = create_light_graphic();
/* create our custom color blending map, which does translucency in the
* bottom five bits and adds the light levels in the top three bits.
* This version just does a 50% translucency if you are drawing sprites
* with it, but you could easily make other color maps for different
* alpha levels, or for doing additive color, which can work happily
* in parallel with the light blending.
*/
color_map = malloc(sizeof(COLOR_MAP));
for (x=0; x<256; x++) {
for (y=0; y<256; y++) {
xc = x&31;
yc = y&31;
xl = x>>5;
yl = y>>5;
if (xc)
c = (xc+yc)/2;
else
c = yc;
l = xl+yl;
if (l > 7)
l = 7;
color_map->data[x][y] = c | (l<<5);
}
}
/* generate tables for converting pixels from magic->screen format */
generate_conversion_tables();
/* display the animation */
while (!keypressed()) {
poll_mouse();
clear_bitmap(buffer);
/* we can draw the graphics using normal calls, just as if they were
* regular 256 color images. Everything is just three times as wide
* as it would usually be, so we need to make sure that we only ever
* draw to an x coordinate that is a multiple of three (otherwise
* all the colors would get shifted out of phase with each other).
*/
blit(image1, buffer, 0, 0, 0, retrace_count%(SCREEN_H+image1->h)-image1->h, image1->w, image1->h);
blit(image2, buffer, 0, 0, buffer->w-image2->w, buffer->h-(retrace_count*2/3)%(SCREEN_H+image2->h), image2->w, image2->h);
/* now we overlay translucent graphics and lights. Having set up a
* suitable color blending table, these can be done at the same time,
* either drawing a series of images some of which are translucent
* sprites and some of which are light maps, or if we want, we can
* just draw a single bitmap containing both color and light data
* with a single call, like this! You could also use graphics
* primitives like circlefill() to draw the lights, as long as you
* do it in a translucent mode.
*/
draw_trans_sprite(buffer, lightmap, (mouse_x-lightmap->w/6)*3, mouse_y-lightmap->h/2);
/* this function is the key to the whole thing, converting from our
* weird 5+3 interleaved format into a regular hicolor pixel that
* can be displayed on your monitor.
*/
blit_magic_format_to_screen(buffer);
}
clear_keybuf();
destroy_bitmap(buffer);
destroy_bitmap(image1);
destroy_bitmap(image2);
destroy_bitmap(lightmap);
free(color_map);
return 0;
}
END_OF_MAIN()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -