[Mono-winforms-list] simple animation

Jon Heiner jon.heiner@gmail.com
Sat, 9 Apr 2005 22:12:51 -0700


Is there a problem with the Graphics Device not being invalidated  
properly? Here is some simple code that animates a sprite moving  
around. The only way I can see anything is if I toggle the mono window  
underneath another window, like the Finder. This is adapted from some  
animation code I picked up that renders to an Image and then uses the  
Graphic DrawImage call. No matter how I do it, my Form does not  
invalidate and update on the timer ticks. Any thoughts?

system: MacOSX 10.3.8 w/ mono1.1.5

code:
________________________________________________________________________ 
__________________________________
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Bouncy
{
	/ 
/----------------------------------------------------------------------- 
-------
	// Ball
	/ 
/----------------------------------------------------------------------- 
-------
	public class Ball
	{
		public Ball( System.Drawing.Size bounds )
		{
			_armPen   = new Pen(Color.Red, (float)3.0);
			_center   = new Point(3,3);
			_size     = new Size( bounds.Width + 5, bounds.Height + 5);
			_velocity = new Point(1,1);
		}

		// bounce the ball around in a bounded rectangle
		public void Update( System.Drawing.Size bounds )
		{
			_center.X += _velocity.X;
			if( _center.X < 0 )             { _center.X = 0; _velocity.X =  
-_velocity.X; }
			if( _center.X > bounds.Width )  { _center.X = bounds.Width;  
_velocity.X = -_velocity.X; }
			_center.Y += _velocity.Y;
			if( _center.Y < 0 )             { _center.Y = 0; _velocity.Y =  
-_velocity.Y; }
			if( _center.Y > bounds.Height ) { _center.Y = bounds.Height;  
_velocity.Y = -_velocity.Y; }
		}

		// draw the 'ball'
		public void Draw(Graphics g)
		{
			g.DrawRectangle( _armPen, new Rectangle( _center, _size) );
		}

		private Color _ballColor;
		private Pen   _armPen;
		private Size  _size;
		private Point _velocity;
		private Point _center;
	}

	/ 
/----------------------------------------------------------------------- 
-------
	// MainForm
	/ 
/----------------------------------------------------------------------- 
-------
	public class MainForm : System.Windows.Forms.Form
	{
		[STAThread]
		static void Main()
		{
			Application.Run(new MainForm());
		}

		public MainForm()
		{
			InitializeComponent();
		}

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.timer1 = new System.Windows.Forms.Timer(this.components);
			this.drawBox = new System.Windows.Forms.GroupBox();
			this.SuspendLayout();

			// timer1
			this.timer1.Enabled = true;
			this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
			this.timer1.Interval = 1000/60;

			// drawBox
			this.drawBox.Location = new System.Drawing.Point(120, 60);
			this.drawBox.Name = "drawBox";
			this.drawBox.Size = new System.Drawing.Size(400, 200);
			this.drawBox.TabIndex = 3;
			this.drawBox.TabStop = false;
			this.drawBox.Text = "Drawing Area";
			this.drawBox.Visible = false;

			// MainForm
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.BackColor = System.Drawing.Color.LightBlue;
			this.ClientSize = new System.Drawing.Size(640, 320);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {  
this.drawBox });
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
			this.MaximizeBox = false;
			this.Name = "MainForm";
			this.Text = "MainForm";
			this.Load += new System.EventHandler(this.OnLoad);
			this.ResumeLayout(false);

		}

		private void OnLoad(object sender, System.EventArgs e)
		{
			_ball = new Ball( drawBox.Size );

			backBrush = new SolidBrush(Color.Black);

			InitForSimpleDrawing();
		}

		private void timer1_Tick(object sender, System.EventArgs e)
		{
			// redraw the whole form
			_ball.Update( this.drawBox.Size );
			DrawSimple();
		}

		private void DrawSimple()
		{
			Graphics clientDC = this.CreateGraphics();

			clientDC.FillRectangle(backBrush, drawBox.Left, drawBox.Top,  
drawBox.Width, drawBox.Height);
			_ball.Draw(clientDC);
			drawBox.Invalidate();
		}
		
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.Timer       timer1;

		private System.Windows.Forms.GroupBox    drawBox;
		private SolidBrush                       backBrush;
		private Ball                             _ball;
	}
}