1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* grav --- planets spinning around a pulsar */
5 static const char sccsid[] = "@(#)grav.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1993 by Greg Boewring <gb@pobox.com>
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: Compatible with xscreensaver
26 * 11-Jul-1994: color version
27 * 06-Oct-1993: Written by Greg Bowering <gb@pobox.com>
32 #define DEFAULTS "*delay: 10000 \n" \
35 "*fpsSolid: true \n" \
36 "*ignoreRotation: True \n" \
39 # define grav_handle_event 0
40 # include "xlockmore.h" /* in xscreensaver distribution */
41 #else /* STANDALONE */
42 # include "xlock.h" /* in xlockmore distribution */
43 #endif /* STANDALONE */
47 #define DEF_DECAY "True" /* Damping for decaying orbits */
48 #define DEF_TRAIL "True" /* For trails (works good in mono only) */
53 static XrmOptionDescRec opts[] =
55 {"-decay", ".grav.decay", XrmoptionNoArg, "on"},
56 {"+decay", ".grav.decay", XrmoptionNoArg, "off"},
57 {"-trail", ".grav.trail", XrmoptionNoArg, "on"},
58 {"+trail", ".grav.trail", XrmoptionNoArg, "off"}
60 static argtype vars[] =
62 {&decay, "decay", "Decay", DEF_DECAY, t_Bool},
63 {&trail, "trail", "Trail", DEF_TRAIL, t_Bool}
65 static OptionStruct desc[] =
67 {"-/+decay", "turn on/off decaying orbits"},
68 {"-/+trail", "turn on/off trail dots"}
71 ENTRYPOINT ModeSpecOpt grav_opts =
72 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
75 ModStruct grav_description =
76 {"grav", "init_grav", "draw_grav", "release_grav",
77 "refresh_grav", "init_grav", (char *) NULL, &grav_opts,
78 10000, -12, 1, 1, 64, 1.0, "",
79 "Shows orbiting planets", 0, NULL};
83 #define GRAV -0.02 /* Gravitational constant */
85 #define COLLIDE 0.0001
88 /* #define INTRINSIC_RADIUS 200.0 */
89 #define INTRINSIC_RADIUS ((float) (gp->height/5))
90 #define STARRADIUS (unsigned int)(gp->height/(2*DIST))
91 #define AVG_RADIUS (INTRINSIC_RADIUS/DIST)
92 #define RADIUS (unsigned int)(INTRINSIC_RADIUS/(POS(Z)+DIST))
94 #define XR HALF*ALMOST
95 #define YR HALF*ALMOST
96 #define ZR HALF*ALMOST
105 #define DAMP 0.999999
106 #define MaxA 0.1 /* Maximum acceleration (w/ damping) */
108 #define POS(c) planet->P[c]
109 #define VEL(c) planet->V[c]
110 #define ACC(c) planet->A[c]
113 if ((x) >= 0 && (y) >= 0 && (x) <= gp->width && (y) <= gp->height) {\
115 XDrawPoint(display, window, gc, (x), (y));\
117 XFillArc(display, window, gc,\
118 (x) - planet->ri / 2, (y) - planet->ri / 2, planet->ri, planet->ri,\
122 #define FLOATRAND(min,max) ((min)+(LRAND()/MAXRAND)*((max)-(min)))
125 double P[DIMENSIONS], V[DIMENSIONS], A[DIMENSIONS];
127 unsigned long colors;
132 int x, y, sr, nplanets;
133 unsigned long starcolor;
134 planetstruct *planets;
137 static gravstruct *gravs = (gravstruct *) NULL;
140 init_planet(ModeInfo * mi, planetstruct * planet)
142 Display *display = MI_DISPLAY(mi);
143 Window window = MI_WINDOW(mi);
145 gravstruct *gp = &gravs[MI_SCREEN(mi)];
148 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
151 if (MI_NPIXELS(mi) > 2)
152 planet->colors = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
154 planet->colors = MI_WHITE_PIXEL(mi);
155 /* Initialize positions */
156 POS(X) = FLOATRAND(-XR, XR);
157 POS(Y) = FLOATRAND(-YR, YR);
158 POS(Z) = FLOATRAND(-ZR, ZR);
160 if (POS(Z) > -ALMOST) {
162 ((double) gp->width * (HALF + POS(X) / (POS(Z) + DIST)));
164 ((double) gp->height * (HALF + POS(Y) / (POS(Z) + DIST)));
166 planet->xi = planet->yi = -1;
169 /* Initialize velocities */
170 VEL(X) = FLOATRAND(-VR, VR);
171 VEL(Y) = FLOATRAND(-VR, VR);
172 VEL(Z) = FLOATRAND(-VR, VR);
175 Planet(planet->xi, planet->yi);
179 draw_planet(ModeInfo * mi, planetstruct * planet)
181 Display *display = MI_DISPLAY(mi);
182 Window window = MI_WINDOW(mi);
184 gravstruct *gp = &gravs[MI_SCREEN(mi)];
185 double D; /* A distance variable to work with */
186 register unsigned char cmpt;
188 D = POS(X) * POS(X) + POS(Y) * POS(Y) + POS(Z) * POS(Z);
193 for (cmpt = X; cmpt < DIMENSIONS; cmpt++) {
194 ACC(cmpt) = POS(cmpt) * GRAV / D;
196 if (ACC(cmpt) > MaxA)
198 else if (ACC(cmpt) < -MaxA)
200 VEL(cmpt) = VEL(cmpt) + ACC(cmpt);
203 /* update velocity */
204 VEL(cmpt) = VEL(cmpt) + ACC(cmpt);
206 /* update position */
207 POS(cmpt) = POS(cmpt) + VEL(cmpt);
213 if (POS(Z) > -ALMOST) {
215 ((double) gp->width * (HALF + POS(X) / (POS(Z) + DIST)));
217 ((double) gp->height * (HALF + POS(Y) / (POS(Z) + DIST)));
219 planet->xi = planet->yi = -1;
222 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
223 Planet(gp->x, gp->y);
225 XSetForeground(display, gc, planet->colors);
226 XDrawPoint(display, MI_WINDOW(mi), gc, gp->x, gp->y);
234 XSetForeground(display, gc, planet->colors);
235 Planet(gp->x, gp->y);
239 init_grav(ModeInfo * mi)
241 Display *display = MI_DISPLAY(mi);
247 if ((gravs = (gravstruct *) calloc(MI_NUM_SCREENS(mi),
248 sizeof (gravstruct))) == NULL)
251 gp = &gravs[MI_SCREEN(mi)];
253 gp->width = MI_WIDTH(mi);
254 gp->height = MI_HEIGHT(mi);
258 gp->nplanets = MI_COUNT(mi);
259 if (gp->nplanets < 0) {
261 (void) free((void *) gp->planets);
262 gp->planets = (planetstruct *) NULL;
264 gp->nplanets = NRAND(-gp->nplanets) + 1; /* Add 1 so its not too boring */
266 if (gp->planets == NULL) {
267 if ((gp->planets = (planetstruct *) calloc(gp->nplanets,
268 sizeof (planetstruct))) == NULL)
274 if (MI_NPIXELS(mi) > 2)
275 gp->starcolor = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
277 gp->starcolor = MI_WHITE_PIXEL(mi);
278 for (ball = 0; ball < (unsigned char) gp->nplanets; ball++)
279 init_planet(mi, &gp->planets[ball]);
281 /* Draw centrepoint */
282 XDrawArc(display, MI_WINDOW(mi), gc,
283 gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
288 draw_grav(ModeInfo * mi)
290 Display *display = MI_DISPLAY(mi);
291 Window window = MI_WINDOW(mi);
293 register unsigned char ball;
298 gp = &gravs[MI_SCREEN(mi)];
299 if (gp->planets == NULL)
302 MI_IS_DRAWN(mi) = True;
303 /* Mask centrepoint */
304 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
305 XDrawArc(display, window, gc,
306 gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
309 /* Resize centrepoint */
312 if (gp->sr < (int) STARRADIUS)
320 /* Draw centrepoint */
321 XSetForeground(display, gc, gp->starcolor);
322 XDrawArc(display, window, gc,
323 gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
326 for (ball = 0; ball < (unsigned char) gp->nplanets; ball++)
327 draw_planet(mi, &gp->planets[ball]);
331 reshape_grav(ModeInfo * mi, int width, int height)
333 gravstruct *gp = &gravs[MI_SCREEN(mi)];
336 XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
340 release_grav(ModeInfo * mi)
345 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
346 gravstruct *gp = &gravs[screen];
349 (void) free((void *) gp->planets);
351 (void) free((void *) gravs);
352 gravs = (gravstruct *) NULL;
357 refresh_grav(ModeInfo * mi)
362 XSCREENSAVER_MODULE ("Grav", grav)
364 #endif /* MODE_grav */