randomfox (randomfox) wrote,
randomfox
randomfox

Randomly-generated fireworks in C#


screenshot

// firework - Fireworks graphics
// Author: Po Shan Cheah
// Last updated: August 18, 2003
// 
// Compile with: csc /doc:firework.xml /t:winexe firework.cs

namespace FireWork {

using System;
using System.Drawing;
using System.Windows.Forms;

/// <summary>Keeps track of one of the fireworks.</summary>
class FireWork {
    /// <summary>Maximum number of rays</summary>
    const int MaxRays = 10;

    /// <summary>Where the rays begin.</summary>
    double start;

    /// <summary>Where the rays end.</summary>
    double stop;

    /// <summary>Maximum length of the rays.</summary>
    double len;

    /// <summary>Current position in the iteration.</summary>
    double curpos;

    SolidBrush brush;

    /// <summary>Number of rays.</summary>
    int nrays;

    /// <summary>Center. X coord.</summary>
    int cx;
    
    /// <summary>Center. Y coord.</summary>
    int cy;

    /// <summary>Cached values of the sin of the angle of each
    /// ray.</summary>
    double[] sintab;

    /// <summary>Cached values of the cos of the angle of each
    /// ray.</summary>
    double[] costab;

    /// <summary>This determines how much faster each ray falls because of
    /// gravity.</summary>
    double descent;

    static Random rand = new Random();

    /// <summary>How much the fireworks should advance on each
    /// step.</summary>
    const double Step = 0.5;

    /// <summary>Advance by one position.</summary>
    /// <returns>False if this fireworks has gone away.</returns>
    public bool Update() {
	curpos += Step;
	return curpos <= stop + len;
    }

    /// <summary>Paint this fireworks</summary>
    /// <remarks>The fireworks should be drawn from max(curpos-len,start)
    /// to min(curpos,stop).</remarks>
    /// <param name="g">Graphics context</param>
    public void Paint(Graphics g) {
	double lower = Math.Max(curpos - len, start);
	double upper = Math.Min(curpos, stop);

	for (double pos = lower; pos < upper; pos += Step) {
	    // The quad squared component simulates some additional
	    // downward movement due to gravity.
	    double quad = descent * pos;
	    double quadsq = quad * quad;

	    for (int i = 0; i < nrays; ++i)
		g.FillRectangle(brush,
				(int) (cx + pos * costab[i]),
				(int) (cy + pos * sintab[i] + quadsq),
				1, 1);
	}
    } // Paint

    /// <summary>Initialize fireworks.</summary>
    /// <param name="xsize">Width of drawing area</param>
    /// <param name="ysize">Height of drawing area</param>
    public FireWork(int xsize, int ysize) {
	cx = rand.Next(xsize);
	cy = rand.Next(ysize);
	descent = rand.NextDouble() * 0.1 + 0.05;

	start = rand.NextDouble() * 10 + 5;
	stop = rand.NextDouble() * 50 + 50;
	len = rand.NextDouble() * 50 + 25;

	curpos = start;

	brush = new SolidBrush(Color.FromArgb(rand.Next(128, 256),
					      rand.Next(128, 256),
					      rand.Next(128, 256)));

	nrays = rand.Next(5, MaxRays + 1);

	double angleInc = 2 * Math.PI / nrays;
	double angle = rand.NextDouble() * angleInc;

	costab = new double[nrays];
	sintab = new double[nrays];
	for (int i = 0; i < nrays; ++i, angle += angleInc) {
	    costab[i] = Math.Cos(angle);
	    sintab[i] = Math.Sin(angle);
	}
    }
} // class FireWork

/// <summary>Tracks all the fireworks</summary>
class FireWorks : Form {
    /// <summary>Maximum number of fireworks.</summary>
    const int MaxFireWorks = 10;

    FireWork[] fireworks = new FireWork[MaxFireWorks];

    static Random rand = new Random();

    /// <summary>Timer event handler. Will be called periodically to update
    /// and redraw the fireworks.</summary>
    void Tick(Object o, EventArgs e) {
	// Update all fireworks.
	for (int i = 0; i < MaxFireWorks; ++i)
	    if (fireworks[i] != null)
		if (!fireworks[i].Update())
		    // If this fireworks has ended, remove it.
		    fireworks[i] = null;

	// Create a new fireworks randomly if there's an open slot.
	if (rand.Next(10) == 0)
	    for (int i = 0; i < MaxFireWorks; ++i)
		if (fireworks[i] == null) {
		    fireworks[i] = new FireWork(ClientRectangle.Width,
						ClientRectangle.Height);
		    break;
		}
	
	Invalidate();
	// Invalidate() by itself does not trigger a repaint.
	Update();
    } // Tick

    /// <summary>Paint event handler.</summary>
    protected override void OnPaint(PaintEventArgs e) {
	e.Graphics.Clear(Color.Black);
	foreach (FireWork fw in fireworks)
	    if (fw != null)
		fw.Paint(e.Graphics);
    }

    /// <summary>Milliseconds between each update.</summary>
    const int UpdateInterval = 25;

    FireWorks() {
	Text = "Fireworks";
	Name = "Fireworks";

	// Activate double-buffering.
	SetStyle(ControlStyles.UserPaint, true);
	SetStyle(ControlStyles.AllPaintingInWmPaint, true);
	SetStyle(ControlStyles.DoubleBuffer, true);

	ClientSize = new Size(700, 600);

	// Create a timer for updating the display.
	Timer timer = new Timer();
	timer.Tick += new EventHandler(Tick);
	timer.Interval = UpdateInterval;
	timer.Start();	
    }

    static int Main() {
	Application.Run(new FireWorks());
	return 0;
    }
} // class FireWorks

} // namespace FireWork

// The End

Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments