import java.applet.*;
import java.awt.*;
import java.util.*;

// copyright 2002 mel@melaxis.de

public class MelCircle extends Applet implements Runnable
{
	Image offi;
	Graphics offg;
	Thread thread;
	int w = 0, h = 0;
	int cx = 0, cy = 0;
	
	int circlex[] = new int[361];
	int circley[] = new int[361];
	Color circlecol[] = new Color[361];
	int ballx[] = new int[361];
	int bally[] = new int[361];
	
	double scale = 1.7;
	boolean scalebigger = true;
	int ballpos = 270; // starting angle of the ball, 270 is at the top, 0 at the right...
	
	String copyright = "© melaxis.com"; // do not change
	int copyrightx = 0;
	int copyrighty = 0;
	
	int fps = 0;
	long fpssek = 0;
	int fpscur = 0;
	double fpsavg = 0;
	
	public void init()
	{
		setBackground(Color.black);
		w = getSize().width;
		h = getSize().height;
		cx = w/2;
		cy = h/2;
		copyrighty = h-2;
		offi = createImage(w, h);
		offg = offi.getGraphics();
		offg.setFont(new Font("SansSerif", Font.PLAIN, 10));
		FontMetrics fm = getFontMetrics(getFont());
		copyrightx = w-2-fm.stringWidth(copyright);
		copyrighty = h-2;
		Random r = new Random();
		for (int a = 0; a <= 360; a++)
		{
			circlex[a] = cx+(int)(Math.cos(a * (Math.PI / 180)) * (180 / Math.PI) * scale);
			circley[a] = cy+(int)(Math.sin(a * (Math.PI / 180)) * (180 / Math.PI) * scale);
			circlecol[a] = new Color(Math.abs(r.nextInt()) % 256, Math.abs(r.nextInt()) % 256, Math.abs(r.nextInt()) % 256);
			ballx[a] = (int)(Math.cos(a * (Math.PI / 180)) * (180 / Math.PI) * 0.1);
			bally[a] = (int)(Math.sin(a * (Math.PI / 180)) * (180 / Math.PI) * 0.1);
		}
	}
	
	public void start()
	{
		if (thread==null)
		{
			thread = new Thread(this);
			thread.start();
		}
	}
	
	public void stop()
	{
		if (thread!=null)
		{
			thread.stop();
		}
	}
	
	public void paint(Graphics g)
	{
		g.drawImage(offi, 0, 0, this);
	}
	
	public void update(Graphics g)
	{
		paint(g);
	}
	
	private void calcPos()
	{
		for (int a = 0; a <= 360; a++)
		{
			circlex[a] = cx+(int)(Math.cos(a * (Math.PI / 180)) * (180 / Math.PI) * scale);
			circley[a] = cy+(int)(Math.sin(a * (Math.PI / 180)) * (180 / Math.PI) * scale);
		}
	}
	
	private void drawCanvas()
	{
		offg.setColor(Color.black);
		offg.fillRect(0,0,w,h);
		// Kreis zeichnen (eigener Algo *gg*)
		int lastx = circlex[0];
		int lasty = circley[1];
		for (int a = 0; a <= 360; a++)
		{
			int x = circlex[a];
			int y = circley[a];
			offg.setColor(circlecol[a]);
			offg.drawLine(lastx,lasty,x,y);
			lastx=x;
			lasty=y;
		}
		// Ball zeichnen
		int ballcx = circlex[ballpos];
		int ballxy = circley[ballpos];
		offg.setColor(Color.red);
		for (int a = 0; a <= 360; a++)
		{
			int x = ballcx+ballx[a];
			int y = ballxy+bally[a];
			offg.drawLine(x,y,x,y);
		}
		// FPS berechnen
		if (fpssek == 0) fpssek = (System.currentTimeMillis()/1000);
		if (fpssek != (System.currentTimeMillis()/1000))
		{
			fps = fpscur;
			fpscur = 0;
			if (fpsavg > 0)
			{
				fpsavg = (fpsavg+fps)/2;
			}
			else
			{
				fpsavg = fps;
			}
			//System.out.println("FPS: " + fps + " \t Average: " + fpsavg);
			fpssek = System.currentTimeMillis()/1000;
		}
		else
		{
			fpscur++;
		}
		// Text ausgeben
		offg.setColor(new Color(155, 155, 155));
		offg.drawString(copyright, copyrightx, copyrighty);
		offg.drawString(fps + " fps", 2, copyrighty);
		// Kreis drehen (Farben rotieren)
		Color[] newcol = new Color[361];
		newcol[0] = circlecol[360];
		for (int a = 1; a <= 360; a++)
		{
			newcol[a] = circlecol[a-1];
		}
		System.arraycopy(newcol, 0, circlecol, 0, 361);
		// Kreisgröße ändern
		if (scalebigger)
		{
			scale += 0.01;
			if (scale >= 2)
				scalebigger=false;
		}
		else
		{
			scale -= 0.01;
			if (scale <= 0.6)
				scalebigger=true;
		}
		ballpos = (ballpos+3) % 360;
		calcPos();
	}
	
	public void run()
	{
		while (true)
		{
			try
			{
				drawCanvas();
				repaint();
				Thread.sleep(10);
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
	}
}