2009-08-15 3 views
2

J'ai pour une tâche scolaire créé un petit jeu, il est divisé en 2 projets différents, un projet avec le formulaire et un avec un fichier DLL contenant le Jeu.C# problème de fermeture de mon petit jeu lorsque l'événement de fermeture de formulaire est déclenché

La boucle de jeu est très simple et ressemble à ceci:

private void GameLoop(Graphics g) 
    { 
     int lastTick = Kernel32.GetTickCount(); 
     do 
     { 
      if (terminated) 
       break; 

      while ((lastTick + 50) > Kernel32.GetTickCount()) 
       Application.DoEvents(); 

      while (gamePaused) 
       Application.DoEvents(); 

      g.FillRectangle(new SolidBrush(Color.White), 0, 0, 800, 640); 
      DrawWalls(g); 
      MoveMonsters(); 
      DrawMonsters(g); 
      lastTick = Kernel32.GetTickCount(); 
     } 
     while (true); 
     gameRunning = false; 
    } 

Il fonctionne comme prévu et redessine le panneau sur la page du formulaire. Sur la page de formulaire, j'ai un bouton pour quitter le jeu en cours, cela se fait simplement par le formulaire principal appelant la commande TerminateGame() de game.dll terminée par true, cela fonctionne aussi comme prévu. Maintenant, mon problème est lorsque l'utilisateur clique sur le bouton de fermeture de formulaire ou appuie sur F4.

Alors j'ai essayé de faire la même chose:

private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     if (game.IsRunning) 
      game.TerminateGame();    
    } 

Mais je continue à obtenir cette erreur: Une erreur générique est produite dans GDI +. et il pointe vers cette ligne: g.FillRectangle (nouveau SolidBrush (Color.White), 0, 0, 800, 640); Je ne sais pas pourquoi cela fonctionne quand j'appuie sur le bouton qui vient de terminer le jeu et pourquoi il ne fonctionne pas lorsque le formulaire se ferme, c'est le même appel de méthode.

Le formulaire se ferme parfaitement si j'appuie d'abord sur le bouton, puis appuyez sur F4, c'est juste quand je presse juste F4 que je continue à obtenir cela.

Des idées?

+0

+1 pour l'idée du projet, puisqu'il s'agit d'une tâche scolaire;) –

Répondre

6

Votre principale erreur (OMI) crée une boucle de vous appeler jeu et Application.DoEvents. Au lieu de cela, vous devez laisser la boucle d'événement UI normale s'exécuter elle-même (via Application.Run(form), et ajouter des timers pour l'animation, etc.)

La raison pour laquelle vous échouez est parce que vous êtes essayer de dessiner après que le formulaire a été fermé - c'est-à-dire que vous dessinez sur un handle Graphics invalide Lorsque le bouton "Terminer" est pressé, je suppose que vous n'êtes pas en réalité fermant le formulaire, d'où l'absence du problème .

Un hack rapide et sale serait d'ajouter une autre:

if (terminated) 
    break; 

après le dernier appel à Application.DoEvents, avant d'essayer de dessiner sur le Graphics - mais cela ne s'attaque pas à la façon plus fondamentale que vous essayez d'utiliser WinForms d'une manière pour laquelle il n'était pas vraiment conçu.

+0

Donc, je devrais sortir la boucle de jeu et la mettre dans le formulaire de Windows à la place? La seule raison pour laquelle je l'ai mise là était que nous avions besoin d'avoir au moins un fichier DLL dans le projet. – Patrick

+1

La "boucle" devrait être implicite en exécutant le formulaire. C'est comme ça que fonctionne WinForms: la boucle est exécutée par WinForms jusqu'à la fermeture du formulaire principal. Pour les occurrences chronométrées (par exemple, les monstres en mouvement), vous utilisez une minuterie. Tout le reste est axé sur les événements. Les minuteurs ne sont pas exactement de haute précision, mais devraient être assez bon pour un projet d'école. –

+0

Ok, merci. Je vais déplacer la boucle de jeu vers le formulaire à la place. – Patrick

0

Vous devez attendre la fin du gameloop. Si ce n'est pas le cas, le code sera exécuté après que divers objets graphiques ont déjà été éliminés, ce qui renvoie l'exception que vous recevez. Pour résoudre ce problème, attendez la fin de la boucle de jeu, puis laissez votre application se terminer.

Comme

if (game.IsRunning) 
    game.TerminateGame(); 
while (game.IsRunning) 
    Continue; 
Questions connexes