/* water.c v0.80 */ /* EB = Edward Boone */ /* epsilonbeta@geocities.com */ /* http://www.geocities.com/SiliconValley/Vista/6617/index.html */ /* Only nothing seems to be what it looks like */ /*---------------------------------------------------------------------------*/ /* #include */ #include "specific.h" /*---------------------------------------------------------------------------*/ /* #define */ #define DELAY_MIN 0 #define DELAY_MAX 3000 #define DELAY_STEP 100 #define DENSITY_MIN 0 #define DENSITY_MAX 32768 #define DENSITY_STEP 1 #define DISTANCE_MIN -32768 #define DISTANCE_MAX 32768 #define DISTANCE_STEP 100 #define LIGHT_MIN 0 #define LIGHT_MAX 1 #define LIGHT_STEP 1 #define MOVEMENT_MIN 0 #define MOVEMENT_MAX 1 #define MOVEMENT_STEP 1 #define SIZE_MIN 0 #define SIZE_MAX 32768 #define SIZE_STEP 1 #define SORT_MIN 1 #define SORT_MAX 7 #define SORT_STEP 1 #define X_MIN 0 #define X_MAX scr_w #define X_STEP 10 #define Y_MIN 0 #define Y_MAX scr_h #define Y_STEP 10 /*---------------------------------------------------------------------------*/ /* variables */ uchr *scr_buf, *bmp_buf; int hpage, offset, ox, oy, swirlangle, sz_pixels, xang, yang; int **height; int fcostab[FSINMAX + 1]; int fsintab[FSINMAX + 1]; BITMAP *scr_pbmp; int delayy, density, distance, light, material, movement; int size, x, y; static tkeyparse see_f9_0 = {K_0, keysee_f9_0}, /* water.c specific */ see_f9_1 = {K_1, keysee_f9_1}, see_f9_2 = {K_2, keysee_f9_2}, see_f9_3 = {K_3, keysee_f9_3}, see_f9_4 = {K_4, keysee_f9_4}, see_f9_5 = {K_5, keysee_f9_5}, see_f9_6 = {K_6, keysee_f9_6}, see_f9_7 = {K_7, keysee_f9_7}, see_f9_8 = {K_8, keysee_f9_8}, see_f9_9 = {K_9, keysee_f9_9}, see_f9_A = {K_A, keysee_f9_A}, see_f9_D = {K_D, keysee_f9_D}, see_f9_E = {K_E, keysee_f9_E}, see_f9_F = {K_F, keysee_f9_F}, see_f9_H = {K_H, keysee_f9_H}, see_f9_L = {K_L, keysee_f9_L}, see_f9_S = {K_S, keysee_f9_S}, see_f9_X = {K_X, keysee_f9_X}, see_f9_Y = {K_Y, keysee_f9_Y}, see_f9_a = {K_a, keysee_f9_a}, see_f9_d = {K_d, keysee_f9_d}, see_f9_e = {K_e, keysee_f9_e}, see_f9_f = {K_f, keysee_f9_f}, see_f9_h = {K_h, keysee_f9_h}, see_f9_l = {K_l, keysee_f9_l}, see_f9_s = {K_s, keysee_f9_s}, see_f9_x = {K_x, keysee_f9_x}, see_f9_y = {K_y, keysee_f9_y} ; tkeyparse* tkeyparsetbl_water[] = { TKEYPARSETBL_SEE, /* see.c specific */ &see_f9_0, /* water.c specific */ &see_f9_1, &see_f9_2, &see_f9_3, &see_f9_4, &see_f9_5, &see_f9_6, &see_f9_7, &see_f9_8, &see_f9_9, &see_f9_A, &see_f9_D, &see_f9_E, &see_f9_F, &see_f9_H, &see_f9_L, &see_f9_S, &see_f9_X, &see_f9_Y, &see_f9_a, &see_f9_d, &see_f9_e, &see_f9_f, &see_f9_h, &see_f9_l, &see_f9_s, &see_f9_x, &see_f9_y, NULL }; teffect eff_water = { water_init, water_effect, water_loop_end, water_done, tkeyparsetbl_water, 1 }; /*---------------------------------------------------------------------------*/ int water_loop_end() { switch (lastkey) { COMMON_LOOP_END case K_A: case K_D: case K_E: case K_F: case K_H: case K_L: case K_S: case K_X: case K_Y: case K_a: case K_d: case K_e: case K_f: case K_h: case K_l: case K_s: case K_x: case K_y: return 0; break; default: return 1; break; } } /*---------------------------------------------------------------------------*/ int fcosa(int angle) { return fcostab[angle & FSINMAX]; /* 2047 = 0x07FF */ } /*---------------------------------------------------------------------------*/ int fsina(int angle) { return fsintab[angle & FSINMAX]; /* 2047 = 0x07FF */ } /*---------------------------------------------------------------------------*/ void calcwater(int npage, int adensity) { int count = scr_w + 1, newh; int *newptr = &height[npage][0]; int *oldptr = &height[npage^1][0]; int x, y; for (y = (scr_h - 1) * scr_w; count < y; count += 2) { for (x = count + scr_w - 2; count < x; count++) { newh = ((oldptr[count + scr_w] + oldptr[count - scr_w] + oldptr[count + 1] + oldptr[count - 1] + oldptr[count - scr_w - 1] + oldptr[count - scr_w + 1] + oldptr[count + scr_w - 1] + oldptr[count + scr_w + 1]) >> 2) - newptr[count]; newptr[count] = newh - (newh >> adensity); } } } /*---------------------------------------------------------------------------*/ void calcwaterbigfilter(int npage, int adensity) { int newh, x, y; int count = (2 * scr_w) + 2; int *newptr = &height[npage][0]; int *oldptr = &height[npage^1][0]; for (y = 2; y < scr_h - 2; y++) { for (x = 2; x < scr_w - 2; x++) { newh = ((( (oldptr[count + scr_w] + oldptr[count - scr_w] + oldptr[count + 1] + oldptr[count - 1]) << 1) + ((oldptr[count - scr_w - 1] + oldptr[count - scr_w + 1] + oldptr[count + scr_w - 1] + oldptr[count + scr_w + 1])) + ((oldptr[count - (scr_w * 2)] + oldptr[count + (scr_w * 2)] + oldptr[count - 2] + oldptr[count + 2]) >> 1 ) + ((oldptr[count - (scr_w * 2) - 1] + oldptr[count - (scr_w * 2) + 1] + oldptr[count + (scr_w * 2) - 1] + oldptr[count + (scr_w * 2) + 1] + oldptr[count - 2 - scr_w] + oldptr[count - 2 + scr_w] + oldptr[count + 2 - scr_w] + oldptr[count + 2 + scr_w]) >> 2)) >> 3) - (newptr[count]); newptr[count] = newh - (newh >> adensity); count++; } count += 4; } } /*---------------------------------------------------------------------------*/ void drawwaternolight(int page) { int c, dx, dy, x, y; int offset = scr_w + 1; int *ptr = &height[page][0]; for (y = (scr_h - 1) * scr_w; offset < y; offset += 2) { for(x = offset + scr_w - 2; offset < x; offset++) { dx = ptr[offset] - ptr[offset + 1]; dy = ptr[offset] - ptr[offset + scr_w]; c = bmp_buf[offset + scr_w * (dy >> 3) + (dx >> 3)]; scr_buf[offset] = (c < 0) ? 0 : (c > 255) ? 255 : c; offset++; dx = ptr[offset] - ptr[offset + 1]; dy = ptr[offset] - ptr[offset + scr_w]; c = bmp_buf[offset + scr_w * (dy >> 3) + (dx >> 3)]; scr_buf[offset] = (c < 0) ? 0 : (c > 255) ? 255 : c; } } blit(scr_pbmp, screen, 0, 0, 0, 0, scr_w, scr_h); } /*---------------------------------------------------------------------------*/ void drawwaterwithlight(int page, int lightmodifier) { int c, dx, dy, x, y; int offset = scr_w + 1; int *ptr = &height[page][0]; for (y = (scr_h - 1) * scr_w; offset < y; offset += 2) { for (x = offset + scr_w - 2; offset < x; offset++) { dx = ptr[offset] - ptr[offset + 1]; dy = ptr[offset] - ptr[offset + scr_w]; c = bmp_buf[offset + scr_w * (dy >> 3) + (dx >> 3)] - (dx >> lightmodifier); scr_buf[offset] = (c < 0) ? 0 : (c > 255) ? 255 : c; offset++; dx = ptr[offset] - ptr[offset + 1]; dy = ptr[offset] - ptr[offset + scr_w]; c = bmp_buf[offset + scr_w * (dy >> 3) + (dx >> 3)] - (dx >> lightmodifier); scr_buf[offset] = (c < 0) ? 0 : (c > 255) ? 255 : c; } } blit(scr_pbmp, screen, 0, 0, 0, 0, scr_w, scr_h); } /*---------------------------------------------------------------------------*/ void fcreatesines() { int i; double angle; for (i = 0; i < (FSINMAX + 1); i++) { angle = (float) i * (PI / ((FSINMAX + 1) / 2.0)); /* fixed point format : 1.0000 0000 0000 0000 = 65536 */ fsintab[i] = (int) (sin(angle) * (float) 0x10000); fcostab[i] = (int) (cos(angle) * (float) 0x10000); } } /*---------------------------------------------------------------------------*/ void heightblob(int x, int y, int aradius, int aheight, int page) { int bottom, cx, cy, cyq, left, right, rquad, top; rquad = aradius * aradius; if (x < 0) { x = 1 + aradius + rand() % (scr_w - 2 * aradius - 1); } if (y < 0) { y = 1 + aradius + rand() % (scr_h - 2 * aradius - 1); } left = -aradius; right = aradius; top = -aradius; bottom = aradius; if (x - aradius < 1) { left -= (x - aradius - 1); } if (y - aradius < 1) { top -= (y - aradius - 1); } if (x + aradius > scr_w - 1) { right -= (x + aradius - scr_w + 1); } if (y + aradius > scr_h - 1) { bottom -= (y + aradius - scr_h + 1); } for (cy = top; cy < bottom; cy++) { cyq = cy * cy; for (cx = left; cx < right; cx++) { if (cx * cx + cyq < rquad) height[page][scr_w * (cy + y) + (cx + x)] += aheight; } } } /*---------------------------------------------------------------------------*/ void heightbox(int x, int y, int aradius, int aheight, int page) { int bottom, cx, cy, left, right, top; if (x < 0) x = 1 + aradius + rand() % (scr_w - 2 * aradius - 1); if (y < 0) y = 1 + aradius + rand() % (scr_h - 2 * aradius - 1); left = -aradius; right = aradius; top = -aradius; bottom = aradius; if (x - aradius < 1) { left -= (x - aradius - 1); } if (y - aradius < 1) { top -= (y - aradius - 1); } if (x + aradius > scr_w - 1) { right -= (x + aradius - scr_w + 1); } if (y + aradius > scr_h - 1) { bottom -= (y + aradius - scr_h + 1); } for (cy = top; cy < bottom; cy++) { for (cx = left; cx < right; cx++) { height[page][scr_w * (cy + y) + (cx + x)] = aheight; } } } /*---------------------------------------------------------------------------*/ void keysee_f9_0() { keysee_f9_gen("f9_0"); } /*---------------------------------------------------------------------------*/ void keysee_f9_1() { keysee_f9_gen("f9_1"); } /*---------------------------------------------------------------------------*/ void keysee_f9_2() { keysee_f9_gen("f9_2"); } /*---------------------------------------------------------------------------*/ void keysee_f9_3() { keysee_f9_gen("f9_3"); } /*---------------------------------------------------------------------------*/ void keysee_f9_4() { keysee_f9_gen("f9_4"); } /*---------------------------------------------------------------------------*/ void keysee_f9_5() { keysee_f9_gen("f9_5"); } /*---------------------------------------------------------------------------*/ void keysee_f9_6() { keysee_f9_gen("f9_6"); } /*---------------------------------------------------------------------------*/ void keysee_f9_7() { keysee_f9_gen("f9_7"); } /*---------------------------------------------------------------------------*/ void keysee_f9_8() { keysee_f9_gen("f9_8"); } /*---------------------------------------------------------------------------*/ void keysee_f9_9() { keysee_f9_gen("f9_9"); } /*---------------------------------------------------------------------------*/ void keysee_f9_A() { paraint(&eff_water.asort, SORT_MIN, SORT_MAX, SORT_STEP, 1, 1); } /*---------------------------------------------------------------------------*/ void keysee_f9_D() { paraint(&delayy, DELAY_MIN, DELAY_MAX, DELAY_STEP, 1, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_E() { paraint(&density, DENSITY_MIN, DENSITY_MAX, DENSITY_STEP, 1, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_F() { paraint(&movement, MOVEMENT_MIN, MOVEMENT_MAX, MOVEMENT_STEP, 1, 1); } /*---------------------------------------------------------------------------*/ void keysee_f9_H() { paraint(&distance, DISTANCE_MIN, DISTANCE_MAX, DISTANCE_STEP, 1, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_L() { paraint(&light, LIGHT_MIN, LIGHT_MAX, LIGHT_STEP, 1, 1); } /*---------------------------------------------------------------------------*/ void keysee_f9_S() { paraint(&size, SIZE_MIN, SIZE_MAX, SIZE_STEP, 1, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_X() { paraint(&x, X_MIN, X_MAX, X_STEP, 1, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_Y() { paraint(&y, Y_MIN, Y_MAX, Y_STEP, 1, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_a() { paraint(&eff_water.asort, SORT_MIN, SORT_MAX, SORT_STEP, 0, 1); } /*---------------------------------------------------------------------------*/ void keysee_f9_d() { paraint(&delayy, DELAY_MIN, DELAY_MAX, DELAY_STEP, 0, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_e() { paraint(&density, DENSITY_MIN, DENSITY_MAX, DENSITY_STEP, 0, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_f() { paraint(&movement, MOVEMENT_MIN, MOVEMENT_MAX, MOVEMENT_STEP, 0, 1); } /*---------------------------------------------------------------------------*/ void keysee_f9_gen(uchr s[256]) { int pi; char **tps; water_restore(); tps = get_config_argv("[See]", s, &pi); eff_water.asort = atoi(tps[1]); delayy = atoi(tps[2]); density = atoi(tps[3]); distance = atoi(tps[4]); movement = atoi(tps[5]); light = atoi(tps[6]); material = atoi(tps[7]); size = atoi(tps[8]); x = atoi(tps[9]); y = atoi(tps[10]); do_effect(&eff_water); } /*---------------------------------------------------------------------------*/ void keysee_f9_h() { paraint(&distance, DISTANCE_MIN, DISTANCE_MAX, DISTANCE_STEP, 0, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_l() { paraint(&light, LIGHT_MIN, LIGHT_MAX, LIGHT_STEP, 0, 1); } /*---------------------------------------------------------------------------*/ void keysee_f9_s() { paraint(&size, SIZE_MIN, SIZE_MAX, SIZE_STEP, 0, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_x() { paraint(&x, X_MIN, X_MAX, X_STEP, 0, 0); } /*---------------------------------------------------------------------------*/ void keysee_f9_y() { paraint(&y, Y_MIN, Y_MAX, Y_STEP, 0, 0); } /*---------------------------------------------------------------------------*/ void sineblob(int x, int y, int aradius, int aheight, int page) { int bottom, cx, cy, dist, left, right, square, top; int radsquare = aradius * aradius; float length = (1024.0 / (float) aradius) * (1024.0 / (float) aradius); if (x < 0) { x = 1 + aradius + rand() % (scr_w - 2 * aradius - 1); } if (y < 0) { y = 1 + aradius + rand() % (scr_h - 2 * aradius - 1); } radsquare = (aradius * aradius); left = -aradius; right = aradius; top = -aradius; bottom = aradius; if (x - aradius < 1) { left -= (x - aradius - 1); } if (y - aradius < 1) { top -= (y - aradius - 1); } if (x + aradius > scr_w-1) { right -= (x + aradius - scr_w + 1); } if (y + aradius > scr_h - 1) { bottom -= (y + aradius - scr_h + 1); } for (cy = top; cy < bottom; cy++) { for (cx = left; cx < right; cx++) { square = cy * cy + cx * cx; if (square < radsquare) { dist = sqrt(square * length); height[page][scr_w * (cy + y) + cx + x] += (int)((fcosa(dist) + 0xFFFF) * (aheight)) >> 19; } } } } /*---------------------------------------------------------------------------*/ void smoothwater(int npage) { int newh, x, y; int count = scr_w + 1; int *newptr = &height[npage][0]; int *oldptr = &height[npage^1][0]; for (y = 1; y < scr_h - 1; y++) { for (x = 1; x < scr_w - 1; x++) { newh = ((oldptr[count + scr_w] + oldptr[count - scr_w] + oldptr[count + 1] + oldptr[count - 1] + oldptr[count - scr_w - 1] + oldptr[count - scr_w + 1] + oldptr[count + scr_w - 1] + oldptr[count + scr_w + 1]) >> 3) + newptr[count]; newptr[count] = newh >> 1; count++; } count += 2; } } /*---------------------------------------------------------------------------*/ void warpblob(int x, int y, int aradius, int aheight, int page) { int cx, cy; int left, top, right, bottom; int square; int radsquare = aradius * aradius; radsquare = (aradius * aradius); aheight /= 64; left = -aradius; right = aradius; top = -aradius; bottom = aradius; if (x - aradius < 1) { left -= (x - aradius - 1); } if (y - aradius < 1) { top -= (y - aradius - 1); } if (x + aradius > scr_w - 1) { right -= (x + aradius - scr_w + 1); } if (y + aradius > scr_h - 1) { bottom -= (y + aradius - scr_h + 1); } for (cy = top; cy < bottom; cy++) { for (cx = left; cx < right; cx++) { square = cy * cy + cx * cx; if (square < radsquare) { height[page][scr_w * (cy + y) + cx + x] += (aradius - sqrt(square)) * (float)(aheight); } } } } /*---------------------------------------------------------------------------*/ void water_done() { int i; free(bmp_buf); destroy_bitmapm(scr_pbmp); for (i = 0; i < 2; i++) { free(height[i]); } free(height); } /*---------------------------------------------------------------------------*/ void water_effect(int asort) { switch (asort) { case 1: water_surfer(); break; case 2: water_raindrops(); break; case 3: water_splashes(); break; case 4: water_swirling(); break; case 5: water_test1(); break; case 6: water_test2(); break; case 7: water_test3(); break; } if (light) { drawwaterwithlight(hpage, light - 1); } else { drawwaternolight(hpage); } if (movement) { calcwater(hpage ^ 1, density); } else { memcpy(&height[hpage ^ 1][0], &height[hpage][0], sz_pixels); } hpage ^= 1; for (x = 0; x < 20; x++) { if (retrace_count > x) { putpixel(scr_pbmp, x << 1, 0, 255); } else { putpixel(scr_pbmp, x << 1, 0, 0); } putpixel(scr_pbmp, (x << 1) + 1, 0, 0); } retrace_count = 0; rest(delayy); } /*---------------------------------------------------------------------------*/ void water_init() { int i; sz_pixels = sizeof(int) * npixels; srand(time(NULL)); fcreatesines(); hpage = 0; offset = 0; ox = 0; oy = 0; swirlangle = 0; x = 0; y = 0; xang = rand() % (FSINMAX + 1); yang = rand() % (FSINMAX + 1); height = (int **) mallocm(2 * sizeof(int *)); for (i = 0; i < 2; i++) { height[i] = (int *) mallocm(sz_pixels); } memset(height[0], 0, sz_pixels); memset(height[1], 0, sz_pixels); scr_pbmp = create_bitmap(scr_w, scr_h); blit(pbmp, scr_pbmp, 0, 0, 0, 0, scr_w, scr_h); bmp_buf = mallocm(npixels * sizeof(uchr)); scr_buf = (uchr*) scr_pbmp->dat; /* scr_pbmp->line[0] */ memcpy(bmp_buf, scr_buf, npixels); /* bmp_buf remains unchanged */ lastkey = K_d; } /*---------------------------------------------------------------------------*/ void water_raindrops() { x = rand() % (scr_w - 2) + 1; y = rand() % (scr_h - 2) + 1; height[hpage][y * scr_w + x] = rand() % (distance << 2); } /*---------------------------------------------------------------------------*/ void water_restore() { keysee_insert(); } /*---------------------------------------------------------------------------*/ void water_splashes() { if (rand() % 20 == 0) { if (material == 0) { heightblob(-1, -1, size, distance, hpage); } else { sineblob(-1, -1, size, -distance, hpage); } } } /*---------------------------------------------------------------------------*/ void water_surfer() { x = (scr_w / 2) + ((((fsina((xang * 65) >> 8) >> 8) * (fsina((xang * 349) >> 8) >> 8)) * ((scr_w - 8) / 2)) >> 16); y = (scr_h / 2) + ((((fsina((yang * 377) >> 8) >> 8) * (fsina((yang * 84) >> 8) >> 8)) * ((scr_h - 8) / 2)) >> 16); xang += 13; yang += 12; if (material == 0) { offset = (oy + y) / 2 * scr_w + (ox + x) / 2; height[hpage][offset] = distance; height[hpage][offset + 1] = height[hpage][offset - 1] = height[hpage][offset + scr_w] = height[hpage][offset - scr_w] = distance >> 1; offset = y * scr_w + x; height[hpage][offset] = distance << 1; height[hpage][offset + 1] = height[hpage][offset - 1] = height[hpage][offset + scr_w] = height[hpage][offset - scr_w] = distance; } else { sineblob((ox + x) / 2, (oy + y) / 2, 3, -1200, hpage); sineblob(x, y, 4, -2000, hpage); } ox = x; oy = y; } /*---------------------------------------------------------------------------*/ void water_swirling() { x = (scr_w / 2) + (((fcosa(swirlangle)) * (25)) >> 16); y = (scr_h / 2) + (((fsina(swirlangle)) * (25)) >> 16); swirlangle += 50; if (material == 0) { heightblob(x, y, size / 3, distance, hpage); } else { warpblob(x, y, size, distance, hpage); } } /*---------------------------------------------------------------------------*/ void water_test1() { warpblob(x, y, size, distance, hpage); } /*---------------------------------------------------------------------------*/ void water_test2() { sineblob(x, y, size, distance, hpage); } /*---------------------------------------------------------------------------*/ void water_test3() { heightblob(x, y, size, distance, hpage); }