Animationen richtig verwenden

  • WPF

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von phil.

    Animationen richtig verwenden

    Hallo,

    ich bin gerade dabei von GDI (Windows Forms) auf WPF umzusteigen.
    Jetzt möchte ich ein kleines "Spiel" programmieren, bei dem (erst mal) ein Kreis mit den Pfeiltasten gesteuert wird. Ideal wäre auch noch Beschleunigung.


    Früher (mit GDI und Timer) habe ich das so gemacht:
    Ich hatte ein Objekt mit den Eigenschaften: x, y, speedX, speedY (und vill. noch mehr)
    Dieses Objekt hatte die Methoden:
    • changeSpeed(x,y)
      hier wurde speedX und speedY verändert
    • doFraction()
      um Reibung zu simulieren wurde hier speedX und speedY verringert
    • doSpeed()
      hier wurde die eigentliche Bewegung ausgeführt:
      x += speedX
      y += speedY
    • redraw(bit as Bitmap)
      hier wurde mit einer GDI-Grafik ein Kreis an die Position x,y auf das Bitmap gezeichnet
      dieses Bitmap wurde dann zurückgegeben
    Das ganze habe ich mit einem Timer gesteuert. Bei gedrückten Pfeiltasten wurde dann die Mehtode changeSpeed() aufgerufen.
    Jedes mal wurde am Schluss die redraw()-Methode aufgerufen und das resultierende Bild auf eine PictureBox gelegt.
    Dabei habe ich das TimerIntervall und die Übergabevariablen bei changeSpeed() so angepasst, dass die Geschwindigkeit annehmbar und die Ruckler minimal waren.

    Kurze Frage:
    Wie findet ihr mein Vorgehen? - alles selbst ausgedacht!
    Hätte ich da (noch mit GDI) etwas verbessern können?


    Jetzt aber wieder zu meiner eigentlichen Frage:
    Wie soll ich das ganze ohne einen Timer machen?
    Ich habe mir das Animations-Tutorial (und andere) von dieser Webcast Reihe angeschaut und habe gemerkt, dass da alles ohne einen Timer, sondern mit Animationen abläuft.
    Da sich bei mir aber alles in der Laufzeit abspielt kann ich keinen vordefinierten Pfad nehmen auf dem sich der Kreis bewegt. Eine weitere Frage ist, wann ich dann die Benutzereingaben mit den Animationen syncronisiere.

    Das war jetzt ganz schön viel Lesearbeit ;) , hoffentlich kann mir der ein oder andere helfen.
    Ein großes Dankeschön schonmal.

    phil schrieb:

    Hätte ich da (noch mit GDI) etwas verbessern können?
    ja.
    Es ist unnötig umständlich, bei jeder Bewegung eine ganz neue Bitmap zu creiern, da drauf zu malen, und die Picturebox-Bitmap auszutauschen.
    Gdi kann direkt auf die Picturebox malen, und dassis zigfach schneller, v.a., weil Gdi sich auch auf den gemalten Ausschnitt beschränken kann.

    in wpf gibts glaub geeignete Objekte, die einen Kreis darstellen können. - guggemol die Uhr in den Wpf-Tutorials von VBP, oder die rundeButtons (die sind besonders einfach).

    Dann plaziere mal einen Kreis auf einem Canvas - das ist schon 75% der Miete - über die Bewegung kann man dann erst anfangen nachzudenken.
    Ich habe es bei komplizierteren Hintergründen so gemacht, dass der Hintergrund nur einmal gezeichnet werden muss und dann abgespeichert wird. Auf dieses Bild habe ich dann draufgezeichnet.
    Das mit der PictureBox geht dann einfach so? :
    Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
    Interessant...

    Zu meiner eigentlichen Frage:
    So weit war ich schon. - Ich denke gerade über die Bewegung nach ;).
    und da wolltest du iwas mit Tasten-Steuerung machen? Was genau hab ich noch nicht verstanden, weil man kann mit Tasten direkt eine Bewegung "befehlen".
    Oder man befiehlt damit eine Beschleunigung.
    Und möglicherweise sind noch weitere Konzepte denkbar.

    auch das Focus-Handling muß bedacht sein. Also ich täte vorschlagen, du verwendest wirklich einen runden Button.
    Der kann den Focus annehmen, und empfängt auch Tastendrücke.

    uiih - das führt auf den Gedanken, mehrere Figuren zu ermöglichen. Und das führt weiter dahin, die Figuren in einem ItemsControl darzustellen, und das Canvas ist dann das PanelTemplate davon.

    Dann könnte man gscheite Viewmodels dazu coden, die die notwendigen Eigenschaften beinhalten, an die die Figuren zu binden wären.
    die Bewegungen könnte man dann per Timer im Viewmodel steuern - da hat man volle Kontrolle - tja - wird mal wieder nix mit dolle Storyboard-Krimskrams :P

    also da kann man sich kunstvoll verkünsteln dran.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ich will ein Objekt folgendermaßen bewegen:
    rechtePfeiltaste --> Objekt bewegt sich nach rechts
    oberePfeiltaste --> Objekt bewegt sich nach oben
    , ...
    Das sieht dann aus, als ob man von oben auf eine Karte schaut, auf der sich ein Männchen (dargestellt durch den Kreis - man sieht nur den Kopf von oben - oder so ähnlich) durch die Pfeiltasten bewegt.



    Focus-Handling möchte ich Global.
    Bis jetzt habe ich imer die GetAsyncKeyState-Methode benutzt. Die ruft immer nur den aktuellen Tastenzustand ab. Da gab es kein Event, weswegen ich es mit einem Timer kombiniert habe.

    Bei einem KeyDown-Event ist das Problem, dass man die Taste jedes mal neu antippen müsste.
    Oder man hat das Problem, dass sich das Event immer wieder wiederholt und man die Geschwindigkeit - bzw. die Zeit zwischen den einzelnen Wiederholungen nicht wie bei einem Timer kontrollieren kann.

    Genau das ist mein Problem. - ich würde es schon gerne mit Events machen, weiß aber nicht, wie man da genau vorgehen sollte
    - und wann man der Animation sagt, dass sie von Punkt1 zu Punkt2 animieren soll. - da sollten auch keine Zeiten sein, in denen sich der Kreis nicht bewegt.



    Dass man Objekte, wie z.B. ein Kreis und eine Linie kombinieren kann, ist mir klar. - Ich habe schon einmal den Fehler gemacht mich bei so etwas zu sehr zu verkünsteln (2 Tage umsonst;)).
    Im Generellen, ein Statement zum Posting:
    Du hast nun vor umzusteigen, ggf. nur, um ein Spiel zu kreieren, dass im Gegensatz zu GDI+, performanter ist.

    WPF rendert mit DirectX, ja, steig doch dann gleich auf SharpDX um.
    Es ist möglich, nur ungewohnt.
    DirectX habe ich schon ausprobiert, das war mir aber zu kompliziert. Davon habe ich jetzt die Nase voll.
    Ich denke WPF ist eine gute Zwischenlösung zwischen GDI und DirectX. Und ist noch gut verständlich.


    Was gibt es da bei einer Ellipse in einem Canvas zu zeigen?
    Meinst du so etwas:

    <Canvas Height="100" Width="100" >
    <Ellipse Name="Ellipse1" Canvas.Left="20" Canvas.Top="40" Height="10" Width="10" Stroke="Black" />
    </Canvas>


    Dein EDIT habe ich noch nicht gesehen:
    Du meinst also, dass ich es wieder mit einem Timer machen sollte - dann kann es doch nicht so schlimm sein, wie viele behaupten;).
    Schade, die Animationen in dem Webcast sahen richtig toll aus. Ich vermute, dass die Perfomance da auch eine ganz andere ist.

    Dann stellt sich wieder die Frage, wie ich es mit dem Input mache.
    Ich gebe zu, dass es mich schon genervt hat, dass sich mein Männchen auch bewegt hat, wenn das Fenster des Programms nich aktiv war. Aber mit dem GetAsyncKeyState ging es nicht anders und so schlimm war es nicht. - Also korrigiere ich mich: Ich kannte keine andere Möglichkeit als global, aber toll wäre es, wenn es nicht global ist.
    Könnte man das villeicht doch mit Events machen?



    EDIT:
    ich habe mir gerade überlegt, dass man von TimerTick zu TimerTick eine Animation von Punkt 1 zu Punkt2 machen könnte.
    Wird das zu aufwendig / Unperformant?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „phil“ ()

    phil schrieb:

    dann kann es doch nicht so schlimm sein, wie viele behaupten
    in einem StoryBoard ist auch nix anneres drin als ein Timer.

    Zu deiner Ellipse: Jo, und jetzt creiere ein ViewModel, und binde Ellipse.Top, Ellipse.Left daran :P

    achnochwas: Bitte VB-Tag benutzen - aber richtig - das gilt ebenso auch for den xml-Tag
    Ok, dann passt das.

    Ich war nur zu faul, auf "Zum Editor wechseln" zu klicken. Das nächste mal mach ichs richtig. - Versprochen!

    Was sagst du zu meinem EDIT?
    Dann könnte man bei meinem selbst erstellten Timer das Intervall etwas größer stellen...
    Aber warscheinlich dauert das dann viel länger, als wenn nur mein Timer läuft?