Hey Leute!
Ich arbeite jetzt schon seit einer Weile an einem netten Spiel für Android, bin jetzt allerdings auf ein kleines Problem gestoßen…
Also: Es gibt verschiedene Situationen in denen das Spiel pausiert wird und über dem eigentlichen Bild ein Fenster auftaucht (zum Beispiel bei Ja/Nein Dialogen).
Um das ganze schöner und übersichtlicher zu gestalten wird währenddessen der Hintergrund mit einem grauen „Filter“ überzeichnet (bzw. eigentlich nur mit „canvas.drawARGB(100, 0, 0, 0);“).
Seit dem ich diesen „Filter“ eingebaut habe stürzen die FPS auf einmal während den Dialogen extrem herab. Um zu prüfen ob das wirklich an der Methode liegt habe ich mir einen kleinen Debugger gebastelt, der die benötigte Zeiten für einzelne Schritte misst:
Collected Time Data:
- ticking: 82 MS
- draw: 82 MS
- draw components: 7 MS
- draw special text: 67 MS
- draw gray transparent background: 50 MS //Besteht nur aus "canvas.drawARGB(100, 0, 0, 0);"
- draw components above gray filter: 4 MS
- draw current text: 13 MS //Hier kommt auch ein extra transparenter grauer Hintergrund hinter dem zu zeichnenden Text vor
- rest: 8 MS
→ Der Beweis: Die Methode verbraucht extrem viel Arbeitspeicher
Bei leistungsstarken Handys ist das zwar kein Problem, aber bei schwächeren Handys kann dann sogar der Dialog anfangen zu laggen (Während das Spiel selbst 100% flüssig läuft)… Vor allem auf einem Tablet laggen die Dialoge extrem, da wegen der großen Auflösung auch jede Menge Pixel berechnet werden müssen.
So jetzt meine Frage:
Habt ihr vielleicht irgendwelchen Ideen/Tipps?
Ich finde den grauen „Filter“ echt sehr wichtig, da er gut aussieht und vor allem auch damit der Spieler erkennt, dass der Hintergrund im Moment nicht „aktiv“ ist bzw. ausgeblendet ist.
Die canvas.drawARGB Methode stammt direkt von Android und sollte deswegen so effizient geschrieben sein wie möglich. Das heißt, es ist vielleicht prinzipiell nicht möglich effizienter den Bildschirm mit einer transparenten Farbe zu füllen, da es einfach aufwändig ist z.B. 1920*1080 = 2073600 Pixel zu erkennen und deren Farbe zu modifizieren…
Dann Frage ich mich aber, wieso das Zeichnen des gesamten Hintergrunds so vergleichsweise wenig Zeit braucht (Mögliche Antwort: Weil da die Pixel nur auf einen Wert gesetzt werden, während bei meiner Methode jeder Pixel erst erkannt, eine richtige Farbe ausgerechnet und schließlich erst die Farbe gesetzt werden kann).
Ich nehme an, dass es keinen besseren Weg gibt, diesen grauen Filter zu zeichnen… Falls ihr doch einen kennt, dann wäre ich euch ewig dankbar
Möglicher Lösungsweg (Bin unzufrieden damit)
[ol]
[li]Aktuelles Bild im Spiel erkennen (Hintergrund, Komponenten usw.)[/li][li]Den grauen „Filter“ darüber zeichnen[/li][li]Das Bild in eine Variable speichern[/li][li]Die ganze Zeit anstatt den normalen Hintergrund, die Komponenten, den grauen Filter usw. zu zeichnen einfach direkt das Bild aus der Variable nehmen[/li][/ol]
Damit bin ich allerdings nicht ganz zufrieden, da:
[ol]
[li]Die verschiedenen Bilder die aktuell im Hintergrund gezeichnet werden sollten im Arbeitspeicher bleiben, da sie nach dem Dialog sofort wieder gebraucht werden. Speichert man jetzt noch zusätzlich das komplette Bild → Doppelte Besetzung im Arbeitspeicher[/li][li]Im Moment werden viele einzelne Bilder relativ klein geladen und zum Anzeigen gezoomt (Allerdings unterschiedlicher Zoom für verschiedene Bildteile. z.B. bei einem Tablet: Hintergrund wird über Bild gestreckt, mit Wert X gezoomt aber Button wird an Pixeldichte angepasst, mit Wert Y gezoomt). Dadurch verbrauchen die geladenen Bilder gesamt relativ wenig Arbeitspeicher. Wenn ich jetzt das komplette aktuelle Bild bei eine Tablet festhalte verbrauche ich viel mehr Arbeitspeicher, als wenn ich nur die einzelnen Komponenten ohne Zoom geladen habe [/li][/ol]
→ Der Lösungsweg verbaucht ziemlich viel Arbeitspeicher, allerdings lässt er das Spiel flüssiger verlaufen, sobald einmal alles geladen ist.
Ansonsten fällt mir leider nichts ein…
Habt ihr vielleicht irgendwelchen Ideen?
Mit freundlichen Grüßen
Felix