source: libcaca/trunk/src/cacaball.c @ 734

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