[.net] Problem with animated object.
I have a Bullet class which animates an ellipse on screen. The thing is, it doesn't draw animate it across the entire screen, only a small portion, then it disappears. It's kinda of hard to describe so heres the code.
public class Bullet
{
private int xspeed;
private int yspeed;
private int x;
private int y;
private int width;
private int height;
private Graphics g;
public Bullet( int x, int y, int width, int height, Form form )
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
InitializeGraphics( form );
xspeed = 3;
yspeed = 3;
}
private void InitializeGraphics( Form form )
{
g = form.CreateGraphics();
}
public void Draw()
{
g.FillEllipse( Brushes.Azure, x, y, width, height );
}
public void ClearOld()
{
g.FillRectangle( Brushes.Black, x - xspeed, y - yspeed, width, height );
}
public void UpdateBullet()
{
x += xspeed;
y += yspeed;
if( x > 800 )
xspeed *= -1;
if( y > 600 )
yspeed *= -1;
if( x < 0 )
xspeed *= -1;
if( y < 0 )
yspeed *= -1;
}
}// end of Bullet class
public class TestCC : Form
{
private Bullet bullet;
private Timer timer;
public TestCC()
{
bullet = new Bullet( 150, 150, 30, 30, this );
this.BackColor = Color.Black;
this.Size = new Size( 800, 600 );
}
private void InitializeTimer()
{
timer = new Timer();
timer.Interval = 16;
timer.Tick += new EventHandler( TimerTick );
timer.Enabled = true;
}
private void TimerTick( object sender, EventArgs ea )
{
bullet.UpdateBullet();
bullet.ClearOld();
bullet.Draw();
}
public static void Main()
{
TestCC tcc = new TestCC();
tcc.Show();
tcc.InitializeTimer();
Application.Run( tcc );
}
}// end of Test Class
What am I doing wrong?
-triele-
You appear to be caching the Graphics object in Bullet. This is no good; the created Graphics object is only valid for a very short while (the current window message, in fact).
What you need to do is handle the main form's OnPaint event, and pass the Graphics object you get there to the Bullet class when it's time to draw it. Then that Graphics object will always be good.
Or, to get it working more simply, cache the main form reference in Bullet, and call CreateGraphics() during Draw() and ClearOld() (though I'd probably combine the two, or have the main window clear itself instead of Bullet doing it). But that's quick and dirty, and you should really draw in response to OnPaint.
What you need to do is handle the main form's OnPaint event, and pass the Graphics object you get there to the Bullet class when it's time to draw it. Then that Graphics object will always be good.
Or, to get it working more simply, cache the main form reference in Bullet, and call CreateGraphics() during Draw() and ClearOld() (though I'd probably combine the two, or have the main window clear itself instead of Bullet doing it). But that's quick and dirty, and you should really draw in response to OnPaint.
Tricksy code! [smile]
Change this:
bullet = new Bullet( 150, 150, 30, 30, this );
this.BackColor = Color.Black;
this.Size = new Size( 800, 600 );
to this:
this.BackColor = Color.Black;
this.Size = new Size( 800, 600 );
bullet = new Bullet( 150, 150, 30, 30, this );
You're creating the graphics object before setting the form size, so the graphics object uses the default form size.
I have to disagree partly with RenderTarget. You don't need to call CreateGraphics every time you draw. The graphics object is valid the way you have it. If it were me, though, I'd probably pass a reference to the graphics object to the bullet when you draw it instead of keeping a reference in the class or get the data from the bullet and do the drawing in the form.
Change this:
bullet = new Bullet( 150, 150, 30, 30, this );
this.BackColor = Color.Black;
this.Size = new Size( 800, 600 );
to this:
this.BackColor = Color.Black;
this.Size = new Size( 800, 600 );
bullet = new Bullet( 150, 150, 30, 30, this );
You're creating the graphics object before setting the form size, so the graphics object uses the default form size.
I have to disagree partly with RenderTarget. You don't need to call CreateGraphics every time you draw. The graphics object is valid the way you have it. If it were me, though, I'd probably pass a reference to the graphics object to the bullet when you draw it instead of keeping a reference in the class or get the data from the bullet and do the drawing in the form.
There is one very quick fix to get your code working. It won't be well designed as yet (you never .Dispose() your Graphics object, for instance), but at least it'll work...
Resize the form before you pass it to the Bullet constructor, which calls InitializeGraphics() and constructs a Graphics instance with a clip region set to match the form's original size!
Machaira was quicker.
public TestCC() { this.Size = new Size(800, 600); bullet = new Bullet(150, 150, 30, 30, this); this.BackColor = Color.Black; }
Resize the form before you pass it to the Bullet constructor, which calls InitializeGraphics() and constructs a Graphics instance with a clip region set to match the form's original size!
Machaira was quicker.
Thanks guys for all the tips. Yeah, I know the code is ugly, but I just wanted to get something up and running quickly.
Oluseyi && Machaira: That fixed it right up!! Thanks.
-triele-
Oluseyi && Machaira: That fixed it right up!! Thanks.
-triele-
Quote:Original post by Machaira
I have to disagree partly with RenderTarget. You don't need to call CreateGraphics every time you draw. The graphics object is valid the way you have it. If it were me, though, I'd probably pass a reference to the graphics object to the bullet when you draw it instead of keeping a reference in the class or get the data from the bullet and do the drawing in the form.
From MSDN, under Control.CreateGraphics:
Quote:The returned Graphics must be disposed through a call to its Dispose method when it is no longer needed. The Graphics is only valid for the duration of the current window's message.
Theoretically it may be okay, but who knows what state it's relying on, or will in the future.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement