2009-06-09 9 views
0

J'ai essayé d'animer en douceur certains emplacements Windows Form mais j'ai quelques problèmes si je veux que la vitesse soit variable. En d'autres termes, si je veux permettre à l'utilisateur de sélectionner la vitesse préférée pour l'animation.Comment animer en douceur l'emplacement de Windows Forms à différentes vitesses?

J'ai trouvé l'article suivant qui m'a aidé à réaliser l'animation que je cherchais, pour ma forme. Il semble mieux dans tous les sens qu'une approche BackgroundWorker ou Threads j'ai essayé dans le passé: http://www.vcskicks.com/animated-windows-form.html

Mon seul problème maintenant, est de maintenir une animation fluide si je veux avoir des vitesses différentes pour l'animation. Il y a deux valeurs qui sont importantes dans mon code: FPS et PX. FPS représente les images par seconde (quoi d'autre) et PX représente le nombre de pixels pour déplacer le formulaire. Pour avoir l'animation la plus douce possible, je préférerais que le formulaire bouge 1px à la fois mais je ne pense pas que je serai capable de déplacer le formulaire aussi vite que je le veux. . Augmenter la valeur FPS à une valeur très élevée ne semble pas avoir d'effet, c'est comme s'il y avait une limite et au-dessus de cette limite, il n'y aurait pas de différences visibles. Je suis sûr qu'il y a une bonne explication à cela.

Ma question est la suivante: Avez-vous une bonne solution à ce problème ou la seule solution est de changer la valeur PX et de déplacer le formulaire de plus de 1px si je veux un mouvement plus rapide? Si la solution pour la question ci-dessus est de changer la valeur PX en conséquence, j'ai découvert (en testant différentes valeurs) qu'une valeur FPS égale à 300 suffirait à mon besoin de déplacer le formulaire comme lent et aussi vite que je le veux. Ensuite, si je voulais 10 vitesses, déplacer le formulaire par 1, 2, 3, 4, 5, 6, 7, 8, 9 et 10 pixels fournit des animations lisses et rapides, comme je le veux. Si je voulais 5 vitesses, je pourrais utiliser 2, 4, 6, 8, 10, par exemple.

Ma question ici est: Y at-il un problème à utiliser une valeur de 300 pour FPS? Y a-t-il de mauvaises conséquences pour une telle valeur?

Et voici mon code actuel:

public partial class Form1 : Form { 

    bool dir = true; 

    public Form1() { 
     InitializeComponent(); 

     Location = new Point(1280/2 - Width, 800/2 - Height/2); 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     double FPS = 300; 
     int PX = 1; 
     long lastTicks = 0; 
     long currentTicks = 0; 
     double interval = (double)Stopwatch.Frequency/FPS; 

     while(dir ? Left <= 1280/2 : Left >= 1280/2 - Width) { 
      Application.DoEvents(); 

      currentTicks = Stopwatch.GetTimestamp(); 

      if(currentTicks >= lastTicks + interval) { 
       lastTicks = Stopwatch.GetTimestamp(); 

       this.Location = new Point(dir ? Left + PX : Left - PX, Top); 

       this.Invalidate(); //refreshes the form 
      } 

      Thread.Sleep(1); //frees up the cpu 
     } 

     dir = !dir; 
    } 

} 

Note: Ceci est juste un exemple de code, à des fins de test, le code pas réel mais être mon invité si vous voulez signaler certaines choses très importantes que je devrait considérer quand portage ceci à l'application réelle.

+1

La limite devrait être la fréquence de rafraîchissement de votre moniteur: 60Hz pour un TFT typique, qui est effectivement de 60 FPS. – VVS

Répondre

4

Essayez cette mise en œuvre de ma suggestion avant (sans tenir compte des FPS):

public partial class Form1 : Form 
{ 
    private bool go; 
    private int dx = 1; 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     if (go) 
     { 
      this.Location = new Point(this.Location.X + dx, this.Location.Y); 
      if (Location.X < 10 || Location.X > 1200) 
      { 
       go = false; 
       dx = -dx; 
      } 
      else 
      { 
       this.Invalidate(); 
      } 
     } 
    } 
    private void button1_Click(object sender, EventArgs e) 
    { 
     go = true; 
     this.Invalidate(); 
    } 
} 

Je pense que vous aurez probablement à aller à l'extérieur de WinForms pour obtenir FPS plus élevé.

1

Je pense que Windows limite le taux de repeint, donc ce n'est pas grave si vous avez poussé le FPS jusqu'à des valeurs insensées; Si vous voulez voir des fréquences d'image plus élevées, vous devrez probablement créer quelque chose comme l'animation XNA/DirectX.

Vous pouvez utiliser un temporisateur et écrire un gestionnaire d'événements écoulé qui déplacerait tous les deux & pour invalider votre formulaire. À cette fin, vous n'auriez pas à faire le Thread.Sleep ou la tenue de livres avec les dernières mesures et intervalles de temps, et cela se produirait avec une cadence régulière. De plus, au lieu du code conditionnel autour du booléen 'dir', vous pouvez annuler la valeur PX lorsque vous voulez changer de directions (et faire des additions seulement au lieu de l'opérateur ternaire sur dir); c'est possible puisque la soustraction est la même que l'addition d'un négatif. Cela devrait rendre votre animation plus facile à étendre pour faire d'autres choses. Pour le plaisir, vous pouvez également créer un PY pour se déplacer verticalement. Quoi qu'il en soit, j'espère que vous vous amuserez avec ça.:)

+0

Une minuterie ne permet pas la précision que je recherche. Et je suis sûr que vous n'avez même pas lu le lien que j'ai posté parce que le Thread.Sleep() est là uniquement pour une raison et que la raison n'est pas de contrôler la vitesse d'animation, mais comme le dit le commentaire, libérer le CPU. Sans cette ligne, l'utilisation du processeur sera de 100% pendant l'animation. –

+0

Je viens de lire le lien, beaucoup plus court que prévu. J'essaie d'aider ici. Je m'attendrais à ce que la minuterie winforms soit d'une durée plus longue que la classe Threading.Timer, car elle fonctionne probablement à partir de l'événement Windows WM_TIMER. En excluant les temporisateurs, pourquoi ne pas surcharger OnPaint() et calculer la nouvelle position en fonction de l'intervalle entre les appels OnPaint()? Cela me semble plus propre que de faire toute l'animation en un seul appel de méthode. Je suppose aussi que c'est pour l'animation de contrôle et que vous n'essayez pas de le faire pour un jeu quelconque, n'est-ce pas? – devgeezer

+0

OnPaint ne sera appelé qu'en cas de besoin, et non lorsque j'ai besoin de déplacer le formulaire. De toute façon, je ne pense pas que ce soit proche d'une bonne solution pour faire n'importe quel type d'animation. Mais cela peut être juste moi ... Qu'est-ce qui est si mauvais en faisant une animation dans un appel de méthode? Comment est-ce "sale"? Il me semble assez propre et utilise l'horloge du système pour produire une animation fluide sur tous les systèmes. Semble la solution parfaite en réalité. Et c'est ce que je vais utiliser (très probablement), donc, inutile d'en discuter plus avant. De toute façon, cela n'a rien à voir avec mes questions/problèmes. –

-1

super Over-Kill Solution

Résumé: faire une animation de votre mouvement de la fenêtre, et le lire (mode plein écran, peut-être)

Détails:
Supposons que votre fenêtre est 100x100, et est @ 0,0
Prenez une capture d'écran de l'écran, bien, (0,0) - (200,200). Utilisez la capture d'écran pour créer un clip, qui représente le déplacement de votre fenêtre de 0,0 à 100,100
Créez ensuite une fenêtre sans bordure (0,0) - (200,200) et placez un lecteur vidéo dessus. rejoue l'animation de ta fenêtre qui bouge à l'intérieur.

Inutile de dire que votre fenêtre sera statique. Mais vous pouvez obtenir la meilleure animation possible. Vous pouvez même ajouter quelques effets à votre fenêtre en mouvement, comme des balles dans la matrice, ou des vaisseaux Necromunga.

0

Si vous obtenez les résultats que vous voulez avec une valeur FPS de 300 alors je voudrais aller avec ça. Le concept des images par seconde pour WinForms n'est pas le même que celui des jeux vidéo gourmands en graphismes, donc une valeur élevée ne sera pas un problème. La valeur FPS ici ajuste simplement la fréquence d'exécution du code.