You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

201 lines
5.5 KiB

  1. /*
  2. * cacaball metaballs effect for libcaca
  3. * Copyright (c) 2003-2004 Jean-Yves Lamoureux <jylam@lnxscene.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. #include "config.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <math.h>
  18. #ifndef M_PI
  19. # define M_PI 3.14159265358979323846
  20. #endif
  21. #include "cucul.h"
  22. #include "caca.h"
  23. /* Virtual buffer size */
  24. #define XSIZ 256
  25. #define YSIZ 256
  26. #define METASIZE 100
  27. #define METABALLS 16
  28. /* Colour index where to crop balls */
  29. #define CROPBALL 160
  30. static void create_ball(void);
  31. static void draw_ball(unsigned int, unsigned int);
  32. static unsigned char pixels[XSIZ * YSIZ];
  33. static unsigned char metaball[METASIZE * METASIZE];
  34. int main(int argc, char **argv)
  35. {
  36. cucul_t *qq; caca_t *kk;
  37. unsigned int r[256], g[256], b[256], a[256];
  38. float d[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
  39. unsigned int x[METABALLS], y[METABALLS];
  40. struct cucul_bitmap *cucul_bitmap;
  41. float i = 10.0, j = 17.0, k = 11.0;
  42. int p, frame = 0, pause = 0;
  43. qq = cucul_init();
  44. if(!qq)
  45. return 1;
  46. kk = caca_attach(qq);
  47. if(!kk)
  48. return 1;
  49. caca_set_delay(kk, 20000);
  50. /* Make the palette eatable by libcaca */
  51. for(p = 0; p < 256; p++)
  52. r[p] = g[p] = b[p] = a[p] = 0x0;
  53. r[255] = g[255] = b[255] = 0xfff;
  54. /* Create a libcucul bitmap smaller than our pixel buffer, so that we
  55. * display only the interesting part of it */
  56. cucul_bitmap = cucul_create_bitmap(qq, 8, XSIZ - METASIZE, YSIZ - METASIZE,
  57. XSIZ, 0, 0, 0, 0);
  58. /* Generate ball sprite */
  59. create_ball();
  60. for(p = 0; p < METABALLS; p++)
  61. {
  62. d[p] = cucul_rand(0, 100);
  63. di[p] = (float)cucul_rand(500, 4000) / 6000.0;
  64. dj[p] = (float)cucul_rand(500, 4000) / 6000.0;
  65. dk[p] = (float)cucul_rand(500, 4000) / 6000.0;
  66. }
  67. /* Go ! */
  68. for(;;)
  69. {
  70. switch(caca_get_event(kk, CACA_EVENT_KEY_PRESS))
  71. {
  72. case CACA_EVENT_KEY_PRESS | CACA_KEY_ESCAPE: goto end;
  73. case CACA_EVENT_KEY_PRESS | ' ': pause = !pause;
  74. }
  75. if(pause)
  76. goto paused;
  77. frame++;
  78. /* Crop the palette */
  79. for(p = CROPBALL; p < 255; p++)
  80. {
  81. int t1, t2, t3;
  82. t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
  83. t2 = p < 0xe0 ? 0 : (p - 0xe0) * 0x80;
  84. t3 = p < 0x40 ? p * 0x40 : 0xfff;
  85. r[p] = (1.0 + sin((double)frame * M_PI / 60)) * t1 / 4
  86. + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t2 / 4
  87. + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t3 / 4;
  88. g[p] = (1.0 + sin((double)frame * M_PI / 60)) * t2 / 4
  89. + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t3 / 4
  90. + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t1 / 4;
  91. b[p] = (1.0 + sin((double)frame * M_PI / 60)) * t3 / 4
  92. + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t1 / 4
  93. + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t2 / 4;
  94. }
  95. /* Set the palette */
  96. cucul_set_bitmap_palette(qq, cucul_bitmap, r, g, b, a);
  97. /* Silly paths for our balls */
  98. for(p = 0; p < METABALLS; p++)
  99. {
  100. float u = di[p] * i + dj[p] * j + dk[p] * sin(di[p] * k);
  101. float v = d[p] + di[p] * j + dj[p] * k + dk[p] * sin(dk[p] * i);
  102. u = sin(i + u * 2.1) * (1.0 + sin(u));
  103. v = sin(j + v * 1.9) * (1.0 + sin(v));
  104. x[p] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
  105. y[p] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
  106. }
  107. i += 0.011;
  108. j += 0.017;
  109. k += 0.019;
  110. memset(pixels, 0, XSIZ * YSIZ);
  111. /* Here is all the trick. Maybe if you're that
  112. * clever you'll understand. */
  113. for(p = 0; p < METABALLS; p++)
  114. draw_ball(x[p], y[p]);
  115. paused:
  116. /* Draw our virtual buffer to screen, letting libcucul resize it */
  117. cucul_draw_bitmap(qq, 0, 0,
  118. cucul_get_width(qq) - 1, cucul_get_height(qq) - 1,
  119. cucul_bitmap, pixels + (METASIZE / 2) * (1 + XSIZ));
  120. caca_refresh(kk);
  121. }
  122. /* End, bye folks */
  123. end:
  124. cucul_free_bitmap(qq, cucul_bitmap);
  125. caca_detach(kk);
  126. cucul_end(qq);
  127. return 0;
  128. }
  129. /* Generate ball sprite
  130. * You should read the comments, I already wrote that before ... */
  131. static void create_ball(void)
  132. {
  133. int x, y;
  134. float distance;
  135. for(y = 0; y < METASIZE; y++)
  136. for(x = 0; x < METASIZE; x++)
  137. {
  138. distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
  139. + ((METASIZE/2) - y) * ((METASIZE/2) - y);
  140. distance = sqrt(distance) * 64 / METASIZE;
  141. metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
  142. }
  143. }
  144. /* You missed the trick ? */
  145. static void draw_ball(unsigned int bx, unsigned int by)
  146. {
  147. unsigned int color;
  148. unsigned int i, e = 0;
  149. unsigned int b = (by * XSIZ) + bx;
  150. for(i = 0; i < METASIZE * METASIZE; i++)
  151. {
  152. color = pixels[b] + metaball[i];
  153. if(color > 255)
  154. color = 255;
  155. pixels[b] = color;
  156. if(e == METASIZE)
  157. {
  158. e = 0;
  159. b += XSIZ - METASIZE;
  160. }
  161. b++;
  162. e++;
  163. }
  164. }