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

Last change on this file since 321 was 321, checked in by Sam Hocevar, 18 years ago
  • examples/cacaball.c: + 24 metaballs instead of 5, but smaller. + Zoom the bitmap to make more use of the screen area.
  • Property svn:keywords set to Id
File size: 4.7 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 321 2004-01-07 12:42:22Z sam $
7 *
8 *  This program is free software; you can redistribute it and/or
9 *  modify it under the terms of the GNU Lesser General Public
10 *  License as published by the Free Software Foundation; either
11 *  version 2 of the License, or (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *  Lesser General Public License for more details.
17 *
18 *  You should have received a copy of the GNU Lesser General Public
19 *  License along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 *  02111-1307  USA
22 */
23
24#include "config.h"
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <math.h>
30
31#include "caca.h"
32
33/* Virtual buffer size */
34#define XSIZ 256
35#define YSIZ 256
36
37#define METASIZE 100
38#define METABALLS 24
39
40/* Colour index where to crop balls */
41#define CROPBALL 180
42
43static void create_ball(void);
44static void draw_ball(unsigned int, unsigned int);
45
46static unsigned char pixels[XSIZ * YSIZ];
47static unsigned char metaball[METASIZE * METASIZE];
48
49int main(int argc, char **argv)
50{
51    int r[256], g[256], b[256], a[256];
52    float d[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
53    unsigned int x[METABALLS], y[METABALLS];
54    struct caca_bitmap *caca_bitmap;
55    float i = 10.0, j = 17.0, k = 11.0;
56    int p;
57
58    if(caca_init())
59        return 1;
60
61    caca_set_delay(10000);
62
63    /* Make the palette eatable by libcaca */
64    for(p = 0; p < 256; p++)
65    {
66        r[p] = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
67        g[p] = p < 0xc0 ? 0 : (p - 0xc0) * 0x40;
68        b[p] = p < 0x40 ? p * 0x40 : 0xfff;
69        a[p] = 0x0;
70    }
71
72    /* Crop the palette */
73    for(p = 0; p < CROPBALL; p++)
74        r[p] = g[p] = b[p] = a[p] = 0x0;
75
76    /* Create a libcaca bitmap smaller than our pixel buffer, so that we
77     * display only the interesting part of it */
78    caca_bitmap = caca_create_bitmap(8, XSIZ - METASIZE, YSIZ - METASIZE,
79                                     XSIZ, 0, 0, 0, 0);
80
81    /* Set the palette */
82    caca_set_bitmap_palette(caca_bitmap, r, g, b, a);
83
84    /* Generate ball sprite */
85    create_ball();
86
87    for(p = 0; p < METABALLS; p++)
88    {
89        d[p] = caca_rand(0, 100);
90        di[p] = (float)caca_rand(500, 4000) / 6000.0;
91        dj[p] = (float)caca_rand(500, 4000) / 6000.0;
92        dk[p] = (float)caca_rand(500, 4000) / 6000.0;
93    }
94
95    /* Go ! */
96    while(!caca_get_event(CACA_EVENT_KEY_PRESS))
97    {
98        /* Silly paths for our balls */
99        for(p = 0; p < METABALLS; p++)
100        {
101            float u = di[p] * i + dj[p] * j + dk[p] * sin(di[p] * k);
102            float v = d[p] + di[p] * j + dj[p] * k + dk[p] * sin(dk[p] * i);
103            u = sin(i + u * 2.1) * (1.0 + sin(u));
104            v = sin(j + v * 1.9) * (1.0 + sin(v));
105            x[p] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
106            y[p] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
107        }
108
109        i += 0.011;
110        j += 0.017;
111        k += 0.019;
112
113        memset(pixels, 0, XSIZ * YSIZ);
114
115        /* Here is all the trick. Maybe if you're that
116         * clever you'll understand. */
117        for(p = 0; p < METABALLS; p++)
118            draw_ball(x[p], y[p]);
119
120        /* Draw our virtual buffer to screen, letting libcaca resize it */
121        caca_draw_bitmap(0, 0, caca_get_width() - 1, caca_get_height() - 1,
122                         caca_bitmap, pixels + (METASIZE / 2) * (1 + XSIZ));
123        caca_refresh();
124    }
125
126    /* End, bye folks */
127    caca_end();
128
129    return 0;
130}
131
132/* Generate ball sprite
133 * You should read the comments, I already wrote that before ... */
134static void create_ball(void)
135{
136    int x, y;
137    float distance;
138
139    for(y = 0; y < METASIZE; y++)
140        for(x = 0; x < METASIZE; x++)
141    {
142        distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
143                 + ((METASIZE/2) - y) * ((METASIZE/2) - y);
144        distance = sqrt(distance) * 64 / METASIZE;
145        metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
146    }
147}
148
149/* You missed the trick ? */
150static void draw_ball(unsigned int bx, unsigned int by)
151{
152    unsigned int color;
153    unsigned int i, e = 0;
154    unsigned int b = (by * XSIZ) + bx;
155
156    for(i = 0; i < METASIZE * METASIZE; i++)
157    {
158        color = pixels[b] + metaball[i];
159
160        if(color > 255)
161            color = 255;
162
163        pixels[b] = color;
164        if(e == METASIZE)
165        {
166            e = 0;
167            b += XSIZ - METASIZE;
168        }
169        b++;
170        e++;
171    }
172}
173
Note: See TracBrowser for help on using the repository browser.