//* <C> 1996 Growler Software, Inc. *//

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;

public class Firework extends Applet implements Runnable {
	public int AnimationSpeed, RocketStyleVariability, MaxRocketNumber,
			MaxRocketExplosionEnergy, MaxRocketPatchNumber,
			MaxRocketPatchLength, Gravity;
	public String RocketSoundtrack;
	private int mx, my;
	private Thread thread = null;
	private Rocket rocket[];

	public void init() {
		int i;
		String p;
		p = getParameter("AnimationSpeed");
		AnimationSpeed = (p == null) ? 100 : Integer.valueOf(p).intValue();
		RocketSoundtrack = getParameter("RocketSoundtrack");
		p = getParameter("RocketStyleVariability");
		RocketStyleVariability = (p == null) ? 20 : Integer.valueOf(p)
				.intValue();
		p = getParameter("MaxRocketNumber");
		MaxRocketNumber = (p == null) ? 5 : Integer.valueOf(p).intValue();
		p = getParameter("MaxRocketExplosionEnergy");
		MaxRocketExplosionEnergy = (p == null) ? 500 : Integer.valueOf(p)
				.intValue();
		p = getParameter("MaxRocketPatchNumber");
		MaxRocketPatchNumber = (p == null) ? 50 : Integer.valueOf(p).intValue();
		p = getParameter("MaxRocketPatchLength");
		MaxRocketPatchLength = (p == null) ? 100 : Integer.valueOf(p)
				.intValue();
		p = getParameter("Gravity");
		Gravity = (p == null) ? 20 : Integer.valueOf(p).intValue();
		mx = size().width - 1;
		my = size().height - 1;
		rocket = new Rocket[MaxRocketNumber];
		for (i = 0; i < MaxRocketNumber; i++)
			rocket[i] = new Rocket(mx, my, Gravity);
	}

	public void start() {
		if (thread == null) {
			thread = new Thread(this);
			thread.start();
		}
	}

	public void stop() {
		if (thread != null) {
			thread.stop();
			thread = null;
		}
	}

	public void run() {
		int i, e = (int) (Math.random() * MaxRocketExplosionEnergy * 3 / 4)
				+ MaxRocketExplosionEnergy / 4 + 1, p = (int) (Math.random()
				* MaxRocketPatchNumber * 3 / 4)
				+ MaxRocketPatchNumber / 4 + 1, l = (int) (Math.random()
				* MaxRocketPatchLength * 3 / 4)
				+ MaxRocketPatchLength / 4 + 1;
		long s = (long) (Math.random() * 10000);
		boolean sleep;
		Graphics g = getGraphics();
		URL u = null;
		while (true) {
			try {
				thread.sleep(100 / AnimationSpeed);
			} catch (InterruptedException x) {
			}
			sleep = true;
			for (i = 0; i < MaxRocketNumber; i++)
				sleep = sleep && rocket[i].sleep;
			if (sleep && Math.random() * 100 < RocketStyleVariability) {
				e = (int) (Math.random() * MaxRocketExplosionEnergy * 3 / 4)
						+ MaxRocketExplosionEnergy / 4 + 1;
				p = (int) (Math.random() * MaxRocketPatchNumber * 3 / 4)
						+ MaxRocketPatchNumber / 4 + 1;
				l = (int) (Math.random() * MaxRocketPatchLength * 3 / 4)
						+ MaxRocketPatchLength / 4 + 1;
				s = (long) (Math.random() * 10000);
			}
			for (i = 0; i < MaxRocketNumber; i++) {
				if (rocket[i].sleep && Math.random() * MaxRocketNumber * l < 1) {
					try {
						u = new URL(getDocumentBase(), RocketSoundtrack);
					} catch (MalformedURLException x) {
					}
					play(u);
					rocket[i].init(e, p, l, s);
					rocket[i].start();
				}
				rocket[i].show(g);
			}
		}
	}

	public void paint(Graphics g) {
		g.setColor(Color.black);
		g.fillRect(0, 0, mx + 1, my + 1);
	}
}

class Rocket {
	public boolean sleep = true;
	private int energy, patch, length, mx, my, gravity, ox, oy, vx[], vy[], x,
			y, red, blue, green, t;
	private Random random;

	public Rocket(int a, int b, int g) {
		mx = a;
		my = b;
		gravity = g;
	}

	public void init(int e, int p, int l, long seed) {
		int i;
		energy = e;
		patch = p;
		length = l;
		random = new Random(seed);
		vx = new int[patch];
		vy = new int[patch];
		red = (int) (random.nextDouble() * 128) + 128;
		blue = (int) (random.nextDouble() * 128) + 128;
		green = (int) (random.nextDouble() * 128) + 128;
		ox = (int) (Math.random() * mx / 2) + mx / 4;
		oy = (int) (Math.random() * my / 2) + my / 4;
		for (i = 0; i < patch; i++) {
			vx[i] = (int) (Math.random() * energy) - energy / 2;
			vy[i] = (int) (Math.random() * energy * 7 / 8) - energy / 8;
		}
	}

	public void start() {
		t = 0;
		sleep = false;
	}

	public void show(Graphics g) {
		if (!sleep)
			if (t < length) {
				int i, c;
				double s;
				Color color;
				c = (int) (random.nextDouble() * 64) - 32 + red;
				if (c >= 0 && c < 256)
					red = c;
				c = (int) (random.nextDouble() * 64) - 32 + blue;
				if (c >= 0 && c < 256)
					blue = c;
				c = (int) (random.nextDouble() * 64) - 32 + green;
				if (c >= 0 && c < 256)
					green = c;
				color = new Color(red, blue, green);
				for (i = 0; i < patch; i++) {
					s = (double) t / 100;
					x = (int) (vx[i] * s);
					y = (int) (vy[i] * s - gravity * s * s);
					g.setColor(color);
					g.drawLine(ox + x, oy - y, ox + x, oy - y);
					if (t >= length / 2) {
						int j;
						for (j = 0; j < 2; j++) {
							s = (double) ((t - length / 2) * 2 + j) / 100;
							x = (int) (vx[i] * s);
							y = (int) (vy[i] * s - gravity * s * s);
							g.setColor(Color.black);
							g.drawLine(ox + x, oy - y, ox + x, oy - y);
						}
					}
				}
				t++;
			} else {
				sleep = true;
			}
	}
}


