source: libcaca/trunk/examples/cacaball.c @ 524

Last change on this file since 524 was 524, checked in by Sam Hocevar, 15 years ago

A new low-level text management library (canvas for ultrafast compositing

of unicode letters) is now separated from the higher level rendering and I/O
(that is, libcaca). This commit totally breaks the API, but once everything
is polished I will think about source-level backward compatibility. Most
drivers are broken, but X11 still sorta works.

The new design is much more object-oriented and allows having several

active renderers at the same time, changing renderers on the fly, and more
important, having no renderer at all (useful for converters, or when you
want to do your own renderer).

And in case you are still wondering, the libcucul acronym has "Unicode"

because I want to support at least a subset of Unicode. There are awesome
glyphs in it, including the ones inherited from Codepage 437 such as
"gray 25%" that are used in DOS and Win32 ANSI art.

  • Property svn:keywords set to Id
File size: 5.5 KB
Line 
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: cacaball.c 524 2006-03-05 18:43:13Z sam $
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
14#include "config.h"
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <math.h>
20
21#ifndef M_PI
22#   define M_PI 3.14159265358979323846
23#endif
24
25#include "cucul.h"
26#include "caca.h"
27
28/* Virtual buffer size */
29#define XSIZ 256
30#define YSIZ 256
31
32#define METASIZE 100
33#define METABALLS 16
34
35/* Colour index where to crop balls */
36#define CROPBALL 160
37
38static void create_ball(void);
39static void draw_ball(unsigned int, unsigned int);
40
41static unsigned char pixels[XSIZ * YSIZ];
42static unsigned char metaball[METASIZE * METASIZE];
43
44int main(int argc, char **argv)
45{
46    cucul_t *qq; caca_t *kk;
47    unsigned int r[256], g[256], b[256], a[256];
48    float d[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
49    unsigned int x[METABALLS], y[METABALLS];
50    struct cucul_bitmap *cucul_bitmap;
51    float i = 10.0, j = 17.0, k = 11.0;
52    int p, frame = 0, pause = 0;
53
54    qq = cucul_init();
55    if(!qq)
56        return 1;
57    kk = caca_attach(qq);
58    if(!kk)
59        return 1;
60
61    caca_set_delay(kk, 20000);
62
63    /* Make the palette eatable by libcaca */
64    for(p = 0; p < 256; p++)
65        r[p] = g[p] = b[p] = a[p] = 0x0;
66    r[255] = g[255] = b[255] = 0xfff;
67
68    /* Create a libcucul bitmap smaller than our pixel buffer, so that we
69     * display only the interesting part of it */
70    cucul_bitmap = cucul_create_bitmap(qq, 8, XSIZ - METASIZE, YSIZ - METASIZE,
71                                       XSIZ, 0, 0, 0, 0);
72
73    /* Generate ball sprite */
74    create_ball();
75
76    for(p = 0; p < METABALLS; p++)
77    {
78        d[p] = cucul_rand(0, 100);
79        di[p] = (float)cucul_rand(500, 4000) / 6000.0;
80        dj[p] = (float)cucul_rand(500, 4000) / 6000.0;
81        dk[p] = (float)cucul_rand(500, 4000) / 6000.0;
82    }
83
84    /* Go ! */
85    for(;;)
86    {
87        switch(caca_get_event(kk, CACA_EVENT_KEY_PRESS))
88        {
89            case CACA_EVENT_KEY_PRESS | CACA_KEY_ESCAPE: goto end;
90            case CACA_EVENT_KEY_PRESS | ' ': pause = !pause;
91        }
92
93        if(pause)
94            goto paused;
95
96        frame++;
97
98        /* Crop the palette */
99        for(p = CROPBALL; p < 255; p++)
100        {
101            int t1, t2, t3;
102            t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
103            t2 = p < 0xe0 ? 0 : (p - 0xe0) * 0x80;
104            t3 = p < 0x40 ? p * 0x40 : 0xfff;
105
106            r[p] = (1.0 + sin((double)frame * M_PI / 60)) * t1 / 4
107                 + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t2 / 4
108                 + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t3 / 4;
109            g[p] = (1.0 + sin((double)frame * M_PI / 60)) * t2 / 4
110                 + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t3 / 4
111                 + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t1 / 4;
112            b[p] = (1.0 + sin((double)frame * M_PI / 60)) * t3 / 4
113                 + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t1 / 4
114                 + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t2 / 4;
115        }
116
117        /* Set the palette */
118        cucul_set_bitmap_palette(qq, cucul_bitmap, r, g, b, a);
119
120        /* Silly paths for our balls */
121        for(p = 0; p < METABALLS; p++)
122        {
123            float u = di[p] * i + dj[p] * j + dk[p] * sin(di[p] * k);
124            float v = d[p] + di[p] * j + dj[p] * k + dk[p] * sin(dk[p] * i);
125            u = sin(i + u * 2.1) * (1.0 + sin(u));
126            v = sin(j + v * 1.9) * (1.0 + sin(v));
127            x[p] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
128            y[p] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
129        }
130
131        i += 0.011;
132        j += 0.017;
133        k += 0.019;
134
135        memset(pixels, 0, XSIZ * YSIZ);
136
137        /* Here is all the trick. Maybe if you're that
138         * clever you'll understand. */
139        for(p = 0; p < METABALLS; p++)
140            draw_ball(x[p], y[p]);
141
142paused:
143        /* Draw our virtual buffer to screen, letting libcucul resize it */
144        cucul_draw_bitmap(qq, 0, 0,
145                          cucul_get_width(qq) - 1, cucul_get_height(qq) - 1,
146                          cucul_bitmap, pixels + (METASIZE / 2) * (1 + XSIZ));
147        caca_refresh(kk);
148    }
149
150    /* End, bye folks */
151end:
152    cucul_free_bitmap(qq, cucul_bitmap);
153    caca_detach(kk);
154    cucul_end(qq);
155
156    return 0;
157}
158
159/* Generate ball sprite
160 * You should read the comments, I already wrote that before ... */
161static void create_ball(void)
162{
163    int x, y;
164    float distance;
165
166    for(y = 0; y < METASIZE; y++)
167        for(x = 0; x < METASIZE; x++)
168    {
169        distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
170                 + ((METASIZE/2) - y) * ((METASIZE/2) - y);
171        distance = sqrt(distance) * 64 / METASIZE;
172        metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
173    }
174}
175
176/* You missed the trick ? */
177static void draw_ball(unsigned int bx, unsigned int by)
178{
179    unsigned int color;
180    unsigned int i, e = 0;
181    unsigned int b = (by * XSIZ) + bx;
182
183    for(i = 0; i < METASIZE * METASIZE; i++)
184    {
185        color = pixels[b] + metaball[i];
186
187        if(color > 255)
188            color = 255;
189
190        pixels[b] = color;
191        if(e == METASIZE)
192        {
193            e = 0;
194            b += XSIZ - METASIZE;
195        }
196        b++;
197        e++;
198    }
199}
200
Note: See TracBrowser for help on using the repository browser.