randomfox: (Default)
[personal profile] randomfox

screenshot

// worms - Moving worms animation
// Author: Po Shan Cheah
// Last updated: August 27, 2003
// 
// Compile with: csc /t:winexe /doc:worms.xml worms.cs

namespace Worms {

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

/// <summary>Keeps track of one worm</summary>
class Worm {
    Point[] points;

    /// <summary>Width of the drawing area</summary>
    int xsize;

    /// <summary>Height of the drawing area</summary>
    int ysize;

    /// <summary>The current tail of the worm. The next segment will be
    /// added after this one.</summary>
    int tail = 0;

    Pen pen;

    /// <summary>Current direction of travel for the worm in
    /// radians.</summary>
    double dir = 0;

    /// <summary>Angle of the worm's direction change on each round in
    /// radians.</summary> 
    const double DirChange = 0.2;

    /// <summary>Distance the worm will move on each round.</summary>
    const int WormShift = 6;
    
    /// <summary>Radius of each worm segment.</summary>
    const int WormRadius = 4;

    /// <summary>Worm length</summary>
    const int WormLength = 25;

    static Random rand = new Random();

    /// <summary>Constructor for the worm</summary>
    /// <param name="xsize">Width of drawing area</param>
    /// <param name="ysize">Height of drawing area</param>
    public Worm(int xsize, int ysize) {
	this.xsize = xsize;
	this.ysize = ysize;

	points = new Point[WormLength];

	// Choose a random color for this worm.
	pen = new Pen(Color.FromArgb(rand.Next(128, 256),
				     rand.Next(128, 256),
				     rand.Next(128, 256)));

	// Need to start the worm with at least one segment.
	points[tail] = new Point(rand.Next(xsize), rand.Next(ysize));
    }

	
    /// <summary>Adjust x so that it is between 0 and upper.</summary>
    /// <remarks>If x is greater than upper, it will wrap to 0.
    /// If x is less than zero, it will wrap to upper.</remarks>
    /// <param name="x">value to wrap</param>
    /// <param name="upper">upper upper bound of the range</param>
    /// <returns>wrapped value</returns>
	
    public int Wrap(int x, int upper) {
	return x < 1 ? upper : x > upper ? 1 : x;
    }
    
    /// <summary>Generates a new worm segment.</summary>
    /// <remarks>The direction of travel will be dir plus or minus
    /// DirChange. The worm will wrap around the screen if
    /// necessary.</remarks>
    public void NewSegment() {
	int nextTail = (tail + 1) % WormLength;
	dir += rand.NextDouble() >= 0.5 ? DirChange : -DirChange;

	points[nextTail] = 
	    new Point(Wrap(points[tail].X +
			   (int) Math.Round(WormShift * Math.Cos(dir)),
			   xsize),
		      Wrap(points[tail].Y +
			   (int) Math.Round(WormShift * Math.Sin(dir)),
			   ysize));
	tail = nextTail;
    } // NewSegment

    /// <summary>Draw the worm using the specified graphics context.</summary>
    /// <param name="g">graphics context</param>
    public void Paint(Graphics g) {
	foreach (Point p in points)
	    if (!p.IsEmpty)
		g.DrawEllipse(pen, 
			      p.X - WormRadius, p.Y - WormRadius,
			      2 * WormRadius, 2 * WormRadius);
    }
} // class Worm

/// <summary>Manages all the worms</summary>
class Worms : Form {
    /// <summary>Number of worms</summary>
    const int NWorms = 10;

    Worm[] worms;

    /// <summary>Paint event handler.</summary>
    protected override void OnPaint(PaintEventArgs e) {
	e.Graphics.FillRectangle(Brushes.Black, 0, 0, 
				 ClientRectangle.Width, 
				 ClientRectangle.Height);
	foreach (Worm w in worms)
	    w.Paint(e.Graphics);
    }

    /// <summary>Timer event handler. Will be called periodically to move
    /// the worms and redraw the image.</summary>
    void Tick(Object o, EventArgs e) {
	foreach (Worm w in worms)
	    w.NewSegment();

	Invalidate();
	// Invalidate() by itself does not trigger a repaint.
	Update();
    }

    /// <summary>Milliseconds between each round of worm
    /// movement.</summary>
    const int UpdateInterval = 200;

    Worms() {
	Text = "Worms";
	Name = "Worms";

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

	ClientSize = new Size(700, 600);

	worms = new Worm[NWorms];
	for (int i = 0; i < NWorms; ++i)
	    worms[i] = new Worm(ClientRectangle.Width, ClientRectangle.Height);

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

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

// The End

Profile

randomfox: (Default)
randomfox

November 2012

S M T W T F S
    123
45678910
11121314151617
18192021222324
25262728 2930 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Oct. 24th, 2014 07:41 am
Powered by Dreamwidth Studios