/* DO_MAP adds an additional level of weirdness. */ /* #undef DO_MAP */ #define DO_MAP /* POLYTYPE_ATEX is normal, and POLYTYPE_ATEX_TRANS is extra-crispy. */ /* #define POLYTYPE POLYTYPE_ATEX */ #define POLYTYPE POLYTYPE_ATEX_TRANS /* Transparency factor. The bigger the blurrier. */ #define TRANS_LEVEL 3 /* Screen size. W and H should probably be multiples of SPACE. */ #define W 640 #define H 480 #define SPACE 5 /* The rest of the program. Scroll down at your own risk. This code is the * messiest I have ever written. */ #include #include #include #include #include #include /* #include "loadpng.h" */ /* Weighted map entry */ typedef struct Map { int x, y; int a1, a2, a3, a4; /* ul, ur, ll, lr */ } Map; #define COUNT ((W + 80) / SPACE) * ((H + 80) / SPACE) int gridx[COUNT]; int gridy[COUNT]; /* Sets up a grayscale palette. */ /* GRR... why can't I use eight-bit values in palettes!?! */ void init_palette(void) { /* static int offset = 0; static PALETTE pal; int r, g, b; set_palette_range(pal, 0, 255, 0); */ int c; RGB color; for (c = 0; c < 256; c++) { color.r = c / 4; color.g = c / 4; color.b = c / 4; set_color(c, &color); } } /* getpixel variant that returns the pixel value the map entry points to. */ int get(BITMAP* bmp, Map* m) { /* unsigned char** line = bmp->line + m->y; unsigned char* l1 = line[0] + m->x; unsigned char* l2 = m->y < H ? (line[1] + m->x) : NULL; int c = 0; if (m->a1 != 0) c += l1[0] * m->a1; if (m->a2 != 0) c += l1[1] * m->a2; if (m->a3 != 0) c += l2[0] * m->a3; if (m->a4 != 0) c += l2[1] * m->a4; return c / 256; */ unsigned** line = (unsigned**)bmp->line + m->y; unsigned* l1 = line[0] + m->x; unsigned* l2 = m->y < H ? (line[1] + m->x) : NULL; int r = 0, g = 0, b = 0; if (m->a1 != 0) { r += getr32(l1[0]) * m->a1; g += getg32(l1[0]) * m->a1; b += getb32(l1[0]) * m->a1; } if (m->a2 != 0) { r += getr32(l1[1]) * m->a2; g += getg32(l1[1]) * m->a2; b += getb32(l1[1]) * m->a2; } if (m->a3 != 0) { r += getr32(l2[0]) * m->a3; g += getg32(l2[0]) * m->a3; b += getb32(l2[0]) * m->a3; } if (m->a4 != 0) { r += getr32(l2[1]) * m->a4; g += getg32(l2[1]) * m->a4; b += getb32(l2[1]) * m->a4; } return makecol32(r / 256, g / 256, b / 256); } /* Sets up four contiguous map entries. */ void init_map_helper(float x, float y, Map* m) { int fx = m->x = floor(x); int fy = m->y = floor(y); float cx = x - fx; float cy = y - fy; float icx = 1.0 - cx; float icy = 1.0 - cy; m->a1 = fx < 0 || fx > W - 1 || fy < 0 || fy > H - 1 ? 0 : icx * icy * 256; m->a2 = fx < -1 || fx > W - 2 || fy < 0 || fy > H - 1 ? 0 : cx * icy * 256; m->a3 = fx < 0 || fx > W - 1 || fy < -1 || fy > H - 2 ? 0 : icx * cy * 256; m->a4 = fx < -1 || fx > W - 2 || fy < -1 || fy > H - 2 ? 0 : cx * cy * 256; } /* Sets up the entire map. */ void init_map(Map* m) { int x, y; float xx, yy; float a, xs, ys; for (y = 0; y < H; y++) { for (x = 0; x < W; x++, m++) { xs = sin((x - y - W / 2) * M_PI / 40.0) / 20.0 + 1.08; ys = cos((y - x - H / 2) * M_PI / 40.0) / 20.0 + 1.08; a = cos((x - sin((x + y) * M_PI / 40.0) * 10.0 - W / 2) * M_PI / H * 4) * M_PI / 50.0; /* xs = cos(M_PI / 45 * sqrt((x - W / 2) * (x - W / 2) + (y - H / 2) * (y - H / 2))) * 0.05 + 1.05; ys = sin(M_PI / 50 * sqrt((x - W / 2) * (x - W / 2) + (y - H / 2) * (y - H / 2))) * 0.05 + 1.05; a = cos(M_PI / 30 * sqrt((x - W / 2) * (x - W / 2) + (y - H / 2) * (y - H / 2))) * M_PI / 20; xs = 1.01; ys = 0.99; a = M_PI / 40.; */ xx = W / 2 + (-cos(-a) * (W / 2 - x) + sin(-a) * (H / 2 - y)) / xs; yy = H / 2 + (-sin(-a) * (W / 2 - x) - cos(-a) * (H / 2 - y)) / ys; /* Source pixel: (xx, yy); Dest pixel: (x, y) */ init_map_helper(xx, yy, m); } } } /* Frobs your widgets */ int main(int argc, char** argv) { BITMAP* buffer; BITMAP* buffer2; clock_t timer; int frames = 0; BITMAP* buffer3; #ifdef DO_MAP Map* map; map = malloc(sizeof(Map) * W * H); init_map(map); #endif srand(time(NULL)); allegro_init(); install_keyboard(); install_mouse(); install_timer(); /* set_color_depth(8); set_gfx_mode(GFX_AUTODETECT, W, H, 0, 0); init_palette(); */ set_color_depth(32); set_gfx_mode(GFX_AUTODETECT_WINDOWED, W, H, 0, 0); if (argc == 2) { /* register_png_file_type(); */ set_color_depth(32); buffer = load_bitmap(argv[1], NULL); /* set_color_depth(8); */ buffer3 = create_bitmap(1024, 1024); stretch_blit(buffer, buffer3, 0, 0, buffer->w, buffer->h, 0, 0, buffer3->w, buffer3->h); destroy_bitmap(buffer); } buffer = create_bitmap(W, H); clear_bitmap(buffer); #ifdef DO_MAP buffer2 = create_bitmap(W, H); clear_bitmap(buffer2); #endif text_mode(-1); /* Disable text background */ set_trans_blender(0, 0, 0, 255 / TRANS_LEVEL); timer = clock(); while (1) { /* unsigned char** bpp = buffer2->line; unsigned char** bpp_end = bpp + H; unsigned char* bp; unsigned char* bp_end; */ unsigned** bpp = (unsigned**)buffer2->line; unsigned** bpp_end = bpp + H; unsigned* bp; unsigned* bp_end; #ifdef DO_MAP Map* mp = (Map*)map; #endif /* int x = W / 2 + (rand() & 63) - 31; int y = H / 2 + (rand() & 63) - 31; */ int x, y; /* Add interesting stuff */ #if 1 float ticks = frames * M_PI / 160; int i = 0; int w = (W + 80) / SPACE; for (y = -40; y < H + 40; y += SPACE) { for (x = -40; x < W + 40; x += SPACE) { int ix, iy, x2, y2; x2 = W / 2 + (-cos(1.2 * ticks) * (W / 2 - x) + sin(1.5 * ticks) * (H / 2 - y)); y2 = H / 2 + (-sin(1.3 * ticks) * (W / 2 - x) - cos(-1.1 * ticks) * (H / 2 - y)); ix = x + cos(ticks + y2 / (H / 13.0)) * (5 * SPACE * sin(ticks + x2 / (W / 16.))); iy = y - sin(ticks + x2 / (W / 13.0)) * (5 * SPACE * cos(ticks - y2 / (H / 16.))); gridx[i] = ix; gridy[i++] = iy; } } #if 1 { V3D_f vtx[4]; V3D_f* vtx_i[4] = {&vtx[0], &vtx[1], &vtx[2], &vtx[3]}; vtx[0].z = vtx[1].z = vtx[2].z = vtx[3].z = 1; vtx[0].c = vtx[1].c = vtx[2].c = vtx[3].c = 255; i = 0; for (y = 0; y < (H + 80) / SPACE - 1; y++) { int ii = i; x = 0; for (; i < ii + w - 1; i++, x++) { vtx[0].x = gridx[i]; vtx[0].y = gridy[i]; vtx[0].u = x * 1024. / ((W + 80) / SPACE); vtx[0].v = y * 1024. / ((H + 80) / SPACE); vtx[1].x = gridx[i + w]; vtx[1].y = gridy[i + w]; vtx[1].u = x * 1024. / ((W + 80) / SPACE); vtx[1].v = (y + 1) * 1024. / ((H + 80) / SPACE); vtx[2].x = gridx[i + w + 1]; vtx[2].y = gridy[i + w + 1]; vtx[2].u = (x + 1) * 1024. / ((W + 80) / SPACE); vtx[2].v = (y + 1) * 1024. / ((H + 80) / SPACE); vtx[3].x = gridx[i + 1]; vtx[3].y = gridy[i + 1]; vtx[3].u = (x + 1) * 1024. / ((W + 80) / SPACE); vtx[3].v = y * 1024. / ((H + 80) / SPACE); polygon3d_f(buffer, POLYTYPE, buffer3, 4, vtx_i); #if 0 line(buffer, vtx[0].x, vtx[0].y, vtx[1].x, vtx[1].y, ~0); line(buffer, vtx[0].x, vtx[0].y, vtx[3].x, vtx[3].y, ~0); #endif } i = ii + w; } } #endif #if 0 i = 0; for (y = -40; y < H + 40; y += SPACE) { int ii = i; for (; i < ii + w; i++) { int x1, y1, x2, y2; x1 = gridx[i]; y1 = gridy[i]; if (i > ii) { x2 = gridx[i - 1]; y2 = gridy[i - 1]; line(buffer, x1, y1 - 1, x2, y2 - 1, 0); line(buffer, x1, y1 + 1, x2, y2 + 1, 0); line(buffer, x1 - 1, y1, x2 - 1, y2, 0); line(buffer, x1 + 1, y1, x2 + 1, y2, 0); } if (i >= w) { x2 = gridx[i - w]; y2 = gridy[i - w]; line(buffer, x1, y1 - 1, x2, y2 - 1, 0); line(buffer, x1, y1 + 1, x2, y2 + 1, 0); line(buffer, x1 - 1, y1, x2 - 1, y2, 0); line(buffer, x1 + 1, y1, x2 + 1, y2, 0); } } } #endif #if 0 i = 0; for (y = -40; y < H + 40; y += SPACE) { int ii = i; for (; i < ii + w; i++) { int x1, y1, x2, y2; x1 = gridx[i]; y1 = gridy[i]; if (i > ii) { x2 = gridx[i - 1]; y2 = gridy[i - 1]; line(buffer, x1, y1, x2, y2, 255); } if (i >= w) { x2 = gridx[i - w]; y2 = gridy[i - w]; line(buffer, x1, y1, x2, y2, 255); } } } #endif #endif #if 0 for (x = 0; x < W; x++) putpixel(buffer, x, H / 2 + 32 * sin((frames + x) * M_PI / W * 2), 255); for (y = 0; y < H; y++) putpixel(buffer, W / 2 + 32 * cos((frames + y) * M_PI / H * 2), y, 255); #endif #if 0 textprintf_centre(buffer, font, mouse_x + 1, mouse_y + 1, 0, "fps: %f", (float)frames * CLOCKS_PER_SEC / (clock() - timer)); textprintf_centre(buffer, font, mouse_x, mouse_y, 255 << 16, "fps: %f", (float)frames * CLOCKS_PER_SEC / (clock() - timer)); #endif #if 0 circlefill(buffer, x, y, 4, 255); #endif #if 0 circlefill(buffer, mouse_x, mouse_y, 5, 255); #endif /* putpixel(buffer, W / 2, H / 2, 0); */ /* Map old image to new */ #ifdef DO_MAP for (; bpp < bpp_end; bpp++) { bp = *bpp; bp_end = bp + W; for (; bp < bp_end; bp++, mp++) *bp = get(buffer, mp); } /* clear_bitmap(buffer); */ blit(buffer2, buffer, 0, 0, 0, 0, W, H); /* Feedback! */ /* vsync(); */ blit(buffer2, screen, 0, 0, 0, 0, W, H); /* Display */ #else blit(buffer, screen, 0, 0, 0, 0, W, H); /* clear_bitmap(buffer); */ #endif frames++; if (keypressed()) { int k = readkey(); if (k >> 8 == KEY_ESC) break; if (k >> 8 == KEY_SPACE) { while (key[KEY_SPACE]); while (!key[KEY_SPACE]); while (key[KEY_SPACE]); } clear_keybuf(); } } timer = clock() - timer; set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); printf("Average FPS: %f\n", (float)frames * CLOCKS_PER_SEC / timer); destroy_bitmap(buffer); #ifdef DO_MAP destroy_bitmap(buffer2); free(map); #endif return EXIT_SUCCESS; } END_OF_MAIN()