Alright, so I've done some research into this topic and most of the solutions I've found claim to fix the problem but I am finding that they aren't quite working right. I'm in the early stages of implementing just a simple little particle engine, nothing crazy I'm just doing it out of boredom. I have not done anything like this with WinForms before, I have certainly with C/C++ but this is a new thing for me. The following is the code I am using to draw the particles to the screen, the boiler plate code for the particles is not relevant as it works fine, I am more curious about my actual game loop.
Here is the main code for updates and redraws
public MainWindow() { this.DoubleBuffered = true; InitializeComponent(); Application.Idle += HandleApplicationIdle; } void HandleApplicationIdle(object sender, EventArgs e) { Graphics g = CreateGraphics(); while (IsApplicationIdle()) { UpdateParticles(); RenderParticles(g); g.Dispose(); } } //Variables for drawing the particle Pen pen = new Pen(Color.Black, 5); Brush brush = new SolidBrush(Color.Blue); public bool emmiter = false; private void EmitterBtn_Click(object sender, EventArgs e) { //Determine which emitter to use if (emmiter == true) { //Creates a new particle Particle particle = new Particle(EmitterOne.Left, EmitterOne.Top, .5f, .5f, 20, 20); emmiter = false; } else if(emmiter == false) { Particle particle = new Particle(EmitterTwo.Left, EmitterTwo.Top, -.5f, .5f, 20, 20); emmiter = true; } } public void RenderParticles(Graphics renderer) { Invalidate(); Thread.Sleep(0); //Iterate though the static list of particles for (int i = 0; i < Particle.activeParticles.Count; i++) { //Draw Particles renderer.DrawRectangle(pen, Particle.activeParticles[i].x, Particle.activeParticles[i].y, Particle.activeParticles[i].w, Particle.activeParticles[i].h); } } public void UpdateParticles() { for (int i = 0; i < Particle.activeParticles.Count; i++) { //Move particles Particle.activeParticles[i].MoveParticle(); } } The issue I am running into is that anytime the screen is getting cleared and updated, it gets this awful flickering, and not only that but it sometimes won't whenever I emit a particle.
The form is basically just using labels as invisible locations on the screen to say where to render each particle.
Anyway, I've seen this topic before but nothing has fixed anything, the current implementation is the least flickery/laggy but is not solving the issue.
Any help is appreciated, thanks!
EDIT* I realized I was never deallocating the graphics object each loop so I did that and there is no more delay whenever I click the emitter button, however the flicker is still there, I updated the code accordingly.
Invalidate();will cause the entire control area to be wiped clean, hence the flicker. Normally one would draw to an offscreen buffer but since you are merely drawing dots, you could remember the old dot locations and erase them prior to drawing the new location. It works to a point. As I said offscreen buffer is preferred. The speed of your animation will fluctuate badly based onApplication.Idle. You may want to consider using a timer.System.Windows.Forms.Timeris fine for this sort of thing particularly if you want to target say 30 FPS. TheTimeris course enough to handle that (we're not after a super precision timer). The problem of having it sit on application idle instead of a timer, is that if you move the mouse about, Windows will actually cutdown on the amount of app idle messages that you and I probably saw in our c++ MFC days and follows on into c# :)UserControlthat renders offscreen and flickerfree in my answer here - Avoiding creating PictureBoxes again and again. Hope this helps good sir :) (oh it will also do desired FPS)