// This example is from the book _Java in a Nutshell_ by David Flanagan. // Written by David Flanagan. Copyright (c) 1996 O'Reilly & Associates. // You may study, use, modify, and distribute this example for any purpose. // This example is provided WITHOUT WARRANTY either expressed or implied. import java.applet.*; import java.awt.*; import java.net.*; import java.lang.*; public class kepler extends Applet implements Runnable { // static final int deltax = 4; // static final int deltay = 2; static final int deltax = 2; static final int deltay = 1; static final int nsteps = 100; // Conversion factors from Kepler natural units to CGS static final double secyear=3.155815e+7; static final double AUcm = 1.496e+13; // Basic constants static final double Msolar = 1.989e+33; static final double G = 6.67259e-8; // Input data double a = 2.0; double acm = AUcm * a; double M = 3.0; double Mgrams = M * Msolar; double e = 0.8; double P; double Psec; double r = a*(1.0 - e); double rcm = acm*(1.0 - e); int rpixel; double pixelScale = 150./a; double theta = 0.0; double dtheta; double t = 0.0; double dt; int xshift; int yshift; static final String message = "Smooth Animation2"; Image sun; Image planet; int sizeSun; int sizePlanet; int x = 0; int y = 0; Color c1 = new Color(0x000000); Color c2 = new Color(0xffffff); Font font = new Font("Helvetica", Font.BOLD, 24); Image offscreen; int imagewidth, imageheight; int stringwidth, stringheight, stringascent; Thread animator = null; boolean please_stop = false; // Measure the size of the images we'll be animating. We need this // information later to do clipping. public void init() { URL codeBase = getCodeBase(); sun = getImage(codeBase,"siriusA.jpg"); planet = getImage(codeBase,"siriusB.jpg"); sizeSun = sun.getWidth(this); sizePlanet = planet.getWidth(this); // Calculate period in years from Kepler's 3rd Law and // convert to CGS units (seconds). Then calculate the length of // a timestep in seconds. P = Math.sqrt(a*a*a/M); Psec = secyear * P; dt = Psec/((double) nsteps); // System.out.println("Psec= " + Psec + " P= " + P); } // Start the animation public void start() { animator = new Thread(this); animator.start(); } // Stop it. public void stop() { if (animator != null) animator.stop(); animator = null; } // Stop and start animating on mouse clicks. public boolean mouseDown(Event e, int x, int y) { // if running, stop it. Otherwise, start it. if (animator != null) please_stop = true; else { please_stop = false; start(); } return true; } // Draw applet background void drawBackground(Graphics gr, Color c1) { Dimension size = this.size(); int w = size.width, h = size.height; gr.setColor(c1); gr.fillRect(0, 0, w, h); xshift = w/2 + (int)(e*a*pixelScale); yshift = h/2; //gr.drawImage(sun,w/2,h/2,sizeSun,sizeSun,this); // resize version gr.drawImage(sun, yshift - sizeSun/2, yshift - sizeSun/2, this); } // This method draws the background and image at its current position. public void paint(Graphics g) { drawBackground(g, c1); //g.setColor(Color.white); //g.fillOval(x,y,sizePlanet,sizePlanet); // g.drawImage(planet,x,y,sizePlanet,sizePlanet,this); // resize version g.drawImage(planet, x-sizePlanet/2, y-sizePlanet/2, this); // no resize version } // The body of the animator thread. public void run() { while(!please_stop) { Dimension d = this.size(); // Make sure the offscreen image is created and is the right size. if ((offscreen == null) || ((imagewidth != d.width) || (imageheight != d.height))) { // if (offscreen != null) offscreen.flush(); offscreen = this.createImage(d.width, d.height); imagewidth = d.width; imageheight = d.height; } // Set up clipping. We only need to draw within the // old rectangle that needs to be cleared and the new // one that is being drawn. // the old rectangle Rectangle oldrect = new Rectangle(x-sizePlanet/2, y-sizePlanet/2, sizePlanet, sizePlanet); // Update the coordinates for animation. // Update time and theta t = t + dt; dtheta = Math.sqrt(G*Mgrams*acm*(1.0 - e*e))*dt/rcm/rcm; theta = theta + dtheta; System.out.println("t= "+t+" dt="+dt+" dtheta="+dtheta+" theta="+theta); // Calculate r r = a*(1.0 - e*e)/(1.0 + e*Math.cos(theta)); rcm = AUcm * r; rpixel = (int)(r * pixelScale); // Calculate relative x and y in pixels int xrel = (int)(r * Math.cos(theta) * pixelScale); int yrel = (int)(r * Math.sin(theta) * pixelScale); System.out.println("r= " + r +" rpixel= " + rpixel+" xrel="+xrel+" yrel="+yrel); x = xrel + xshift; y = yrel + yshift; // x = ((x + deltax)%d.width); // y = ((y + deltay)%d.height); // the new rectangle Rectangle newrect = new Rectangle(x-sizePlanet/2, y-sizePlanet/2, sizePlanet, sizePlanet); // Compute the union of the rectangles Rectangle r = newrect.union(oldrect); // Use this rectangle as the clipping region when // drawing to the offscreen image, and when copying // from the offscreen image to the screen. Graphics g = offscreen.getGraphics(); // g.clipRect(r.x, r.y, r.width, r.height); // Draw into the off-screen image. paint(g); // Copy it all at once to the screen, using clipping. g = this.getGraphics(); // g.clipRect(r.x, r.y, r.width, r.height); //g.setColor(Color.yellow); //g.drawRect(r.x, r.y, r.width, r.height); g.drawImage(offscreen, 0, 0, this); // wait then draw it again! try { Thread.sleep(40); } catch (InterruptedException e) { ; } } animator = null; } }