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.

преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 17 години
преди 17 години
преди 17 години
преди 17 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. /*
  2. * cacademo various demo effects for libcaca
  3. * Copyright (c) 1998 Michele Bini <mibin@tin.it>
  4. * 2003-2006 Jean-Yves Lamoureux <jylam@lnxscene.org>
  5. * 2004-2006 Sam Hocevar <sam@zoy.org>
  6. * All Rights Reserved
  7. *
  8. * $Id$
  9. *
  10. * This program is free software. It comes without any warranty, to
  11. * the extent permitted by applicable law. You can redistribute it
  12. * and/or modify it under the terms of the Do What The Fuck You Want
  13. * To Public License, Version 2, as published by Sam Hocevar. See
  14. * http://sam.zoy.org/wtfpl/COPYING for more details.
  15. */
  16. #include "config.h"
  17. #include "common.h"
  18. #if !defined(__KERNEL__)
  19. # include <stdio.h>
  20. # include <stdlib.h>
  21. # include <string.h>
  22. # include <math.h>
  23. # ifndef M_PI
  24. # define M_PI 3.14159265358979323846
  25. # endif
  26. #endif
  27. #include "cucul.h"
  28. #include "caca.h"
  29. enum action { PREPARE, INIT, UPDATE, RENDER, FREE };
  30. void transition(cucul_canvas_t *, int, int);
  31. void plasma(enum action, cucul_canvas_t *);
  32. void metaballs(enum action, cucul_canvas_t *);
  33. void moire(enum action, cucul_canvas_t *);
  34. void langton(enum action, cucul_canvas_t *);
  35. void matrix(enum action, cucul_canvas_t *);
  36. void rotozoom(enum action, cucul_canvas_t *);
  37. void (*fn[])(enum action, cucul_canvas_t *) =
  38. {
  39. plasma,
  40. metaballs,
  41. moire,
  42. /*langton,*/
  43. matrix,
  44. rotozoom,
  45. };
  46. #define DEMOS (sizeof(fn)/sizeof(*fn))
  47. #define DEMO_FRAMES cucul_rand(500, 1000)
  48. #define TRANSITION_FRAMES 40
  49. #define TRANSITION_COUNT 3
  50. #define TRANSITION_CIRCLE 0
  51. #define TRANSITION_STAR 1
  52. #define TRANSITION_SQUARE 2
  53. /* Common macros for dither-based demos */
  54. #define XSIZ 256
  55. #define YSIZ 256
  56. /* Global variables */
  57. static int frame = 0;
  58. int main(int argc, char **argv)
  59. {
  60. static caca_display_t *dp;
  61. static cucul_canvas_t *frontcv, *backcv, *mask;
  62. int demo, next = -1, pause = 0, next_transition = DEMO_FRAMES;
  63. unsigned int i;
  64. int tmode = cucul_rand(0, TRANSITION_COUNT);
  65. /* Set up two canvases, a mask, and attach a display to the front one */
  66. frontcv = cucul_create_canvas(0, 0);
  67. backcv = cucul_create_canvas(0, 0);
  68. mask = cucul_create_canvas(0, 0);
  69. dp = caca_create_display(frontcv);
  70. if(!dp)
  71. return 1;
  72. cucul_set_canvas_size(backcv, cucul_get_canvas_width(frontcv),
  73. cucul_get_canvas_height(frontcv));
  74. cucul_set_canvas_size(mask, cucul_get_canvas_width(frontcv),
  75. cucul_get_canvas_height(frontcv));
  76. caca_set_display_time(dp, 20000);
  77. /* Initialise all demos' lookup tables */
  78. for(i = 0; i < DEMOS; i++)
  79. fn[i](PREPARE, frontcv);
  80. /* Choose a demo at random */
  81. demo = cucul_rand(0, DEMOS);
  82. fn[demo](INIT, frontcv);
  83. for(;;)
  84. {
  85. /* Handle events */
  86. caca_event_t ev;
  87. while(caca_get_event(dp, CACA_EVENT_KEY_PRESS
  88. | CACA_EVENT_QUIT, &ev, 0))
  89. {
  90. if(ev.type == CACA_EVENT_QUIT)
  91. goto end;
  92. switch(ev.data.key.ch)
  93. {
  94. case CACA_KEY_ESCAPE:
  95. case CACA_KEY_CTRL_C:
  96. case CACA_KEY_CTRL_Z:
  97. goto end;
  98. case ' ':
  99. pause = !pause;
  100. break;
  101. case '\r':
  102. if(next == -1)
  103. next_transition = frame;
  104. break;
  105. }
  106. }
  107. /* Resize the spare canvas, just in case the main one changed */
  108. cucul_set_canvas_size(backcv, cucul_get_canvas_width(frontcv),
  109. cucul_get_canvas_height(frontcv));
  110. cucul_set_canvas_size(mask, cucul_get_canvas_width(frontcv),
  111. cucul_get_canvas_height(frontcv));
  112. if(pause)
  113. goto paused;
  114. /* Update demo's data */
  115. fn[demo](UPDATE, frontcv);
  116. /* Handle transitions */
  117. if(frame == next_transition)
  118. {
  119. next = cucul_rand(0, DEMOS);
  120. if(next == demo)
  121. next = (next + 1) % DEMOS;
  122. fn[next](INIT, backcv);
  123. }
  124. else if(frame == next_transition + TRANSITION_FRAMES)
  125. {
  126. fn[demo](FREE, frontcv);
  127. demo = next;
  128. next = -1;
  129. next_transition = frame + DEMO_FRAMES;
  130. tmode = cucul_rand(0, TRANSITION_COUNT);
  131. }
  132. if(next != -1)
  133. fn[next](UPDATE, backcv);
  134. frame++;
  135. paused:
  136. /* Render main demo's canvas */
  137. fn[demo](RENDER, frontcv);
  138. /* If a transition is on its way, render it */
  139. if(next != -1)
  140. {
  141. fn[next](RENDER, backcv);
  142. cucul_set_color_ansi(mask, CUCUL_LIGHTGRAY, CUCUL_BLACK);
  143. cucul_clear_canvas(mask);
  144. cucul_set_color_ansi(mask, CUCUL_WHITE, CUCUL_WHITE);
  145. transition(mask, tmode,
  146. 100 * (frame - next_transition) / TRANSITION_FRAMES);
  147. cucul_blit(frontcv, 0, 0, backcv, mask);
  148. }
  149. cucul_set_color_ansi(frontcv, CUCUL_WHITE, CUCUL_BLUE);
  150. if(frame < 100)
  151. cucul_put_str(frontcv, cucul_get_canvas_width(frontcv) - 30,
  152. cucul_get_canvas_height(frontcv) - 2,
  153. " -=[ Powered by libcaca ]=- ");
  154. caca_refresh_display(dp);
  155. }
  156. end:
  157. if(next != -1)
  158. fn[next](FREE, frontcv);
  159. fn[demo](FREE, frontcv);
  160. caca_free_display(dp);
  161. cucul_free_canvas(mask);
  162. cucul_free_canvas(backcv);
  163. cucul_free_canvas(frontcv);
  164. return 0;
  165. }
  166. /* Transitions */
  167. void transition(cucul_canvas_t *mask, int tmode, int completed)
  168. {
  169. static float const star[] =
  170. {
  171. 0.000000, -1.000000,
  172. 0.308000, -0.349000,
  173. 0.992000, -0.244000,
  174. 0.500000, 0.266000,
  175. 0.632000, 0.998000,
  176. 0.008000, 0.659000,
  177. -0.601000, 0.995000,
  178. -0.496000, 0.275000,
  179. -0.997000, -0.244000,
  180. -0.313000, -0.349000
  181. };
  182. static float star_rot[sizeof(star)/sizeof(*star)];
  183. static float const square[] =
  184. {
  185. -1, -1,
  186. 1, -1,
  187. 1, 1,
  188. -1, 1
  189. };
  190. static float square_rot[sizeof(square)/sizeof(*square)];
  191. float mulx = 0.0075f * completed * cucul_get_canvas_width(mask);
  192. float muly = 0.0075f * completed * cucul_get_canvas_height(mask);
  193. int w2 = cucul_get_canvas_width(mask) / 2;
  194. int h2 = cucul_get_canvas_height(mask) / 2;
  195. float angle = (0.0075f * completed * 360) * 3.14 / 180, x, y;
  196. unsigned int i;
  197. switch(tmode)
  198. {
  199. case TRANSITION_SQUARE:
  200. /* Compute rotated coordinates */
  201. for(i = 0; i < (sizeof(square) / sizeof(*square)) / 2; i++)
  202. {
  203. x = square[i * 2];
  204. y = square[i * 2 + 1];
  205. square_rot[i * 2] = x * cos(angle) - y * sin(angle);
  206. square_rot[i * 2 + 1] = y * cos(angle) + x * sin(angle);
  207. }
  208. mulx *= 1.8;
  209. muly *= 1.8;
  210. cucul_fill_triangle(mask,
  211. square_rot[0*2] * mulx + w2, square_rot[0*2+1] * muly + h2, \
  212. square_rot[1*2] * mulx + w2, square_rot[1*2+1] * muly + h2, \
  213. square_rot[2*2] * mulx + w2, square_rot[2*2+1] * muly + h2, '#');
  214. cucul_fill_triangle(mask,
  215. square_rot[0*2] * mulx + w2, square_rot[0*2+1] * muly + h2, \
  216. square_rot[2*2] * mulx + w2, square_rot[2*2+1] * muly + h2, \
  217. square_rot[3*2] * mulx + w2, square_rot[3*2+1] * muly + h2, '#');
  218. break;
  219. case TRANSITION_STAR:
  220. /* Compute rotated coordinates */
  221. for(i = 0; i < (sizeof(star) / sizeof(*star)) / 2; i++)
  222. {
  223. x = star[i * 2];
  224. y = star[i * 2 + 1];
  225. star_rot[i * 2] = x * cos(angle) - y * sin(angle);
  226. star_rot[i * 2 + 1] = y * cos(angle) + x * sin(angle);
  227. }
  228. mulx *= 1.8;
  229. muly *= 1.8;
  230. #define DO_TRI(a, b, c) \
  231. cucul_fill_triangle(mask, \
  232. star_rot[(a)*2] * mulx + w2, star_rot[(a)*2+1] * muly + h2, \
  233. star_rot[(b)*2] * mulx + w2, star_rot[(b)*2+1] * muly + h2, \
  234. star_rot[(c)*2] * mulx + w2, star_rot[(c)*2+1] * muly + h2, '#')
  235. DO_TRI(0, 1, 9);
  236. DO_TRI(1, 2, 3);
  237. DO_TRI(3, 4, 5);
  238. DO_TRI(5, 6, 7);
  239. DO_TRI(7, 8, 9);
  240. DO_TRI(9, 1, 5);
  241. DO_TRI(9, 5, 7);
  242. DO_TRI(1, 3, 5);
  243. break;
  244. case TRANSITION_CIRCLE:
  245. cucul_fill_ellipse(mask, w2, h2, mulx, muly, '#');
  246. break;
  247. }
  248. }
  249. /* The plasma effect */
  250. #define TABLEX (XSIZ * 2)
  251. #define TABLEY (YSIZ * 2)
  252. static uint8_t table[TABLEX * TABLEY];
  253. static void do_plasma(uint8_t *,
  254. double, double, double, double, double, double);
  255. void plasma(enum action action, cucul_canvas_t *cv)
  256. {
  257. static cucul_dither_t *dither;
  258. static uint8_t *screen;
  259. static unsigned int red[256], green[256], blue[256], alpha[256];
  260. static double r[3], R[6];
  261. int i, x, y;
  262. switch(action)
  263. {
  264. case PREPARE:
  265. /* Fill various tables */
  266. for(i = 0 ; i < 256; i++)
  267. red[i] = green[i] = blue[i] = alpha[i] = 0;
  268. for(i = 0; i < 3; i++)
  269. r[i] = (double)(cucul_rand(1, 1000)) / 60000 * M_PI;
  270. for(i = 0; i < 6; i++)
  271. R[i] = (double)(cucul_rand(1, 1000)) / 10000;
  272. for(y = 0 ; y < TABLEY ; y++)
  273. for(x = 0 ; x < TABLEX ; x++)
  274. {
  275. double tmp = (((double)((x - (TABLEX / 2)) * (x - (TABLEX / 2))
  276. + (y - (TABLEX / 2)) * (y - (TABLEX / 2))))
  277. * (M_PI / (TABLEX * TABLEX + TABLEY * TABLEY)));
  278. table[x + y * TABLEX] = (1.0 + sin(12.0 * sqrt(tmp))) * 256 / 6;
  279. }
  280. break;
  281. case INIT:
  282. screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
  283. dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
  284. break;
  285. case UPDATE:
  286. for(i = 0 ; i < 256; i++)
  287. {
  288. double z = ((double)i) / 256 * 6 * M_PI;
  289. red[i] = (1.0 + sin(z + r[1] * frame)) / 2 * 0xfff;
  290. blue[i] = (1.0 + cos(z + r[0] * (frame + 100))) / 2 * 0xfff;
  291. green[i] = (1.0 + cos(z + r[2] * (frame + 200))) / 2 * 0xfff;
  292. }
  293. /* Set the palette */
  294. cucul_set_dither_palette(dither, red, green, blue, alpha);
  295. do_plasma(screen,
  296. (1.0 + sin(((double)frame) * R[0])) / 2,
  297. (1.0 + sin(((double)frame) * R[1])) / 2,
  298. (1.0 + sin(((double)frame) * R[2])) / 2,
  299. (1.0 + sin(((double)frame) * R[3])) / 2,
  300. (1.0 + sin(((double)frame) * R[4])) / 2,
  301. (1.0 + sin(((double)frame) * R[5])) / 2);
  302. break;
  303. case RENDER:
  304. cucul_dither_bitmap(cv, 0, 0,
  305. cucul_get_canvas_width(cv),
  306. cucul_get_canvas_height(cv),
  307. dither, screen);
  308. break;
  309. case FREE:
  310. free(screen);
  311. cucul_free_dither(dither);
  312. break;
  313. }
  314. }
  315. static void do_plasma(uint8_t *pixels, double x_1, double y_1,
  316. double x_2, double y_2, double x_3, double y_3)
  317. {
  318. unsigned int X1 = x_1 * (TABLEX / 2),
  319. Y1 = y_1 * (TABLEY / 2),
  320. X2 = x_2 * (TABLEX / 2),
  321. Y2 = y_2 * (TABLEY / 2),
  322. X3 = x_3 * (TABLEX / 2),
  323. Y3 = y_3 * (TABLEY / 2);
  324. unsigned int y;
  325. uint8_t * t1 = table + X1 + Y1 * TABLEX,
  326. * t2 = table + X2 + Y2 * TABLEX,
  327. * t3 = table + X3 + Y3 * TABLEX;
  328. for(y = 0; y < YSIZ; y++)
  329. {
  330. unsigned int x;
  331. uint8_t * tmp = pixels + y * YSIZ;
  332. unsigned int ty = y * TABLEX, tmax = ty + XSIZ;
  333. for(x = 0; ty < tmax; ty++, tmp++)
  334. tmp[0] = t1[ty] + t2[ty] + t3[ty];
  335. }
  336. }
  337. /* The metaball effect */
  338. #define METASIZE (XSIZ/2)
  339. #define METABALLS 12
  340. #define CROPBALL 200 /* Colour index where to crop balls */
  341. static uint8_t metaball[METASIZE * METASIZE];
  342. static void create_ball(void);
  343. static void draw_ball(uint8_t *, unsigned int, unsigned int);
  344. void metaballs(enum action action, cucul_canvas_t *cv)
  345. {
  346. static cucul_dither_t *cucul_dither;
  347. static uint8_t *screen;
  348. static unsigned int r[256], g[256], b[256], a[256];
  349. static float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
  350. static unsigned int x[METABALLS], y[METABALLS];
  351. static float i = 10.0, j = 17.0, k = 11.0;
  352. static double offset[360 + 80];
  353. static unsigned int angleoff;
  354. int n, angle;
  355. switch(action)
  356. {
  357. case PREPARE:
  358. /* Make the palette eatable by libcaca */
  359. for(n = 0; n < 256; n++)
  360. r[n] = g[n] = b[n] = a[n] = 0x0;
  361. r[255] = g[255] = b[255] = 0xfff;
  362. /* Generate ball sprite */
  363. create_ball();
  364. for(n = 0; n < METABALLS; n++)
  365. {
  366. dd[n] = cucul_rand(0, 100);
  367. di[n] = (float)cucul_rand(500, 4000) / 6000.0;
  368. dj[n] = (float)cucul_rand(500, 4000) / 6000.0;
  369. dk[n] = (float)cucul_rand(500, 4000) / 6000.0;
  370. }
  371. angleoff = cucul_rand(0, 360);
  372. for(n = 0; n < 360 + 80; n++)
  373. offset[n] = 1.0 + sin((double)(n * M_PI / 60));
  374. break;
  375. case INIT:
  376. screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
  377. /* Create a libcucul dither smaller than our pixel buffer, so that we
  378. * display only the interesting part of it */
  379. cucul_dither = cucul_create_dither(8, XSIZ - METASIZE, YSIZ - METASIZE,
  380. XSIZ, 0, 0, 0, 0);
  381. break;
  382. case UPDATE:
  383. angle = (frame + angleoff) % 360;
  384. /* Crop the palette */
  385. for(n = CROPBALL; n < 255; n++)
  386. {
  387. int t1, t2, t3;
  388. double c1 = offset[angle];
  389. double c2 = offset[angle + 40];
  390. double c3 = offset[angle + 80];
  391. t1 = n < 0x40 ? 0 : n < 0xc0 ? (n - 0x40) * 0x20 : 0xfff;
  392. t2 = n < 0xe0 ? 0 : (n - 0xe0) * 0x80;
  393. t3 = n < 0x40 ? n * 0x40 : 0xfff;
  394. r[n] = (c1 * t1 + c2 * t2 + c3 * t3) / 4;
  395. g[n] = (c1 * t2 + c2 * t3 + c3 * t1) / 4;
  396. b[n] = (c1 * t3 + c2 * t1 + c3 * t2) / 4;
  397. }
  398. /* Set the palette */
  399. cucul_set_dither_palette(cucul_dither, r, g, b, a);
  400. /* Silly paths for our balls */
  401. for(n = 0; n < METABALLS; n++)
  402. {
  403. float u = di[n] * i + dj[n] * j + dk[n] * sin(di[n] * k);
  404. float v = dd[n] + di[n] * j + dj[n] * k + dk[n] * sin(dk[n] * i);
  405. u = sin(i + u * 2.1) * (1.0 + sin(u));
  406. v = sin(j + v * 1.9) * (1.0 + sin(v));
  407. x[n] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
  408. y[n] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
  409. }
  410. i += 0.011;
  411. j += 0.017;
  412. k += 0.019;
  413. memset(screen, 0, XSIZ * YSIZ);
  414. for(n = 0; n < METABALLS; n++)
  415. draw_ball(screen, x[n], y[n]);
  416. break;
  417. case RENDER:
  418. cucul_dither_bitmap(cv, 0, 0,
  419. cucul_get_canvas_width(cv),
  420. cucul_get_canvas_height(cv),
  421. cucul_dither, screen + (METASIZE / 2) * (1 + XSIZ));
  422. break;
  423. case FREE:
  424. free(screen);
  425. cucul_free_dither(cucul_dither);
  426. break;
  427. }
  428. }
  429. static void create_ball(void)
  430. {
  431. int x, y;
  432. float distance;
  433. for(y = 0; y < METASIZE; y++)
  434. for(x = 0; x < METASIZE; x++)
  435. {
  436. distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
  437. + ((METASIZE/2) - y) * ((METASIZE/2) - y);
  438. distance = sqrt(distance) * 64 / METASIZE;
  439. metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
  440. }
  441. }
  442. static void draw_ball(uint8_t *screen, unsigned int bx, unsigned int by)
  443. {
  444. unsigned int color;
  445. unsigned int i, e = 0;
  446. unsigned int b = (by * XSIZ) + bx;
  447. for(i = 0; i < METASIZE * METASIZE; i++)
  448. {
  449. color = screen[b] + metaball[i];
  450. if(color > 255)
  451. color = 255;
  452. screen[b] = color;
  453. if(e == METASIZE)
  454. {
  455. e = 0;
  456. b += XSIZ - METASIZE;
  457. }
  458. b++;
  459. e++;
  460. }
  461. }
  462. /* The moir effect */
  463. #define DISCSIZ (XSIZ*2)
  464. #define DISCTHICKNESS (XSIZ*15/40)
  465. static uint8_t disc[DISCSIZ * DISCSIZ];
  466. static void put_disc(uint8_t *, int, int);
  467. static void draw_line(int, int, char);
  468. void moire(enum action action, cucul_canvas_t *cv)
  469. {
  470. static cucul_dither_t *dither;
  471. static uint8_t *screen;
  472. static float d[6];
  473. static unsigned int red[256], green[256], blue[256], alpha[256];
  474. int i, x, y;
  475. switch(action)
  476. {
  477. case PREPARE:
  478. /* Fill various tables */
  479. for(i = 0 ; i < 256; i++)
  480. red[i] = green[i] = blue[i] = alpha[i] = 0;
  481. for(i = 0; i < 6; i++)
  482. d[i] = ((float)cucul_rand(50, 70)) / 1000.0;
  483. red[0] = green[0] = blue[0] = 0x777;
  484. red[1] = green[1] = blue[1] = 0xfff;
  485. /* Fill the circle */
  486. for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS)
  487. {
  488. int t, dx, dy;
  489. for(t = 0, dx = 0, dy = i; dx <= dy; dx++)
  490. {
  491. draw_line(dx / 3, dy / 3, (i / DISCTHICKNESS) % 2);
  492. draw_line(dy / 3, dx / 3, (i / DISCTHICKNESS) % 2);
  493. t += t > 0 ? dx - dy-- : dx;
  494. }
  495. }
  496. break;
  497. case INIT:
  498. screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
  499. dither = cucul_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
  500. break;
  501. case UPDATE:
  502. memset(screen, 0, XSIZ * YSIZ);
  503. /* Set the palette */
  504. red[0] = 0.5 * (1 + sin(d[0] * (frame + 1000))) * 0xfff;
  505. green[0] = 0.5 * (1 + cos(d[1] * frame)) * 0xfff;
  506. blue[0] = 0.5 * (1 + cos(d[2] * (frame + 3000))) * 0xfff;
  507. red[1] = 0.5 * (1 + sin(d[3] * (frame + 2000))) * 0xfff;
  508. green[1] = 0.5 * (1 + cos(d[4] * frame + 5.0)) * 0xfff;
  509. blue[1] = 0.5 * (1 + cos(d[5] * (frame + 4000))) * 0xfff;
  510. cucul_set_dither_palette(dither, red, green, blue, alpha);
  511. /* Draw circles */
  512. x = cos(d[0] * (frame + 1000)) * 128.0 + (XSIZ / 2);
  513. y = sin(0.11 * frame) * 128.0 + (YSIZ / 2);
  514. put_disc(screen, x, y);
  515. x = cos(0.13 * frame + 2.0) * 64.0 + (XSIZ / 2);
  516. y = sin(d[1] * (frame + 2000)) * 64.0 + (YSIZ / 2);
  517. put_disc(screen, x, y);
  518. break;
  519. case RENDER:
  520. cucul_dither_bitmap(cv, 0, 0,
  521. cucul_get_canvas_width(cv),
  522. cucul_get_canvas_height(cv),
  523. dither, screen);
  524. break;
  525. case FREE:
  526. free(screen);
  527. cucul_free_dither(dither);
  528. break;
  529. }
  530. }
  531. static void put_disc(uint8_t *screen, int x, int y)
  532. {
  533. char *src = ((char*)disc) + (DISCSIZ / 2 - x) + (DISCSIZ / 2 - y) * DISCSIZ;
  534. int i, j;
  535. for(j = 0; j < YSIZ; j++)
  536. for(i = 0; i < XSIZ; i++)
  537. {
  538. screen[i + XSIZ * j] ^= src[i + DISCSIZ * j];
  539. }
  540. }
  541. static void draw_line(int x, int y, char color)
  542. {
  543. if(x == 0 || y == 0 || y > DISCSIZ / 2)
  544. return;
  545. if(x > DISCSIZ / 2)
  546. x = DISCSIZ / 2;
  547. memset(disc + (DISCSIZ / 2) - x + DISCSIZ * ((DISCSIZ / 2) - y),
  548. color, 2 * x - 1);
  549. memset(disc + (DISCSIZ / 2) - x + DISCSIZ * ((DISCSIZ / 2) + y - 1),
  550. color, 2 * x - 1);
  551. }
  552. /* Langton ant effect */
  553. #define ANTS 15
  554. #define ITER 2
  555. void langton(enum action action, cucul_canvas_t *cv)
  556. {
  557. static char gradient[] =
  558. {
  559. ' ', ' ', '.', '.', ':', ':', 'x', 'x',
  560. 'X', 'X', '&', '&', 'W', 'W', '@', '@',
  561. };
  562. static int steps[][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
  563. static uint8_t *screen;
  564. static int width, height;
  565. static int ax[ANTS], ay[ANTS], dir[ANTS];
  566. int i, a, x, y;
  567. switch(action)
  568. {
  569. case PREPARE:
  570. width = cucul_get_canvas_width(cv);
  571. height = cucul_get_canvas_height(cv);
  572. for(i = 0; i < ANTS; i++)
  573. {
  574. ax[i] = cucul_rand(0, width);
  575. ay[i] = cucul_rand(0, height);
  576. dir[i] = cucul_rand(0, 4);
  577. }
  578. break;
  579. case INIT:
  580. screen = malloc(width * height);
  581. memset(screen, 0, width * height);
  582. break;
  583. case UPDATE:
  584. for(i = 0; i < ITER; i++)
  585. {
  586. for(x = 0; x < width * height; x++)
  587. {
  588. uint8_t p = screen[x];
  589. if((p & 0x0f) > 1)
  590. screen[x] = p - 1;
  591. }
  592. for(a = 0; a < ANTS; a++)
  593. {
  594. uint8_t p = screen[ax[a] + width * ay[a]];
  595. if(p & 0x0f)
  596. {
  597. dir[a] = (dir[a] + 1) % 4;
  598. screen[ax[a] + width * ay[a]] = a << 4;
  599. }
  600. else
  601. {
  602. dir[a] = (dir[a] + 3) % 4;
  603. screen[ax[a] + width * ay[a]] = (a << 4) | 0x0f;
  604. }
  605. ax[a] = (width + ax[a] + steps[dir[a]][0]) % width;
  606. ay[a] = (height + ay[a] + steps[dir[a]][1]) % height;
  607. }
  608. }
  609. break;
  610. case RENDER:
  611. for(y = 0; y < height; y++)
  612. {
  613. for(x = 0; x < width; x++)
  614. {
  615. uint8_t p = screen[x + width * y];
  616. if(p & 0x0f)
  617. cucul_set_color_ansi(cv, CUCUL_WHITE, p >> 4);
  618. else
  619. cucul_set_color_ansi(cv, CUCUL_BLACK, CUCUL_BLACK);
  620. cucul_put_char(cv, x, y, gradient[p & 0x0f]);
  621. }
  622. }
  623. break;
  624. case FREE:
  625. free(screen);
  626. break;
  627. }
  628. }
  629. /* Matrix effect */
  630. #define MAXDROPS 500
  631. #define MINLEN 15
  632. #define MAXLEN 30
  633. void matrix(enum action action, cucul_canvas_t *cv)
  634. {
  635. static struct drop
  636. {
  637. int x, y, speed, len;
  638. char str[MAXLEN];
  639. }
  640. drop[MAXDROPS];
  641. int w, h, i, j;
  642. switch(action)
  643. {
  644. case PREPARE:
  645. for(i = 0; i < MAXDROPS; i++)
  646. {
  647. drop[i].x = cucul_rand(0, 1000);
  648. drop[i].y = cucul_rand(0, 1000);
  649. drop[i].speed = 5 + cucul_rand(0, 30);
  650. drop[i].len = MINLEN + cucul_rand(0, (MAXLEN - MINLEN));
  651. for(j = 0; j < MAXLEN; j++)
  652. drop[i].str[j] = cucul_rand('0', 'z');
  653. }
  654. break;
  655. case INIT:
  656. break;
  657. case UPDATE:
  658. w = cucul_get_canvas_width(cv);
  659. h = cucul_get_canvas_height(cv);
  660. for(i = 0; i < MAXDROPS && i < (w * h / 32); i++)
  661. {
  662. drop[i].y += drop[i].speed;
  663. if(drop[i].y > 1000)
  664. {
  665. drop[i].y -= 1000;
  666. drop[i].x = cucul_rand(0, 1000);
  667. }
  668. }
  669. break;
  670. case RENDER:
  671. w = cucul_get_canvas_width(cv);
  672. h = cucul_get_canvas_height(cv);
  673. cucul_set_color_ansi(cv, CUCUL_BLACK, CUCUL_BLACK);
  674. cucul_clear_canvas(cv);
  675. for(i = 0; i < MAXDROPS && i < (w * h / 32); i++)
  676. {
  677. int x, y;
  678. x = drop[i].x * w / 1000 / 2 * 2;
  679. y = drop[i].y * (h + MAXLEN) / 1000;
  680. for(j = 0; j < drop[i].len; j++)
  681. {
  682. unsigned int fg;
  683. if(j < 2)
  684. fg = CUCUL_WHITE;
  685. else if(j < drop[i].len / 4)
  686. fg = CUCUL_LIGHTGREEN;
  687. else if(j < drop[i].len * 4 / 5)
  688. fg = CUCUL_GREEN;
  689. else
  690. fg = CUCUL_DARKGRAY;
  691. cucul_set_color_ansi(cv, fg, CUCUL_BLACK);
  692. cucul_put_char(cv, x, y - j,
  693. drop[i].str[(y - j) % drop[i].len]);
  694. }
  695. }
  696. break;
  697. case FREE:
  698. break;
  699. }
  700. }
  701. #define TEXTURE_SIZE 256
  702. #define TABLE_SIZE 65536
  703. /* 24:8 Fixed point stuff */
  704. #define PRECISION 8
  705. #define FMUL(a, b) (((a)*(b))>>PRECISION)
  706. #define TOFIX(d) ((int)( (d)*(double)(1<<PRECISION) ))
  707. #define TOINT(a) (a>>PRECISION);
  708. #include "texture.h"
  709. void rotozoom(enum action action, cucul_canvas_t *canvas)
  710. {
  711. static cucul_dither_t *dither;
  712. static unsigned int *screen, *save;
  713. static int alphaF, tF;
  714. int scaleF;
  715. static int *texture;
  716. static int *cosTable;
  717. static int *sinTable;
  718. static int *yTable;
  719. /* register is quite a bad idea on CISC, but not on RISC */
  720. register unsigned int x, y;
  721. register unsigned int xxF, yyF, uF, vF, uF_, vF_;
  722. register unsigned int vu, vv;
  723. switch(action)
  724. {
  725. case INIT:
  726. screen = (unsigned int*)malloc(4 * XSIZ * YSIZ
  727. * sizeof(unsigned char));
  728. dither = cucul_create_dither(32,
  729. XSIZ, YSIZ,
  730. XSIZ*4,
  731. 0x00FF0000,
  732. 0x0000FF00,
  733. 0x000000FF,
  734. 0x00000000);
  735. save = screen;
  736. texture = (int*) textureByte;
  737. cosTable = malloc(TABLE_SIZE*sizeof(int));
  738. sinTable = malloc(TABLE_SIZE*sizeof(int));
  739. yTable = malloc(TEXTURE_SIZE*sizeof(int));
  740. for(x=0; x<TABLE_SIZE; x++) { /* Cos and Sin tables*/
  741. cosTable[x] = TOFIX(cos(x*(360.0f/(float)TABLE_SIZE)));
  742. sinTable[x] = TOFIX(sin(x*(360.0f/(float)TABLE_SIZE)));
  743. }
  744. for(x=0; x<TEXTURE_SIZE; x++) { /* start of lines offsets */
  745. yTable[x] = x*TEXTURE_SIZE;
  746. }
  747. break;
  748. case PREPARE:
  749. break;
  750. case UPDATE:
  751. alphaF += 4;
  752. tF += 3;
  753. scaleF = FMUL(sinTable[tF&0xFFFF], TOFIX(3)) + TOFIX(4);
  754. xxF = FMUL(cosTable[(alphaF)&0xFFFF], scaleF);
  755. yyF = FMUL(sinTable[(alphaF)&0xFFFF], scaleF);
  756. uF = vF = 0;
  757. uF_ = vF_ = 0;
  758. screen = save;
  759. y = YSIZ;
  760. while(y--) {
  761. x = XSIZ;
  762. while(x--) {
  763. uF+=xxF;
  764. vF+=yyF;
  765. vu = TOINT(uF);
  766. vv = TOINT(vF);
  767. vu&=0xFF; /* ARM doesn't like */
  768. vv&=0xFF; /* chars as local vars */
  769. *screen++ = texture[vu+yTable[vv]];
  770. }
  771. uF = uF_ -= yyF;
  772. vF = vF_ += xxF;
  773. }
  774. break;
  775. case RENDER:
  776. cucul_dither_bitmap(canvas, 0, 0,
  777. cucul_get_canvas_width(canvas),
  778. cucul_get_canvas_height(canvas),
  779. dither, save);
  780. break;
  781. case FREE:
  782. free(cosTable);
  783. free(sinTable);
  784. free(save);
  785. cucul_free_dither(dither);
  786. break;
  787. }
  788. }