import java.awt.*; import java.awt.image.*; import kinetoscope.awt.*; /** * * * This is a Java port of grav, which is included in * xscreensaver. *
* This is the original copyright notice in the C source: *
* Copyright (c) 1993 Greg Bowering* * */ public class Grav extends DoubleBufferedFrame implements Runnable { public static long kRefreshInterval = 0; private Thread refreshThread; int width, height; ModeInfo myInfo; java.util.Random rand = new java.util.Random(); public final static double GRAV = -0.02; public final static double DIST = 16.0; public final static double COLLIDE = 0.0001; public final static double ALMOST = 15.99; public final static double HALF = 0.5; public final static double VR = 0.04; public final static int DIMENSIONS = 3; public final static int X = 0; public final static int Y = 1; public final static int Z = 2; public final static double DAMP = 0.999999; public final static double MaxA = 0.1; public static double XR; public static double YR; public static double ZR; public static boolean decay; public static boolean trail; public static int count; GravStruct[] gravs; public Grav() { super("COLOR FRAME"); setSize(512, 384); initFrame(); XR = HALF*ALMOST; YR = HALF*ALMOST; ZR = HALF*ALMOST; refreshThread = new Thread(this); refreshThread.setPriority(Thread.MIN_PRIORITY); refreshThread.start(); this.show(); } void Planet(int x, int y, Graphics g, int ri, GravStruct gp, Color gc) { if ((x) >= 0 && (y) >= 0 && (x) <= gp.width && (y) <= gp.height) { if (ri < 2) { g.setColor(gc); g.drawLine(x,y,x,y); } else { g.setColor(gc); g.fillArc((x) - ri / 2, (y) - ri / 2, ri, ri, 0, 360); } } } double FLOATRAND(double min, double max) { return((rand.nextDouble()*(max-min))+min); } void init_planet(ModeInfo mi, PlanetStruct planet) { Color gc = (mi).xgwa.getColor(); GravStruct gp = gravs[0]; if ((mi).npixels > 2) planet.colors = mi.pixels[Math.abs((int)rand.nextInt()%(mi).npixels)]; else planet.colors = (mi).white; /* Initialize positions */ planet.P[X] = FLOATRAND(-XR, XR); planet.P[Y] = FLOATRAND(-YR, YR); planet.P[Z] = FLOATRAND(-ZR, ZR); if (planet.P[Z] > -ALMOST) { planet.xi = (int) ((double) gp.width * (HALF + planet.P[X] / (planet.P[Z] + DIST))); planet.yi = (int) ((double) gp.height * (HALF + planet.P[Y] / (planet.P[Z] + DIST))); } else { planet.xi = planet.yi = -1; } planet.ri = (int)(((float) (gp.height/5))/(planet.P[Z]+DIST)); if(trail) { planet.x1 = planet.xi; planet.x2 = planet.xi; planet.x3 = planet.xi; planet.x4 = planet.xi; planet.y1 = planet.xi; planet.y2 = planet.xi; planet.y3 = planet.xi; planet.y4 = planet.xi; } /* Initialize velocities */ planet.V[X] = FLOATRAND(-VR, VR); planet.V[Y] = FLOATRAND(-VR, VR); planet.V[Z] = FLOATRAND(-VR, VR); /* Draw planets */ Planet(planet.xi, planet.yi, mi.xgwa, planet.ri, gp, planet.colors); } void draw_planet(ModeInfo mi, PlanetStruct planet) { Color gc = (mi).xgwa.getColor(); GravStruct gp = gravs[0]; double D; /* A distance variable to work with */ int cmpt; D = planet.P[X] * planet.P[X] + planet.P[Y] * planet.P[Y] + planet.P[Z] * planet.P[Z]; if (D < COLLIDE) D = COLLIDE; D = Math.sqrt(D); D = D * D * D; for (cmpt = X; cmpt < DIMENSIONS; cmpt++) { planet.A[cmpt] = planet.P[cmpt] * GRAV / D; if (decay) { if (planet.A[cmpt] > MaxA) planet.A[cmpt] = MaxA; else if (planet.A[cmpt] < -MaxA) planet.A[cmpt] = -MaxA; planet.V[cmpt] = planet.V[cmpt] + planet.A[cmpt]; planet.V[cmpt] *= DAMP; } else { /* update velocity */ planet.V[cmpt] = planet.V[cmpt] + planet.A[cmpt]; } /* update position */ planet.P[cmpt] = planet.P[cmpt] + planet.V[cmpt]; } gp.x = planet.xi; gp.y = planet.yi; if (planet.P[Z] > -ALMOST) { planet.xi = (int) ((double) gp.width * (HALF + planet.P[X] / (planet.P[Z] + DIST))); planet.yi = (int) ((double) gp.height * (HALF + planet.P[Y] / (planet.P[Z] + DIST))); } else planet.xi = planet.yi = -1; /* Mask */ // Planet(gp.x, gp.y, mi.xgwa, planet.ri, gp, mi.black); if (trail) { int size = planet.ri; mi.xgwa.setColor(planet.colors); mi.xgwa.fillArc(gp.x-size/2,gp.y-size/2,(size*2)/3,(size*2)/3,0,360); mi.xgwa.fillArc(planet.x1-size/3,planet.y1-size/3,size*2/5,size*2/5,0,360); mi.xgwa.fillArc(planet.x2-size/4,planet.y2-size/4,size/3,size/3,0,360); mi.xgwa.fillArc(planet.x3-size/6,planet.y3-size/6,(size/4)+1,(size/4)+1,0,360); mi.xgwa.fillArc(planet.x4-size/8,planet.y4-size/8,(size/6)+1,(size/6)+1,0,360); planet.x4 = planet.x3; planet.x3 = planet.x2; planet.x2 = planet.x1; planet.x1 = gp.x; planet.y4 = planet.y3; planet.y3 = planet.y2; planet.y2 = planet.y1; planet.y1 = gp.y; } /* Move */ gp.x = planet.xi; gp.y = planet.yi; planet.ri = (int)(((float) (gp.height/5))/(planet.P[Z]+DIST)); /* Redraw */ Planet(gp.x, gp.y, mi.xgwa, planet.ri, gp, planet.colors); } void init_grav(ModeInfo mi) { Color gc = (mi).xgwa.getColor(); GravStruct gp; int ball; if (gravs == null) { gravs = new GravStruct[1]; gravs[0] = new GravStruct(); } gp = gravs[0]; gp.width = (mi).width; gp.height = (mi).height; gp.sr = (int)(gp.height/(2*DIST)); gp.nplanets = (mi).batchcount; if (gp.nplanets < 0) { if (gp.planets != null) { gp.planets=null; } gp.nplanets = Math.abs(rand.nextInt()%(-gp.nplanets)) + 1; /* Add 1 so its not too boring */ } if (gp.planets==null) { gp.planets = new PlanetStruct[gp.nplanets]; for(int i=0;i* * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * Revision history: * 10-May-97: jwz@jwz.org: turned into a standalone program. * 11-Jul-94: color version * 06-Oct-93: by Greg Bowering *