Laden...

GDI - Bitmap rotieren - Performance besser machen?

Erstellt von IsaacCohen vor 8 Jahren Letzter Beitrag vor 8 Jahren 2.507 Views
I
IsaacCohen Themenstarter:in
15 Beiträge seit 2015
vor 8 Jahren
GDI - Bitmap rotieren - Performance besser machen?

Guten Morgen,

ich möchte einen Asteroids-Clone mit GDI programmieren. Das Game soll keine Engines oder sonstige zu installierende Bibliotheken verwenden.

Im Gegensatz um ursprünglichen Asterorids bleibt der Spieler nach oben ausgerichtet in der Mitte und die Objekte und Map drehen und bewegen sich um den Spieler. Ursprünglich sollte es nur einfachste 2D-Vektorgrafik werden und damit gibt es auch bis jetzt keine unlösbaren Probleme.

Jetzt steigen die Ansprüche mit dem Fortschritten. Es soll jetzt als Hintergrund ein Bild des aktuellen Desktops verwendet werden. Die Rotation einer Bitmap um X Grad in voller Bildschirmauflösung braucht auf meinem sehr schnellen Rechner 15 - 30ms. Ich verwende Graphics.DrawImage mit DestinationPoints zum drehen, das ist nach den ersten Tests schneller als Graphics.RotateTransform.

Leider scheint damit das Ende der Möglichkeiten erreicht. Die Rotation müsste erheblich schneller werden. Vielleicht kennt jemand von euch doch noch eine Möglichkeit? Es kann auch irgend ein Trick sein, Farbtiefe verringern hat z.B. kaum Auswirkungen. Ich zeichne auf einen Buffer der dann in die Form übertragen wird. Vielleicht ist der Ansatz mit der Form auch falsch?

Ich bilde mir die Rotation um den Spieler unbedingt ein und möchte das ungern aufgeben (obwohl das ganze Game auf einen Schlag um 90% schneller und einfacher laufen würde wenn sich der Spieler dreht und bewegt).

4.942 Beiträge seit 2008
vor 8 Jahren

In welchen Gradschritten benötigst du denn die Bilder? Du könntest sie z.B. zu Beginn einmalig berechnen und dann in einem Array speichern, so daß du dann nur noch die Bitmaps direkt zeichnen müßtest.

I
IsaacCohen Themenstarter:in
15 Beiträge seit 2015
vor 8 Jahren

Leider geht das nicht, da sich der Spieler auch bewegen kann und dabei den Rotationsmittelpunkt verschiebt. Ansonsten ware das eine super Idee. Etwa 1 bis 5 Grad sind in einem Frame geplant, man könnte eine speicherschonendes Format verwenden und für jede mögliche Position den Hintergrund verkleinern, berechnen und dann skalier....

Vielleicht den Hintergrund generell in der Größe skalieren? Das wäre zu testen bei welchen Faktor das noch gut aussieht . Mal testen wie sich die Interpolation auf die Performance auswirkt, falls das wenig Einfluß hat könnte der Hintergrund relativ klein werden und wäre trotzdem nicht verpixelt. Bei Verringerung um die Hälfte verringert sich die Anzahl der zu berechnenden Pixel auf 1/4. Sollte die Rotation auch um 3/4 der Zeit verringern.

Vielleicht gibt es doch noch schnellere Möglichkeiten? Letzendlich kann man am Ende alles was die Performance verbessert kombinieren.

Einen Nachteil gibt es bei der Skalierung: Aktuell wird jedes Frame unrotiert aufgebaut, der Cameraausschnitt und Mittelpunkt berechnet und dann für die Ausgabe jedes Objekt um den Mittelpunkt gedreht. Falls das drehen der Bitmap klappen würde könnte man den Buffer als Image rotieren und erspart sich das nochmalige drehen der Objekte. Das würde bei einer Skalierung des Hintergrunds nicht möglich sein.

Für eine Roation muss, zumindest für einen 45 Grad Ausschnitt, für jeden Punkt der Vektor über die Länge zum Mittelpunkt berechnet werden. für die anderen Ausschnitte können die einmal berechneten Vektoren wiedervewendet (negieren, vertauschen) werden. Aber ich denke die GDI-Routinen arbeiten schon so. So etwas wurde früher mit Bit-Verschieben erledigt, hat da noch jemand Ahnung evtl. in Verbindung mit unsafe Code? Vielleicht wäre das einen Test wert.

4.942 Beiträge seit 2008
vor 8 Jahren

Wenn der Spieler sich bewegt, brauchst du doch nur das Hintergrundbild entsprechend verschoben darstellen (kleines bißchen Mathe mit Trigonometrie nötig, wenn ich mich nicht irre).

5.658 Beiträge seit 2006
vor 8 Jahren

Hi IsaacCohen ,

Das Game soll als Easteregg in eine Anwendung integriert werden die im Frühjahr inhouse released wird. Damit es den (etwas humorlosen) Admins vorerst nicht auffällt

Also ich würde ja davon abraten, undokumentierte Funktionen in eine Geschäftsanwendung zu integrieren. Und ich würde auch davon abraten, diejenigen, die für die Funktionsfähigkeit und Sicherheit der Software verantwortlich sind, als "humorlos" zu bezeichnen. Beides könnte auf dich zurückfallen und dich im Zweifel deinen Job kosten.

Christian

Weeks of programming can save you hours of planning

127 Beiträge seit 2015
vor 8 Jahren

Ich kann das aus eigener Erfahrung bestätigen:
Ich habe mal in einer Firma gearbeitet in der genau das passiert ist.
Es wurde ein Easteregg-Spiel in eine Business-Anwendung eingebaut wurde.
Nachdem das Easteregg gefunden wurde und die Runde gemacht hat, kam eine ziemliche Welle der Entrüstung und Erbostheit auf unsere Firma zu.
Es wurde zwar in unserer Firma keiner entlassen, aber Ermahnungen wurde ausgesprochen.

I
IsaacCohen Themenstarter:in
15 Beiträge seit 2015
vor 8 Jahren

Hallo MrSparkle und hummigbird1, ihr habt natürlich recht und ich habe den Satz im Eingangspost entfernt, für das Problem war es eh nur unbedeutende Hintergrundinformation.

Hallo Th69, beim vertikaler oder horizontaler Bewegung müsste man nicht neu berechnen und kann einfach verschieben. Sobald er sich aber nach einer Bewegung dreht müsste neu berechnet werden weil sich der Cameramittelpunkt mit der Bewegung verschoben hat.

Das Testprogramm steht jetzt, der Ablauf ist wie folgt:

  • Die Bitmap wird erstellt, verkleinert und vorgehalten.
  • Beim drehen wird die verkleinerte Bitmap gedreht.
  • Anschließend wieder auf die ursprüngliche Größe skaliert und ausgegeben.

Es gibt jetzt zwei Buffer, einen für die verkleinerte Bitmap und einen weiteren um zu drehen. Es wird zwar bedeutend schneller, allerdings erst richtig schnell bei einem Faktor von 0,1. Vom Hintergrund ist dann nichts mehr zu erkennen. Zum anderern kommen auch bei 0,1 Faktor einzelne Frames vor die doppelt so lange benötigen.

Kann man hier ein Projekt irgendwie anhängen? Bei Interesse gebe ich das gerne weiter.