Objekte auf Hintergrund mit GDI (Suche nach Optimierungsmöglichkeiten)

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Nijin.

    Objekte auf Hintergrund mit GDI (Suche nach Optimierungsmöglichkeiten)

    Hallo Community!

    Erstmal freu ich mich nun auch hier zu sein. Gute Tutorials hab ich mir hier bereits als Gast angeschaut.
    Da ich mich laaaangsam in richtung Spieleprogrammierung vorantasten möchte, habe ich damit angefangen eine klitzekleine Spiele-Engine zu schreiben.

    Ziel von ihr soll es sein, dass man mehrere "Objekte" hat, die auf einem Hintergrundbild dargestellt werden. (Die soll man dann in späteren Schritten auch bewegen können. Aber das sollte ich dann wahrscheinlich selbst hinbekommen.)

    Das Programm ist auch soweit, dass es Ergebnise anzeigt. :)
    Das Problem liegt momentan aber noch in 2 Punkten:
    1.) Wenn ich die Objekte zeichne, "flackern" diese. Irgentwie würde sich das Problem mit einem "Bilderbuffer" lösen lassen. Aber ist das dafür wirklich die inteligenteste Lösung?
    2.) Die Performance. Bereits bei einem Objekt meldet der Taskmanager eine CPU-Auslastung von knapp 8%. Wenn später noch weitere Prgrammteile dazukommen fürchte ich, dass sich das doch sehr stark hochschaukelt.

    Deswegen wollte ich mal fragen ob jemand mir hier Vorschläge geben kann, wie ich das Programm verbessern kann.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public Structure Bildobjekte_struct 'Die späteren Objekte
    3. Public info As String 'Hier kann z.B. ein Name
    4. Public bild As Image 'Das aussehen des Objekts
    5. Public x As Int16 'Wo es in X-Richtugn ist
    6. Public y As Int16 'und in y-richtung
    7. Public gesch As Double 'Die geschwindikeit. Noch ohne Zweck
    8. Public winkel As Double 'Die Richtung, noch ohne Zweck
    9. End Structure
    10. Const ziel_fps As Int16 = 50 'Die gewünschten Bilder pro Sekunde
    11. Dim Anzahl_bildobjekte As Int16 = 0
    12. Dim Bildobjekte() As Bildobjekte_struct
    13. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    14. Timer1.Enabled = True 'male das Hintergrundbild.
    15. End Sub
    16. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    17. 'Hiermit wird ein neues Bildobjekt erstellt.
    18. ReDim Bildobjekte(Anzahl_bildobjekte)
    19. Bildobjekte(Anzahl_bildobjekte).info = InputBox("Wie soll das Objekt heißen?", "Informationen benötigt.", "Fußball")
    20. With Bildobjekte(Anzahl_bildobjekte)
    21. .bild = My.Resources.fussball2
    22. .x = InputBox("X-Position", "Informationen benötigt.", "10")
    23. .y = InputBox("Y-Position", "Informationen benötigt.", "10")
    24. .gesch = 0
    25. .winkel = 0
    26. End With
    27. Anzahl_bildobjekte += 1
    28. End Sub
    29. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    30. 'Dieser Timer malt alle ziel_fps Sekunden das Bild.
    31. Timer1.Interval = ziel_fps 'stellt die gewünschten FPS ein.
    32. Dim graphic As Graphics = Me.CreateGraphics
    33. Dim bg As Image = My.Resources.Background
    34. Zeichne_BG(bg, graphic)
    35. Zeichne_Bildobjekte(graphic)
    36. End Sub
    37. Public Sub Zeichne_BG(ByVal bg As Image, ByVal graphic As Graphics)
    38. Dim nullpunkt As Point
    39. nullpunkt.X = 0
    40. nullpunkt.Y = 0
    41. graphic.DrawImage(bg, nullpunkt)
    42. End Sub
    43. Public Sub Zeichne_Bildobjekte(ByVal graphic As Graphics)
    44. If Not Anzahl_bildobjekte = 0 Then
    45. For c As Int16 = 0 To Anzahl_bildobjekte - 1
    46. Dim punkt As Point
    47. punkt.X = Bildobjekte(c).x
    48. punkt.Y = Bildobjekte(c).y
    49. graphic.DrawImage(Bildobjekte(c).bild, punkt)
    50. Next c
    51. End If
    52. End Sub
    53. End Class


    My.Resources.Background ist ein hintergrundbild mit farbübergängen (bmp)
    My.Resources.fussball2 ein png-Bild eines Fußballes mit Transparents.

    Ich hoffe, das ist kein komplett Hoffnungsloser Fall :) (Bitte möglichst umfangreich/einfach antworten - mit Grafik habe ich noch nie etwas gemacht.)
    das das bild nicht falckert muss:

    VB.NET-Quellcode

    1. Public Sub Zeichne_Bildobjekte(ByVal graphic As Graphics)
    2. If Not Anzahl_bildobjekte = 0 Then
    3. For c As Int16 = 0 To Anzahl_bildobjekte - 1
    4. Dim punkt As Point
    5. punkt.X = Bildobjekte(c).x
    6. punkt.Y = Bildobjekte(c).y
    7. graphic.DrawImage(Bildobjekte(c).bild, punkt)
    8. Next c
    9. End If

    durch das:

    VB.NET-Quellcode

    1. Public Sub Zeichne_Bildobjekte(ByVal graphic As Graphics)
    2. If Not Anzahl_bildobjekte = 0 Then
    3. For c As Int16 = 0 To Anzahl_bildobjekte - 1
    4. Dim punkt As Point
    5. punkt.X = Bildobjekte(c).x
    6. punkt.Y = Bildobjekte(c).y
    7. graphic.DrawImage(Bildobjekte(c).bild, punkt)
    8. Timer1.Stop()
    9. Next c
    10. End If
    11. End Sub

    ersetzt werden.
    wie gehts: Ich hab nur ein timer.stop event eingefügt, sonst wird das bild immer wieder gemalt.
    ich hoffe ich konnte dir helfen.
    ganz einfach -> mach das Zeichnen im Paint Event, dann wird es auch nur gezeichnet, wenn nötig(bzw. evtl. im Timer Event mit einem Me.Invalidate) das Flackern verhinderst du mit Me.SetStyle und DoubleBuffering ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Hallo UFO, danke für den Vorschlag, aber das bewirkt, dass der Timer komplett angehalten hat. Was nicht ganz meine Absicht war, da z.B. weitere Grafikelemente nicht geladen werden.

    Hallo jvbsl, auch dir danke. Das mit dem DoubleBuffering habe ich mir auch schon überlegt, jedoch keine zufriedenstellende Lösung für mich gefunden.

    Ich habe das Grundkonzept nunmal komplett überarbeitet und einen absolut neuen Code dafür. (Nachdem ich endlich ein Tutorial zum Erstellen von eigenen Klassen gefunden habe mit dem ich genau das gerlernt habe was ich brauchte.)

    Der neue Code selbst hat momentan noch 1 oder 2 unbeabsichtigte Efekte - angenommen ich würde dafür weitere Hilfe brauchen (ich versuchs jetzt erstmal noch weiter mit rumprobieren udn googlen) - sollte man dann ein neues Thema eröffnen oder hier reinposten? Die Problematik ist dann ja etwas anderes.
    (Ihr könnt auch gerne per PM antworten, wenn es sonst heir zu unübersichtlich wird)

    Wünsche euch einen schönen Start in die Woche :)