Auto mit GDI+

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von JGF.

    Auto mit GDI+

    Hallo,

    Ich wollte ein "Auto" machen, dass man mit den Pfeiltasten (hoch, rechts und links) steuern kann und zwar, wenn man nach links oder rechts drückt, dreht das Auto sich in die Richtung. Wenn man nach oben drückt, fährt es in die derzeitige Richtung, abhängig davon wie es gedreht ist.
    Ich bin bis hier hin gekommen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Dim Winkel As Integer = 0
    4. <DllImport("user32.dll")> _
    5. Private Shared Function GetAsyncKeyState(ByVal vKey As Int32) As Int16
    6. End Function
    7. Dim Posx As Integer = 0
    8. Dim Posy As Integer = 0
    9. Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    10. Dim RP As New Point(325, 350)
    11. Dim Q As New Rectangle(300, 300, 50, 100) ' Das Rechteck
    12. Dim t As New Drawing2D.Matrix
    13. t.RotateAt(Winkel, RP)
    14. t.Translate(Posx, Posy)
    15. e.Graphics.Transform = t
    16. e.Graphics.FillRectangle(Brushes.Black, Q)
    17. End Sub
    18. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    19. Dim TOben As Boolean = ((GetAsyncKeyState(Keys.Up) And &H8000) <> 0)
    20. Dim TRechts As Boolean = ((GetAsyncKeyState(Keys.Right) And &H8000) <> 0)
    21. Dim TLinks As Boolean = ((GetAsyncKeyState(Keys.Left) And &H8000) <> 0)
    22. If TOben = True Then
    23. Posx = 0
    24. Posy = 0
    25. Invalidate()
    26. End If
    27. If TRechts = True Then
    28. Winkel += 1
    29. Invalidate()
    30. End If
    31. If TLinks = True Then
    32. Winkel -= 1
    33. Invalidate()
    34. End If
    35. End Sub
    36. End Class

    und brauche jetzt Hilfe für das Vorwärtsfahren.

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

    Ich dachte mit der Eigenschaft Translate wird dieses Problem sowieso umgangen, jedoch bewegt sich das Rechteck nur einmal, wenn ich Pfeiltatse nach oben drücke.
    Wieso importierst du eine Api und einen unnützen Timer, wenn es ein KeyDown-Ereignis gibt ?????????

    VB.NET-Quellcode

    1. Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    2. Me.KeyPreview = True
    3. If e.KeyCode = Keys.Up Then
    4. 'Blablabla
    5. End If
    6. End Sub
    Wenn mehr als ein Tastensignal eingehen, wird das KeyDown-Event meines Wissens untauglich, da es nur 1 Taste erkennen kann. Des Weiteren ist das Thema eigentlich unrelevant, da die Funktionen des Timers für meine Zwecke ausreichen sollten. ;)
    Soll das Auto permanent fahren (also nicht mehr zu stoppen sein), oder soll es nur fahren, wenn die Taste gedrückt ist?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Ich habe den Code jetzt umgeformt, doch das Rechteck verhält sich sehr seltsam:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Steht unter der Form1.Paint-Klasse
    2. Dim RMx As String = 325 'Rotationsmittelpunkt (x-Koordinate)
    3. Dim RMy As String = 350 'Rotationsmittelpunkt (y-Koordinate)
    4. Dim RP As New Point(RMx, RMy) 'Punkt, um den rotiert wird
    5. 'Steht im Timer, der für die Tastenerkennung zuständig ist
    6. If TOben = True Then 'Wenn auf die Pfeiltaste nach oben gedrückt wird, dann
    7. Posy += 1 'Anzahl der bereits verschobenen Pixel für das '.Translate(Posy)' was in der Zeichen-Klasse steht
    8. RMx = Math.Cos(Winkel) * Posy + 325 'fehlgeschlagener Versuch, die Koordinaten zu berechnen
    9. RMy = Math.Sin(Winkel) * Posy + 350 'fehlgeschlagener Versuch, die Koordinaten zu berechnen
    10. Invalidate()
    11. End If


    Also es geht jetzt darum, die Koordinaten des Punktes zu finden, um das das Rechteck gedreht werden muss, sprich man muss die Koordinaten vom Mittelpunkt des Rechtecks finden
    Kann mir jemand helfen?

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „JGF“ ()

    also imo kann das so nix werden.

    Imo brauchst du eine Klasse Auto, mit den Properties Location As Point und Orientation As Integer (Winkelbezeichnung in degree)
    diese Klasse kann vom Timer regelmäßig angestoßen werden um ihre Loacation und Orientation anhand des Tastaturzustandes zu überprüfen.
    Ergibt sich eine Änderung, so muß sie ihre vorherige Begrenzungsfläche invalidieren, und dann die neue BegrenzungsFläche ebenfalls.
    Infolge der Invalidierung tritt ja das Paint-Event auf, und da muß die Auto-Klasse sich selbst zeichnen können - die Daten dafür (Location und Orientation) enthält sie ja.

    Also im wesentlichen brauchst du ziemlich genau Control mit beweglicher Figur

    Nur die im GraphicsPath eingespeicherte Figur sieht bei dir anders aus.
    Und die Steuerung von Orientation und Location erfolgen bei dir nicht per Maus, sondern via TastenCodes.
    Ok danke,

    ich habe keine Klasse erstellt, sondern habe es mit Variablen versucht. Das Tutorial vom dem Link verstehe ich nicht wirklich und wirkt mir ziemlich kompliziert?( ^^
    Deshalb ist meine Frage jetzt, wie die Formel lautet, mit der man eben die Mittelpunktskoordinaten für das Rechteck findet.
    Mir ist nur klar, dass man dafür wohl den Winkel und sin oder cos braucht.
    :D Ja das ist mir schon klar, aber ich hänge immer noch bei der "Orientation und Location"-Klasse fest, weil ich nicht weiß, wie man da anfangen soll, ich habe es ja schon probiert, jedoch ohne Erfolg.
    Mit dem "Mittelpunkt" war ja nur gemeint, dass dessen Koordinaten ja letztendlich das sind, was ich suche, weil ich um den Punkt drehen will.
    Man hat ja den Anfangsmittelpunkt, nämlich P(325|350) um den gedreht wird. Und den will ich mit einer Formel bei Verschieben des Rechtecks anpassen.
    imo kommste um Control mit beweglicher Figur nicht drumrum.
    Die Auto-Klasse kennt nicht nur ihre Location, sondern auch ihre Begrenzungen, das ist nämlich ein Rechteck. In Control mit beweglicher Figur habe ich dieses Rechteck "Bounds" genannt.
    Und da das Auto seine Bounds kennt, kanns ja mit Leichtigkeit seinen Mittelpunkt berechnen.
    Ah ok,
    und wie rufe ich diese Bounds meines bestimmten Rechtecks als Zahlenwert auf? Gibt's da ein Befehl für?

    //Edit: Ich meine: Kann man von einem gezeichneten Objekt(Rechteck) mit GDI+ die Koordinaten des Rechtecks bekommen, oder nicht, oder welche Möglichkeiten hat man sonst? Ich dachte ja man registriert jede Bewegung und und berechnet die Koordinaten relativ zu dem am Anfang gewählten Mittelpunkt (in dem Fall P(325|350)). Für ein Codebeispiel wäre ich sehr dankbar.

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

    Edit: Ich habe angefangen, bevor Post #12 gepostet wurde, deshalb kommt das etwas unpassend. Lasst euch in eurer Diskussion nicht stören :D

    @JGF:
    Bezüglich Tastendrucks:
    Das KeyDown-Ereignis wird öfters aufgerufen, wenn Du die Taste gedrückt hältst. Und zwar genau so, wie z.B. Buchstaben in den Editor eingefügt werden.
    Tippst Du nur einmal, ist es z.B. nur "h". Aber hältst Du die Taste gedrückt, dann kommt zuerst nur "h", dann, kurze Zeit später werden viele weitere "h"s eingefügt: "hhhhhhh".

    Dazu würde ich vorschlagen, eine eigene Klasse "KeyHelper" o.ä. anzulegen, die dieses Verhalten ausbessert:

    Zwei Events: KeyDown und KeyUp
    Eine Variable vom Typ Boolean: IsKeyDown
    Eine Variable vom Typ Keys: Key
    Eine Function: TrySetKeyDown(PressedKey As Keys) As Boolean
    Eine Function: TrySetKeyUp(PressedKey As Keys) As Boolean

    Erklärungen:

    Die Events sollten ziemlich selbsterklärend sein. KeyUp/Down wird ausgelöst, wenn die entsprechende Taste gedrückt/losgelassen wurde. Anzumerken ist, dass die Events jeweils nur einmal ausgelöst werden.

    Die Variable IsKeyDown wird zum Merken verwendet, ob TrySetKeyDown() schon aufgerufen wurde.

    Die Variable Key beinhaltet den verknüpften KeyCode. Also z.B. Keys.Up, wenn die Nach-Oben-Taste bei den Pfeiltasten gemeint ist, oder Keys.W, wenn die W-Taste gemeint ist.

    Die Funktion TrySetKeyDown prüft, ob der angegebene KeyCode der Variable Key entspricht. Ist das der Fall, wird geprüft, ob IsKeyDown noch nicht True ist. Ist das der Fall, wird IsKeyDown auf True gesetzt und das Event ausgelöst. Es wird True zurückgegeben. Sollte IsKeyDown False sein, wird False zurückgegeben.

    Die Funktion TrySetKeyUp prüft auch, ob der angegebene Keycode der Variable Key entspricht. Ist das der Fall, wird IsKeyDown auf False gesetzt, das KeyUp-Ereignis ausgelöst und True zurückgegeben. Falls nicht, wird False zurückgegeben.

    Dadurch lässt sich im Code einfach folgendes schreiben:

    VB.NET-Quellcode

    1. 'In der OnKeyDown-Methode der Form
    2. For Each i In (Alle Instanzen von KeyHelper)
    3. If i.TrySetKeyDown(e.KeyCode) Then
    4. Exit For 'Sobald der erste zutreffende KeyHelper gefunden wurde, ist klar, dass es keine weiteren zutreffenden mehr geben kann.
    5. End If
    6. Next

    Bei Zeile 3 wird weitergehend dann das KeyDown-Event der KeyHelper-Klasse aufgerufen, auf das reagiert werden kann. Wenn die Methode nochmal ausgeführt wird, wird das Event nicht mehr ausgelöst.
    Erst, wenn folgendes ausgeführt wird, wird das KeyDown-Event wieder ausgelöst:

    VB.NET-Quellcode

    1. 'In der KeyUp-Methode der Form
    2. For Each i In (Alle Instanzen...)
    3. If i.TrySetKeyUp(e.KeyCode) Then
    4. Exit For
    5. End If
    6. Next


    Damit ist das Problem gelöst, dass die KeyDown-Methode mehrmals ausgeführt wird, obwohl nur einmal gedrückt wurde.

    Weitergehend: Sobald Du das so wie ErfinderDesRades mit Klassen implementiert hast, kannst Du einfach auf das KeyDown-Event jeder Instanz reagieren und entsprechend die Richtung der Auto-Klasse setzen. Beim KeyUp-Ereignis wird das Auto gestoppt.
    Bei jedem Timer-Tick wird die Position des Autos anhand der Richtung neu berechnet.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Diese Antwort ist ziemlich genial und ich werde sie später einbauen, vielen Dank :thumbsup:

    Zu dem anderen Thema (Rechteckkoordinaten) kann ich nur sagen: Ich glaub niemand versteht, was ich suche^^