Animation uses up memory like crazy!

aewarnick

Well-known member
Joined
Jan 29, 2003
Messages
1,031
C#:
int tick=1;
string Im= "D:\\Pictures\\marker.jpg";
		private void PreachForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			e.Graphics.DrawImage(Image.FromFile(Im), 10, 10, 600, 300);
		}

		private void Timer_Tick(object sender, System.EventArgs e)
		{
			if(tick==1) Im= "D:\\Pictures\\marker.jpg";
			else Im= "D:\\Pictures\\nobabysit.jpg";
			
			PreachForm_Paint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle));
			tick= (tick+1)%2;
		}
How do I clear the last picture that I showed from memory? I am not using a picture box. I tried using e.Dispose() and e.Graphics.Dispose() but that creates an exception. There must be some other way to quickly clear the form from the last image displayed.
 
I would only load each image once, then keep the instances around and draw with them when required. Any bitmap instance you create you should also Dispose when youre done with it.

Also, instead of calling your Paint procedure directly as you are doing I would call Invalidate() instead, to make Windows call it. Just good practice.
 
I did exactly what you said and also did some testing. I found that when I use Invalidate() it is not as fast between frames, there is more of a flicker.
Is there a way around that?

Also, I found that there is no flicker (that I can see) when I call Paint directly but it uses memory up. I think it is the new PaintEventArgs that I create each time. Can I call paint directly so that it does not use up memory like that? Just in case there is no way to stop the flicker using Invalidate().

Please answer each question either way this turns out.
 
I wouldnt call the Paint method yourself either, bad practice. Theres almost surely a better way. If nothing else, move out your code from the Paint event into a function and call that function from both the Paint event and your timer.

Having said that, do not pass a reference to "this.CreateGraphics()" ANYWHERE. Any graphics object you create MUST be disposed of or it will NOT go away. Do this instead:
C#:
Graphics g = this.CreateGraphics();
// Use g - in a call to PreachForm_Paint or whatever
g.Dispose();

-Nerseus
 
I found the reason that invalidate is slower is because it repaints the whole form but calling paint directly leaves the images there. If there are alot of controls and other graphical objects on the form then using invalidate will make my animation very slow, right?
 
Ideally, you only want to paint whats changed. If youre doing something with "sprites" in windowed mode (everything except DirectDraw will be in a window) and you want the best speed, you may need or want to keep track of the position of each drawn sprite so that you can only redraw a small portion of the screen each time.

There are lots of techniques, but the simplist (somewhat) is to redraw the background of where your sprite used to be, then draw it in the new location. To make it more efficient, you can event use IntersectRect to see if the old and new positions overlap (they often do) and then you might be able to save more time by not erasing the previous image if the new image is going to overwrite it anyway. This may be overkill for what you want/need.

The best bet is to find the slowest machine that youll want someone to play your game on and make sure it works well enough on that machine.

Having said that, I wouldnt worry about optimizing anything right now other than obvious flaws that are noticable now - which might indicate bad design or more general optimizations that are specific to game programming (such as the aforementioned "erase last position" logic).

-Nerseus
 
So, using a rectangle to paint only a portion of the form could, if I wanted, only update half of the form? For example, a button. I could repaint it but only update half of it?
 
You can do whatever you want, based on your needs.

By calling Invalidate, youre forcing a refresh of the whole form - hence a flicker occurs. When you call paint yourself, youre not really painting the form, just adding a little extra painting (looks like youre drawing an image). Honestly, if thats all you plan on doing, why not use an Image control or a Picturebox? If youre painting a picture on a button, there are better ways - but Id ask that question instead of painting.

My answers thus far have related more to moving pictures, such as an image that represents a "sprite" - a non-rectangular 2D region that may or may not be animated - used in games.

Maybe you could tell us more about what you want, then we can offer clearer suggestions maybe even real code snippets.

-Ners
 
I asked the question about refreshing part of a button, not because I want to do that but because I am curious if that would work. It would give me a better understanding of how painting works.
 

Similar threads

Back
Top