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

Last change on this file since 522 was 522, checked in by Sam Hocevar, 15 years ago
  • Changed the licensing to WTFPL, as per all copyright holders' permission.
  • Property svn:keywords set to Id
File size: 5.3 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 522 2006-03-04 00:35:45Z 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 "caca.h"
26
27/* Virtual buffer size */
28#define XSIZ 256
29#define YSIZ 256
30
31#define METASIZE 100
32#define METABALLS 16
33
34/* Colour index where to crop balls */
35#define CROPBALL 160
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    unsigned int r[256], g[256], b[256], a[256];
46    float d[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
47    unsigned int x[METABALLS], y[METABALLS];
48    struct caca_bitmap *caca_bitmap;
49    float i = 10.0, j = 17.0, k = 11.0;
50    int p, frame = 0, pause = 0;
51
52    if(caca_init())
53        return 1;
54
55    caca_set_delay(20000);
56
57    /* Make the palette eatable by libcaca */
58    for(p = 0; p < 256; p++)
59        r[p] = g[p] = b[p] = a[p] = 0x0;
60    r[255] = g[255] = b[255] = 0xfff;
61
62    /* Create a libcaca bitmap smaller than our pixel buffer, so that we
63     * display only the interesting part of it */
64    caca_bitmap = caca_create_bitmap(8, XSIZ - METASIZE, YSIZ - METASIZE,
65                                     XSIZ, 0, 0, 0, 0);
66
67    /* Generate ball sprite */
68    create_ball();
69
70    for(p = 0; p < METABALLS; p++)
71    {
72        d[p] = caca_rand(0, 100);
73        di[p] = (float)caca_rand(500, 4000) / 6000.0;
74        dj[p] = (float)caca_rand(500, 4000) / 6000.0;
75        dk[p] = (float)caca_rand(500, 4000) / 6000.0;
76    }
77
78    /* Go ! */
79    for(;;)
80    {
81        switch(caca_get_event(CACA_EVENT_KEY_PRESS))
82        {
83            case CACA_EVENT_KEY_PRESS | CACA_KEY_ESCAPE: goto end;
84            case CACA_EVENT_KEY_PRESS | ' ': pause = !pause;
85        }
86
87        if(pause)
88            goto paused;
89
90        frame++;
91
92        /* Crop the palette */
93        for(p = CROPBALL; p < 255; p++)
94        {
95            int t1, t2, t3;
96            t1 = p < 0x40 ? 0 : p < 0xc0 ? (p - 0x40) * 0x20 : 0xfff;
97            t2 = p < 0xe0 ? 0 : (p - 0xe0) * 0x80;
98            t3 = p < 0x40 ? p * 0x40 : 0xfff;
99
100            r[p] = (1.0 + sin((double)frame * M_PI / 60)) * t1 / 4
101                 + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t2 / 4
102                 + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t3 / 4;
103            g[p] = (1.0 + sin((double)frame * M_PI / 60)) * t2 / 4
104                 + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t3 / 4
105                 + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t1 / 4;
106            b[p] = (1.0 + sin((double)frame * M_PI / 60)) * t3 / 4
107                 + (1.0 + sin((double)(frame + 40) * M_PI / 60)) * t1 / 4
108                 + (1.0 + sin((double)(frame + 80) * M_PI / 60)) * t2 / 4;
109        }
110
111        /* Set the palette */
112        caca_set_bitmap_palette(caca_bitmap, r, g, b, a);
113
114        /* Silly paths for our balls */
115        for(p = 0; p < METABALLS; p++)
116        {
117            float u = di[p] * i + dj[p] * j + dk[p] * sin(di[p] * k);
118            float v = d[p] + di[p] * j + dj[p] * k + dk[p] * sin(dk[p] * i);
119            u = sin(i + u * 2.1) * (1.0 + sin(u));
120            v = sin(j + v * 1.9) * (1.0 + sin(v));
121            x[p] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
122            y[p] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
123        }
124
125        i += 0.011;
126        j += 0.017;
127        k += 0.019;
128
129        memset(pixels, 0, XSIZ * YSIZ);
130
131        /* Here is all the trick. Maybe if you're that
132         * clever you'll understand. */
133        for(p = 0; p < METABALLS; p++)
134            draw_ball(x[p], y[p]);
135
136paused:
137        /* Draw our virtual buffer to screen, letting libcaca resize it */
138        caca_draw_bitmap(0, 0, caca_get_width() - 1, caca_get_height() - 1,
139                         caca_bitmap, pixels + (METASIZE / 2) * (1 + XSIZ));
140        caca_refresh();
141    }
142
143    /* End, bye folks */
144end:
145    caca_free_bitmap(caca_bitmap);
146    caca_end();
147
148    return 0;
149}
150
151/* Generate ball sprite
152 * You should read the comments, I already wrote that before ... */
153static void create_ball(void)
154{
155    int x, y;
156    float distance;
157
158    for(y = 0; y < METASIZE; y++)
159        for(x = 0; x < METASIZE; x++)
160    {
161        distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
162                 + ((METASIZE/2) - y) * ((METASIZE/2) - y);
163        distance = sqrt(distance) * 64 / METASIZE;
164        metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
165    }
166}
167
168/* You missed the trick ? */
169static void draw_ball(unsigned int bx, unsigned int by)
170{
171    unsigned int color;
172    unsigned int i, e = 0;
173    unsigned int b = (by * XSIZ) + bx;
174
175    for(i = 0; i < METASIZE * METASIZE; i++)
176    {
177        color = pixels[b] + metaball[i];
178
179        if(color > 255)
180            color = 255;
181
182        pixels[b] = color;
183        if(e == METASIZE)
184        {
185            e = 0;
186            b += XSIZ - METASIZE;
187        }
188        b++;
189        e++;
190    }
191}
192
Note: See TracBrowser for help on using the repository browser.