source: libcaca/trunk/examples/demo.c @ 3495

Last change on this file since 3495 was 3493, checked in by Sam Hocevar, 11 years ago

Fix the old demo examples so that they don't refresh the screen twice
every frame, causing the mouse to flicker.

  • Property svn:keywords set to Id
File size: 16.4 KB
Line 
1/*
2 *  demo          demo for libcaca
3 *  Copyright (c) 2003-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: demo.c 3493 2009-05-21 20:55:07Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#if !defined(__KERNEL__)
18#   include <math.h>
19#   include <string.h>
20#   include <stdio.h>
21#endif
22
23#ifndef M_PI
24#   define M_PI 3.14159265358979323846
25#endif
26
27#include "caca.h"
28
29static void display_menu(void);
30
31static void demo_all(void);
32
33static void demo_dots(void);
34static void demo_lines(void);
35static void demo_boxes(void);
36static void demo_ellipses(void);
37static void demo_triangles(void);
38/*static void demo_sprites(void);*/
39static void demo_render(void);
40
41int bounds = 0;
42int outline = 0;
43int dithering = 0;
44#if 0
45caca_sprite_t *sprite = NULL;
46#endif
47
48caca_canvas_t *cv;
49caca_display_t *dp;
50
51int main(int argc, char **argv)
52{
53    void (*demo)(void) = NULL;
54    int quit = 0;
55
56    cv = caca_create_canvas(80, 24);
57    if(cv == NULL)
58    {
59        printf("Failed to create canvas\n");
60        return 1;
61    }
62
63    dp = caca_create_display(cv);
64    if(dp == NULL)
65    {
66        printf("Failed to create display\n");
67        return 1;
68    }
69
70    caca_set_display_time(dp, 40000);
71
72    /* Initialize data */
73#if 0
74    sprite = caca_load_sprite("caca.txt");
75    if(!sprite)
76        sprite = caca_load_sprite("examples/caca.txt");
77#endif
78
79    /* Disable cursor */
80    caca_set_mouse(dp, 0);
81
82    /* Main menu */
83    display_menu();
84    caca_refresh_display(dp);
85
86    /* Go ! */
87    while(!quit)
88    {
89        caca_event_t ev;
90        int menu = 0, mouse = 0, xmouse = 0, ymouse = 0;
91
92        while(caca_get_event(dp, CACA_EVENT_ANY, &ev, 0))
93        {
94            if(demo && (caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS))
95            {
96                menu = 1;
97                demo = NULL;
98            }
99            else if(caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS)
100            {
101                switch(caca_get_event_key_ch(&ev))
102                {
103                case 'q':
104                case 'Q':
105                case CACA_KEY_ESCAPE:
106                    demo = NULL;
107                    quit = 1;
108                    break;
109                case 'o':
110                case 'O':
111                    outline = (outline + 1) % 3;
112                    display_menu();
113                    caca_refresh_display(dp);
114                    break;
115                case 'b':
116                case 'B':
117                    bounds = (bounds + 1) % 2;
118                    display_menu();
119                    caca_refresh_display(dp);
120                    break;
121#if 0
122                case 'd':
123                case 'D':
124                    dithering = (dithering + 1) % 5;
125                    caca_set_feature(cv, dithering);
126                    display_menu();
127                    caca_refresh_display(dp);
128                    break;
129#endif
130                case 'f':
131                case 'F':
132                    demo = demo_all;
133                    break;
134                case '1':
135                    demo = demo_dots;
136                    break;
137                case '2':
138                    demo = demo_lines;
139                    break;
140                case '3':
141                    demo = demo_boxes;
142                    break;
143                case '4':
144                    demo = demo_triangles;
145                    break;
146                case '5':
147                    demo = demo_ellipses;
148                    break;
149#if 0
150                case 's':
151                case 'S':
152                    if(sprite)
153                        demo = demo_sprites;
154                    break;
155#endif
156                case 'r':
157                case 'R':
158                    demo = demo_render;
159                    break;
160                }
161
162                if(demo)
163                {
164                    caca_set_color_ansi(cv, CACA_LIGHTGRAY, CACA_BLACK);
165                    caca_clear_canvas(cv);
166                }
167            }
168            else if(caca_get_event_type(&ev) & CACA_EVENT_MOUSE_MOTION)
169            {
170                mouse = 1;
171                xmouse = caca_get_event_mouse_x(&ev);
172                ymouse = caca_get_event_mouse_y(&ev);
173            }
174            else if(caca_get_event_type(&ev) & CACA_EVENT_RESIZE)
175            {
176                mouse = 1; /* old hack */
177            }
178        }
179
180        if(menu || (mouse && !demo))
181        {
182            display_menu();
183            if(mouse && !demo)
184            {
185                caca_set_color_ansi(cv, CACA_RED, CACA_BLACK);
186                caca_put_str(cv, xmouse, ymouse,     ".");
187                caca_put_str(cv, xmouse, ymouse + 1, "|\\");
188            }
189            caca_refresh_display(dp);
190            mouse = menu = 0;
191        }
192        else if(demo)
193        {
194            demo();
195
196            caca_set_color_ansi(cv, CACA_LIGHTGRAY, CACA_BLACK);
197            caca_draw_thin_box(cv, 1, 1, caca_get_canvas_width(cv) - 2,
198                                          caca_get_canvas_height(cv) - 2);
199            caca_printf(cv, 4, 1, "[%i.%i fps]----",
200                         1000000 / caca_get_display_time(dp),
201                         (10000000 / caca_get_display_time(dp)) % 10);
202            caca_refresh_display(dp);
203        }
204    }
205
206    /* Clean up */
207#if 0
208    caca_free_sprite(sprite);
209#endif
210    caca_free_display(dp);
211    caca_free_canvas(cv);
212
213    return 0;
214}
215
216static void display_menu(void)
217{
218    int xo = caca_get_canvas_width(cv) - 2;
219    int yo = caca_get_canvas_height(cv) - 2;
220
221    caca_set_color_ansi(cv, CACA_LIGHTGRAY, CACA_BLACK);
222    caca_clear_canvas(cv);
223    caca_draw_thin_box(cv, 1, 1, xo, yo);
224
225    caca_put_str(cv, (xo - strlen("libcaca demo")) / 2, 3, "libcaca demo");
226    caca_put_str(cv, (xo - strlen("==============")) / 2, 4, "==============");
227
228    caca_put_str(cv, 4, 6, "demos:");
229    caca_put_str(cv, 4, 7, "'f': full");
230    caca_put_str(cv, 4, 8, "'1': dots");
231    caca_put_str(cv, 4, 9, "'2': lines");
232    caca_put_str(cv, 4, 10, "'3': boxes");
233    caca_put_str(cv, 4, 11, "'4': triangles");
234    caca_put_str(cv, 4, 12, "'5': ellipses");
235    caca_put_str(cv, 4, 13, "'c': colour");
236    caca_put_str(cv, 4, 14, "'r': render");
237#if 0
238    if(sprite)
239        caca_put_str(cv, 4, 15, "'s': sprites");
240#endif
241
242    caca_put_str(cv, 4, 16, "settings:");
243    caca_printf(cv, 4, 17, "'o': outline: %s",
244                 outline == 0 ? "none" : outline == 1 ? "solid" : "thin");
245    caca_printf(cv, 4, 18, "'b': drawing boundaries: %s",
246                 bounds == 0 ? "screen" : "infinite");
247    //caca_printf(cv, 4, 19, "'d': dithering (%s)",
248    //             caca_get_feature_name(dithering));
249
250    caca_put_str(cv, 4, yo - 2, "'q': quit");
251
252    //caca_refresh_display(dp);
253}
254
255static void demo_all(void)
256{
257    static int i = 0;
258
259    int j, xo, yo, xa, ya, xb, yb, xc, yc;
260
261    i++;
262
263    caca_set_color_ansi(cv, CACA_LIGHTGRAY, CACA_BLACK);
264    caca_clear_canvas(cv);
265
266    /* Draw the sun */
267    caca_set_color_ansi(cv, CACA_YELLOW, CACA_BLACK);
268    xo = caca_get_canvas_width(cv) / 4;
269    yo = caca_get_canvas_height(cv) / 4 + 5 * sin(0.03*i);
270
271    for(j = 0; j < 16; j++)
272    {
273        xa = xo - (30 + sin(0.03*i) * 8) * sin(0.03*i + M_PI*j/8);
274        ya = yo + (15 + sin(0.03*i) * 4) * cos(0.03*i + M_PI*j/8);
275        caca_draw_thin_line(cv, xo, yo, xa, ya);
276    }
277
278    j = 15 + sin(0.03*i) * 8;
279    caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK);
280    caca_fill_ellipse(cv, xo, yo, j, j / 2, '#');
281    caca_set_color_ansi(cv, CACA_YELLOW, CACA_BLACK);
282    caca_draw_ellipse(cv, xo, yo, j, j / 2, '#');
283
284    /* Draw the pyramid */
285    xo = caca_get_canvas_width(cv) * 5 / 8;
286    yo = 2;
287
288    xa = caca_get_canvas_width(cv) / 8 + sin(0.03*i) * 5;
289    ya = caca_get_canvas_height(cv) / 2 + cos(0.03*i) * 5;
290
291    xb = caca_get_canvas_width(cv) - 10 - cos(0.02*i) * 10;
292    yb = caca_get_canvas_height(cv) * 3 / 4 - 5 + sin(0.02*i) * 5;
293
294    xc = caca_get_canvas_width(cv) / 4 - sin(0.02*i) * 5;
295    yc = caca_get_canvas_height(cv) * 3 / 4 + cos(0.02*i) * 5;
296
297    caca_set_color_ansi(cv, CACA_GREEN, CACA_BLACK);
298    caca_fill_triangle(cv, xo, yo, xb, yb, xa, ya, '%');
299    caca_set_color_ansi(cv, CACA_YELLOW, CACA_BLACK);
300    caca_draw_thin_triangle(cv, xo, yo, xb, yb, xa, ya);
301
302    caca_set_color_ansi(cv, CACA_RED, CACA_BLACK);
303    caca_fill_triangle(cv, xa, ya, xb, yb, xc, yc, '#');
304    caca_set_color_ansi(cv, CACA_YELLOW, CACA_BLACK);
305    caca_draw_thin_triangle(cv, xa, ya, xb, yb, xc, yc);
306
307    caca_set_color_ansi(cv, CACA_BLUE, CACA_BLACK);
308    caca_fill_triangle(cv, xo, yo, xb, yb, xc, yc, '%');
309    caca_set_color_ansi(cv, CACA_YELLOW, CACA_BLACK);
310    caca_draw_thin_triangle(cv, xo, yo, xb, yb, xc, yc);
311
312    /* Draw a background triangle */
313    xa = 2;
314    ya = 2;
315
316    xb = caca_get_canvas_width(cv) - 3;
317    yb = caca_get_canvas_height(cv) / 2;
318
319    xc = caca_get_canvas_width(cv) / 3;
320    yc = caca_get_canvas_height(cv) - 3;
321
322    caca_set_color_ansi(cv, CACA_CYAN, CACA_BLACK);
323    caca_draw_thin_triangle(cv, xa, ya, xb, yb, xc, yc);
324
325    xo = caca_get_canvas_width(cv) / 2 + cos(0.027*i) * caca_get_canvas_width(cv) / 3;
326    yo = caca_get_canvas_height(cv) / 2 - sin(0.027*i) * caca_get_canvas_height(cv) / 2;
327
328    caca_draw_thin_line(cv, xa, ya, xo, yo);
329    caca_draw_thin_line(cv, xb, yb, xo, yo);
330    caca_draw_thin_line(cv, xc, yc, xo, yo);
331
332    /* Draw a sprite on the pyramid */
333#if 0
334    caca_draw_sprite(cv, xo, yo, sprite, 0);
335#endif
336
337    /* Draw a trail behind the foreground sprite */
338    for(j = i - 60; j < i; j++)
339    {
340        int delta = caca_rand(-5, 6);
341        caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16));
342        caca_put_char(cv, caca_get_canvas_width(cv) / 2
343                    + cos(0.02*j) * (delta + caca_get_canvas_width(cv) / 4),
344                   caca_get_canvas_height(cv) / 2
345                    + sin(0.02*j) * (delta + caca_get_canvas_height(cv) / 3),
346                   '#');
347    }
348
349    /* Draw foreground sprite */
350#if 0
351    caca_draw_sprite(cv, caca_get_canvas_width(cv) / 2 + cos(0.02*i) * caca_get_canvas_width(cv) / 4,
352                   caca_get_canvas_height(cv) / 2 + sin(0.02*i) * caca_get_canvas_height(cv) / 3,
353                   sprite, 0);
354#endif
355}
356
357static void demo_dots(void)
358{
359    int xmax = caca_get_canvas_width(cv);
360    int ymax = caca_get_canvas_height(cv);
361    int i;
362    static char chars[10] =
363    {
364        '+', '-', '*', '#', 'X', '@', '%', '$', 'M', 'W'
365    };
366
367    for(i = 1000; i--;)
368    {
369        /* Putpixel */
370        caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16));
371        caca_put_char(cv, caca_rand(0, xmax), caca_rand(0, ymax),
372                      chars[caca_rand(0, 9)]);
373    }
374}
375
376static void demo_lines(void)
377{
378    int w = caca_get_canvas_width(cv);
379    int h = caca_get_canvas_height(cv);
380    int xa, ya, xb, yb;
381
382    if(bounds)
383    {
384        xa = caca_rand(- w, 2 * w); ya = caca_rand(- h, 2 * h);
385        xb = caca_rand(- w, 2 * w); yb = caca_rand(- h, 2 * h);
386    }
387    else
388    {
389        xa = caca_rand(0, w); ya = caca_rand(0, h);
390        xb = caca_rand(0, w); yb = caca_rand(0, h);
391    }
392
393    caca_set_color_ansi(cv, caca_rand(0, 16), CACA_BLACK);
394    if(outline > 1)
395        caca_draw_thin_line(cv, xa, ya, xb, yb);
396    else
397        caca_draw_line(cv, xa, ya, xb, yb, '#');
398}
399
400static void demo_boxes(void)
401{
402    int w = caca_get_canvas_width(cv);
403    int h = caca_get_canvas_height(cv);
404    int xa, ya, xb, yb;
405
406    if(bounds)
407    {
408        xa = caca_rand(- w, 2 * w); ya = caca_rand(- h, 2 * h);
409        xb = caca_rand(- w, 2 * w); yb = caca_rand(- h, 2 * h);
410    }
411    else
412    {
413        xa = caca_rand(0, w); ya = caca_rand(0, h);
414        xb = caca_rand(0, w); yb = caca_rand(0, h);
415    }
416
417    caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16));
418    caca_fill_box(cv, xa, ya, xb, yb, '#');
419
420    caca_set_color_ansi(cv, caca_rand(0, 16), CACA_BLACK);
421    if(outline == 2)
422        caca_draw_thin_box(cv, xa, ya, xb, yb);
423    else if(outline == 1)
424        caca_draw_box(cv, xa, ya, xb, yb, '#');
425}
426
427static void demo_ellipses(void)
428{
429    int w = caca_get_canvas_width(cv);
430    int h = caca_get_canvas_height(cv);
431    int x, y, a, b;
432
433    if(bounds)
434    {
435        x = caca_rand(- w, 2 * w); y = caca_rand(- h, 2 * h);
436        a = caca_rand(0, w); b = caca_rand(0, h);
437    }
438    else
439    {
440        do
441        {
442            x = caca_rand(0, w); y = caca_rand(0, h);
443            a = caca_rand(0, w); b = caca_rand(0, h);
444
445        } while(x - a < 0 || x + a >= w || y - b < 0 || y + b >= h);
446    }
447
448    caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16));
449    caca_fill_ellipse(cv, x, y, a, b, '#');
450
451    caca_set_color_ansi(cv, caca_rand(0, 16), CACA_BLACK);
452    if(outline == 2)
453        caca_draw_thin_ellipse(cv, x, y, a, b);
454    else if(outline == 1)
455        caca_draw_ellipse(cv, x, y, a, b, '#');
456}
457
458static void demo_triangles(void)
459{
460    int w = caca_get_canvas_width(cv);
461    int h = caca_get_canvas_height(cv);
462    int xa, ya, xb, yb, xc, yc;
463
464    if(bounds)
465    {
466        xa = caca_rand(- w, 2 * w); ya = caca_rand(- h, 2 * h);
467        xb = caca_rand(- w, 2 * w); yb = caca_rand(- h, 2 * h);
468        xc = caca_rand(- w, 2 * w); yc = caca_rand(- h, 2 * h);
469    }
470    else
471    {
472
473        xa = caca_rand(0, w); ya = caca_rand(0, h);
474        xb = caca_rand(0, w); yb = caca_rand(0, h);
475        xc = caca_rand(0, w); yc = caca_rand(0, h);
476    }
477
478    caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16));
479    caca_fill_triangle(cv, xa, ya, xb, yb, xc, yc, '#');
480
481    caca_set_color_ansi(cv, caca_rand(0, 16), CACA_BLACK);
482    if(outline == 2)
483        caca_draw_thin_triangle(cv, xa, ya, xb, yb, xc, yc);
484    else if(outline == 1)
485        caca_draw_triangle(cv, xa, ya, xb, yb, xc, yc, '#');
486}
487#if 0
488static void demo_sprites(void)
489{
490
491    caca_draw_sprite(cv, caca_rand(0, caca_get_canvas_width(cv)),
492                      caca_rand(0, caca_get_canvas_height(cv)), sprite, 0);
493
494}
495#endif
496#if 0
497static void demo_render(void)
498{
499    caca_dither_t *dither;
500    //short buffer[256*256];
501    //short *dest = buffer;
502    int buffer[256*256];
503    int *dest = buffer;
504    int x, y, z;
505    static int i = 0;
506
507    i = (i + 1) % 512;
508    z = i < 256 ? i : 511 - i;
509
510    for(x = 0; x < 256; x++)
511        for(y = 0; y < 256; y++)
512    {
513        //*dest++ = ((x >> 3) << 11) | ((y >> 2) << 5) | ((z >> 3));
514        *dest++ = (x << 16) | (y << 8) | (z);
515    }
516    caca_set_dither_invert(dither, 1);
517    //dither = caca_create_dither(16, 256, 256, 2 * 256, 0xf800, 0x07e0, 0x001f, 0x0000);
518    dither = caca_create_dither(32, 256, 256, 4 * 256, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
519    caca_dither_bitmap(cv, 0, 0, caca_get_canvas_width(cv), caca_get_canvas_height(cv),
520                     dither, buffer);
521    caca_free_dither(dither);
522}
523#endif
524
525static void draw_circle(int *buffer, int xo, int yo, int r, int mask, int val);
526
527static void demo_render(void)
528{
529    caca_dither_t *dither;
530    int buffer[256*256];
531    int *dest;
532    int x, y, z, xo, yo;
533    static int i = 0;
534
535    i++;
536
537    dest = buffer;
538    for(x = 0; x < 256; x++)
539        for(y = 0; y < 256; y++)
540    {
541        *dest++ = 0xff000000;
542    }
543
544    /* red */
545    xo = 128 + 48 * sin(0.02 * i);
546    yo = 128 + 48 * cos(0.03 * i);
547    for(z = 0; z < 240; z++)
548        draw_circle(buffer, xo, yo, z, 0x00ff0000, 200 << 16);
549
550    /* green */
551    xo = 128 + 48 * sin(2 + 0.06 * i);
552    yo = 128 + 48 * cos(2 + 0.05 * i);
553    for(z = 0; z < 240; z++)
554        draw_circle(buffer, xo, yo, z, 0x0000ff00, 200 << 8);
555
556    /* blue */
557    xo = 128 + 48 * sin(1 + 0.04 * i);
558    yo = 128 + 48 * cos(1 + 0.03 * i);
559    for(z = 0; z < 240; z++)
560        draw_circle(buffer, xo, yo, z, 0x000000ff, 200);
561
562    dither = caca_create_dither(32, 256, 256, 4 * 256, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
563    caca_set_dither_gamma(dither, -1.0);
564    caca_dither_bitmap(cv, 0, 0, caca_get_canvas_width(cv), caca_get_canvas_height(cv), dither, (char *)buffer);
565    caca_free_dither(dither);
566}
567
568static void draw_circle(int *buffer, int x, int y, int r, int mask, int val)
569{
570    int t, dx, dy;
571
572#define POINT(X,Y) \
573    buffer[(X) + 256 * (Y)] = 0xff000000 | (buffer[(X) + 256 * (Y)] & ~mask) | val;
574
575    for(t = 0, dx = 0, dy = r; dx <= dy; dx++)
576    {
577        POINT(x - dx / 3, y - dy / 3);
578        POINT(x + dx / 3, y - dy / 3);
579        POINT(x - dx / 3, y + dy / 3);
580        POINT(x + dx / 3, y + dy / 3);
581
582        POINT(x - dy / 3, y - dx / 3);
583        POINT(x + dy / 3, y - dx / 3);
584        POINT(x - dy / 3, y + dx / 3);
585        POINT(x + dy / 3, y + dx / 3);
586
587        t += t > 0 ? dx - dy-- : dx;
588    }
589}
590
Note: See TracBrowser for help on using the repository browser.