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

Last change on this file since 537 was 527, checked in by Sam Hocevar, 15 years ago
  • All output plugins should now work again.
  • Renamed caca_refresh() into caca_display() which makes more sense.
  • Optimised gl_bgpal by directly storing floats instead of doing the conversion at runtime.
  • Handle resizing in cucul_set_size() and try to keep as much information as possible from the previous canvas.
  • Moved most global variables into cucul_t or caca_t contexts.
  • Moved time.c into libcaca.
  • 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 527 2006-03-06 08:32:40Z 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_display(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.