OK, quindi ho svolto alcune ricerche su questo argomento e la maggior parte delle soluzioni che ho trovato sostengono di risolvere il problema, ma sto scoprendo che non stanno funzionando correttamente. Sono nelle prime fasi dell'implementazione di un semplice piccolo motore di particelle, niente di pazzesco lo sto solo facendo per noia. Non ho mai fatto nulla del genere con WinForms, ho certamente con C/C++ ma questa è una novità per me. Quello che segue è il codice che sto usando per disegnare le particelle sullo schermo, il codice della piastra della caldaia per le particelle non è rilevante in quanto funziona bene, sono più curioso del mio ciclo di gioco reale.Flicker nel programma C# WinForms sullo schermo chiaro
Ecco il codice principale per gli aggiornamenti e ridisegna
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();
}
}
L'edizione che sto funzionando in è che ogni volta che lo schermo è sempre cancellata e aggiornato, si ottiene questo sfarfallio terribile, e non solo, ma a volte non lo farò ogni volta che emetto una particella.
Il modulo è fondamentalmente solo utilizzando le etichette come posizioni invisibili sullo schermo per dire dove visualizzare ogni particella.
In ogni caso, ho già visto questo argomento ma nulla ha risolto nulla, l'implementazione corrente è il minimo sfarfallio/rallentamento ma non risolve il problema.
Qualsiasi aiuto è apprezzato, grazie!
EDIT * Mi sono reso conto che non stavo mai spostando l'oggetto grafico ogni ciclo, così l'ho fatto e non c'è più ritardo ogni volta che faccio clic sul pulsante dell'emettitore, tuttavia il flicker è ancora lì, ho aggiornato il codice di conseguenza.
'Invalidate();' farà pulire l'intera area di controllo, quindi lo sfarfallio. Normalmente si dovrebbe disegnare su un buffer fuori schermo, ma dal momento che si stanno semplicemente disegnando punti, è possibile ricordare le posizioni dei punti precedenti e cancellarli prima di disegnare la nuova posizione. Funziona su un punto. Come ho detto, il buffer esterno è preferito. La velocità della tua animazione fluttuerà male in base a 'Application.Idle'. Si consiglia di prendere in considerazione l'utilizzo di un timer. – MickyD
Interessante, le altre cose che ho letto dicono che il timer non è affidabile, anche se stavo pensando la stessa cosa, potrei dover provare. –
Il 'System.Windows.Forms.Timer' va bene per questo genere di cose, in particolare se si desidera target dire 30 FPS.Il 'Timer' è abbastanza veloce per gestirlo (non stiamo cercando un timer di super precisione). Il problema di averlo seduto su applicazione inattiva invece di un timer, è che se si sposta il mouse, Windows ridurrà effettivamente la quantità di messaggi inattivi di app che io e te probabilmente abbiamo visto nei nostri giorni MFC C++ e seguiamo in C# :) – MickyD