Grauer Transparenter Filter -> Lag?!

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 :smiley:

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

Nachdem sonst niemand antwortet, spekuliere ich mal, auch wenn ich von Android keine “fundierte” Ahnung habe:

[QUOTE=iFelixxxx]Hey Leute!
-> Der Beweis: Die Methode verbraucht extrem viel Arbeitspeicher


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).
[/QUOTE]

Nicht Speicher. Speicher und Rechenzeit haben nichts (zumindest nicht direkt) miteinander zu tun.

Der Grund, den du angeführt hast, dürfte genau der richtige sein. Bei Farben mit Alpha-Anteil muss relativ aufwändig rumgerechnet werden, um rauszufinden, welche Farbe am Ende auf dem Bildschirm zu sehen ist.

Aber mit ein bißchen Spekulation und einer Mischung aus Bauchgefühl und (so kann man glaube ich doch inzwischen sagen) einem kleinen bißchen Erfahrung mit Swing und BufferedImages heraus: Versuch’ mal, diesen grauen Schleier so zu zeichnen:

    Rect r = new Rect(0, 0, getWidth(), getHeight());
    paint.setColor(Color.BLACK);
    paint.setAlpha(64)
    paint.setStyle(Style.FILL);
    canvas.drawRect(r, paint);   

Ist aber wirklich nur wild ins Blaue geschossen.

Oh manno… Sorry Marco ich habe diese Antwort erst viel zu spät gesehen!
Hoffe du bist mir nicht böse :o

Auf jeden Fall Danke für die Antwort :slight_smile: Probiere das gleich mal aus!

Bisher habe ich das Problem „gelöst“, indem ich im Menü eine Option eingefügt habe, die den transparenten Filter ausschalten kann, dh. dass man optional diese „Lagmaschine“ deaktivieren kann.
Bei Geräten mit sehr großen Bildschirm oder wenig Rechenleistung ist der Filter standardmäßig deaktiviert.

Edit:
Habe sofort mal deine Methode getestet, aber da schenkt sich leider echt kaum etwas…

Das Bild zeigt die benötigte Zeit in MS an, welche für bestimmte Arbeitsschritte benötigt wurde.
Bei dem Test wird gleichzeitig der transparente Filter einmal in meiner alten Methode, und einmal in deiner Methode gezeichnet.

Erklärung zu dem Bild:
„draw gray transparent background1“: Misst die Zeit in MS, die für meine bisherige Methode benötigt wird
„draw gray transparent background2“: Misst die Zeit in MS, die für deine Methode benötigt wird

Ich glaube man kommt um diese sehr aufwändigen und intensiven Rechnungen einfach nicht drum herum.
Die momentan einzigen Optionen sind dann wohl entweder

  1. Damit leben
    oder
  2. Das Bild einmalig zusammen mit dem transparenten Filter berechnen. Dann einfach immer das fertig berechnete Bild zeichnen. ← Verbraucht relativ viel Arbeitsspeicher, falls das originale Bild auch noch geladen sein muss

Hmschade. Die Zeitunterschiede liegen ja um die Messungenauigkeit rum. Naja, war ein Versuch.

Wenn man das Bild einmal kombinieren kann, wäre das ja eine Option. Speicher ist billig und wird schneller mehr, als die Rechenleistung (und verbrät keine Akkulaufzeit :wink: ).

Vielleicht könnte/würde noch jemand was sagen, wenn du ein KSKB (soweit das bei sowas möglich ist) posten würdest (aber ich wäre dann erstmal raus - müßte erstmal mein Android-Testmaschinchen ausgraben, das ansonsten (schon vieeeel zu lange :frowning: ) unbenutzt hier rumliegt…)

Edit: Es gibt hier doch einige Android-Entwickler @Apo , @schlingel & Co - keine Idee dazu?

[QUOTE=Marco13]

Vielleicht könnte/würde noch jemand was sagen, wenn du ein KSKB (soweit das bei sowas möglich ist) posten würdest[/QUOTE]

Ich versuche sobald ich Zeit dafür habe (also hoffentlich morgen) ein kleines KSKB dafür zu basteln :wink:

Spiele-Entwicklung ist nicht meine Stärke. Ich würde das einfach so lösen und die Game-Loop (bzw. die Logik die im Tick ausgeführt werden soll) anhalten. Dann musst du nur einmal ein Bild zeichnen da sich ja im Hintergrund nichts mehr bewegt und das zeigst du dann die ganze Zeit wieder als Hintergrund für den Dialog an. Über das zeichnest du drüber. Ich schätze die Fenstergröße des Dialogs wird sich nicht ändern, dementsprechend musst du auch nur in diesem Bereich neu zeichnen.

Habe jetzt ein kleines kurzes, selbständiges und kompilierbares Beispiel geschrieben:


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends ActionBarActivity {


	private static GameView v;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);	

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

		v = new GameView(this);
		setContentView(v);

		new Thread(new GameThread()).start();
	}



	private class GameView extends SurfaceView{
		public GameView(Context context) {
			super(context);
		}

		public void onDraw(Canvas c){	
			if(c!=null){
				long draw_start = System.currentTimeMillis();
				c.drawColor(Color.RED);
				long draw_time = System.currentTimeMillis();
				Log.i("[DEBUGGER]", "Time needed to draw Background: "+(draw_time-draw_start)+" MS!");


				draw_start = System.currentTimeMillis();
				c.drawARGB(100, 0, 0, 0);
				draw_time = System.currentTimeMillis();
				Log.i("[DEBUGGER]", "Time needed to draw transparent filter: "+(draw_time-draw_start)+" MS!");
			}
		}
	}


	private class GameThread extends Thread{
		@Override
		public void run(){
			while(true){
				displayGame();
				try{
					sleep(20);
				}catch (InterruptedException e){
					//Do nothing
				}
			}
		}

		@SuppressLint("WrongCall")
		private void displayGame(){
			Canvas canvas = null;
			try{
				canvas = v.getHolder().lockCanvas();
				synchronized (v.getHolder()) {
					v.onDraw(canvas);
				}
			} finally {
				if(canvas != null){
					v.getHolder().unlockCanvasAndPost(canvas);
				}
			}
		}

	}

}

Daran lässt sich das Problem wunderbar testen!

Guter Einfall! Es bringt sicherlich auch schon einiges, wenn man den Game-Loop einfach etwas verlangsamt.

Wie ich sehe, nutzt du keine externe Library, sondern pures Android.
Gerade für die Performance beim Zeichnen von mehreren Layern am Besten mit unterschiedlichen Alphawerten rate ich dir dringend zu einer Spielelibrary/engine. Empfehlen kann ich dir libgdx, weil es einfach zu bedienen ist, es viel mitbringt (GameLoop, Partikeleffekte, Physikeffekte etc), es sehr flott ist, es unterschiedliche Plattformen unterstützt und vor allem eine riesige Community dahinter steht.
Es gibt natürlich noch andere Engines (Übersicht über game engines für die Android Spiele Entwicklung). Ich rate dir halt nur, wenn du möchtest das es performant läuft, dann nimm eine. Nur für einfach Spiele kannst du gerne mit pures Android benutzen [ für ein Tic Tac Toe oder einen Snakeklon] =)

			if(c!=null){
                                Bitmap bitmap = Bitmap.createBitmap(c.getHeight(), getWidth(), Bitmap.Config.ARGB_8888);
                                Canvas cv = new Canvas(bitmap);
				
                                long draw_start = System.currentTimeMillis();
				cv.drawColor(Color.RED);
				long draw_time = System.currentTimeMillis();
				Log.i("[DEBUGGER]", "Time needed to draw Background: "+(draw_time-draw_start)+" MS!");


				draw_start = System.currentTimeMillis();
				cv.drawARGB(100, 0, 0, 0);
				draw_time = System.currentTimeMillis();
				Log.i("[DEBUGGER]", "Time needed to draw transparent filter: "+(draw_time-draw_start)+" MS!");

                                c.drawBitmap(bitmap, 0,0,...);
			}
		}
	}

Mal eine ganz unverblümte Frage, wenn ich das bischen Wissen aus Swing übertrage, dann verwendet man dort von Zeit zu Zeit ein BufferedImage, double Buffered Bla-Bla-Bla, damit das ganze schön wird. In Swing erstellt man also ein BufferedImage, zeichnet dann auf diesem Image alles was man zeichnen möchte und wenn man fertig ist, dann nimmt man dieses Bild und zeichnet es auf den Bildschirm über das übergebene Graphics Objekt.

Wenn ich dann https://developer.android.com/guide/topics/graphics/2d-graphics.html#draw-with-canvas lese, dann gibt es sowas für Android auch über Bitmap.

Die Theorie, warum es günstiger ist zuerst in ein BufferedImage/Bitmap zu zeichnen ist die, dass hier zuerst nur im Speicher gezeichnet wird und erst wenn alles fertig ist mit dem Speicher der Grafikkarte kommuniziert wird.

[QUOTE=Apo]Wie ich sehe, nutzt du keine externe Library, sondern pures Android.
Gerade für die Performance beim Zeichnen von mehreren Layern am Besten mit unterschiedlichen Alphawerten rate ich dir dringend zu einer Spielelibrary/engine. Empfehlen kann ich dir libgdx, weil es einfach zu bedienen ist, es viel mitbringt (GameLoop, Partikeleffekte, Physikeffekte etc), es sehr flott ist, es unterschiedliche Plattformen unterstützt und vor allem eine riesige Community dahinter steht.
Es gibt natürlich noch andere Engines (Übersicht über game engines für die Android Spiele Entwicklung). Ich rate dir halt nur, wenn du möchtest das es performant läuft, dann nimm eine. Nur für einfach Spiele kannst du gerne mit pures Android benutzen [ für ein Tic Tac Toe oder einen Snakeklon] =)[/QUOTE]

Das habe ich mir schon oft überlegt, aber so weit wie das Spiel gerade schon ist lohnt es sich nicht mehr umzusteigen. Bisher funktioniert auch alles ziemlich gut (auch bei Handys mit wenig Arbeitspeicher und schlechter Performance). Allerdings habe ich schon geplant, bei meinem nächsten größeren Projekt mit cocos2d zu arbeiten (und dafür dann noch die Sprache C++ zu lernen). Das würde eine enorm gute Performance mit sich bringen und würde einem sogar direkt erlauben mit mehreren Platformen zu arbeiten.

[QUOTE=Unregistered;121129]``` public void onDraw(Canvas c){
if(c!=null){
Bitmap bitmap = Bitmap.createBitmap(c.getHeight(), getWidth(), Bitmap.Config.ARGB_8888);
Canvas cv = new Canvas(bitmap);

                            long draw_start = System.currentTimeMillis();
			cv.drawColor(Color.RED);
			long draw_time = System.currentTimeMillis();
			Log.i("[DEBUGGER]", "Time needed to draw Background: "+(draw_time-draw_start)+" MS!");


			draw_start = System.currentTimeMillis();
			cv.drawARGB(100, 0, 0, 0);
			draw_time = System.currentTimeMillis();
			Log.i("[DEBUGGER]", "Time needed to draw transparent filter: "+(draw_time-draw_start)+" MS!");

                            c.drawBitmap(bitmap, 0,0,...);
		}
	}
}

Mal eine ganz unverblümte Frage, wenn ich das bischen Wissen aus Swing übertrage, dann verwendet man dort von Zeit zu  Zeit ein BufferedImage, double Buffered Bla-Bla-Bla, damit das ganze schön wird. In Swing erstellt man also ein BufferedImage, zeichnet dann auf diesem Image alles was man zeichnen möchte und wenn man fertig ist, dann nimmt man dieses Bild und zeichnet es auf den Bildschirm über das übergebene Graphics Objekt.


Wenn ich dann https://developer.android.com/guide/topics/graphics/2d-graphics.html#draw-with-canvas lese, dann gibt es sowas für Android auch über Bitmap.


Die Theorie, warum es günstiger ist zuerst in ein BufferedImage/Bitmap zu zeichnen ist die, dass hier zuerst nur im Speicher gezeichnet wird und erst wenn alles fertig ist mit dem Speicher der Grafikkarte kommuniziert wird.[/QUOTE]

Was die Performance angeht ist das sicherlich eine gute Sache :) 
In vielen Fällen auch eine gute Lösung, allerdings müssen in meinem Fall die einzelnen Objekte (Bilder), welche du in ein Bild zusammensetzen möchtest, gleichzeitig auch noch einzeln geladen sein.
Öffnet man mitten im Spiel das Pause-Menü, so soll das Spielfeld mit grauem Filter angezeigt werden. Beendet man das Pause-Menü aber wieder, so soll sofort das vorherige farbige Spielfeld wieder angezeigt werden (auf dem sich die einzelnen Objekte bewegen und verändern können). Das heißt in diesem Fall würde deine Lösung relativ viel Arbeitspeicher benötigen.

Es gibt immer mehrere Möglichkeiten aus denen man auswählen kann.

Entweder man berechnet ständig neu dann braucht man halt CPU-Power und Zeit oder man cacht, dann braucht man eben Speicher.

Im ungünstigsten Fall, der hier wohl eingetreten ist, versuchst du alle 20 ms eine Operation anzustoßen die 50 ms (cv.drawARGB(100, 0, 0, 0)) benötigt.

Was passiert denn im ungünstigstern Fall bei dieser Aktion?

Jeder einzelne Pixel wird genommen und dann wird ein Grau draufgerechnet und dies dann gezeichnet. Für jeden dieser 2073600 Pixel! Und das braucht 50 ms.
Ist halt so.

Bei jedem Durchlauf von onDraw ist nach dem Aufruf vom Graufilter das Bild das gleiche wie beim vorigen Aufruf, da das Spiel ja angehalten ist.

Also wird alle 20 ms eine Aktion getriggert die erstens lange braucht und zweitens jedesmal bis zu dem Punkt nach dem Zeichnen des Graufilters, das selbe Ergebnis (Spielfeld + Graufilter) produziert.

Warum also beim Starten des Pause Menus nicht

  • ein einziges mal ein Bitmap anlegen bei dem das Spielfeld + Graufilter gezeichnet werden
  • danach dieses Bitmap zeichnen lassen sowie darauf das Pausemenu.

Beim Beenden des Pause Menus das Angelegte Bitmap des (Spielfelds + Graufilter) disposen, null setzen und schauen das es der GC entsorgt. Kosten dieses Bitmaps sind bei 4 Byte pro Pixel und 2 Mio Pixeln etwa 8 - 10 MB an Arbeitsspeicher die währende der Pause gebraucht werden. Und dann zeichnen wie bisher, da dies ja soweit ganz gut zu funktionieren scheint.

Das geht zwar weg vom ursprünglichen Double-Buffering, sollte aber sich leicht adaptieren lassen.

Cocos2D-X (!) und da bin ich aber mal gespannt. C++ auf Android, wird sicher witzig.
Insbesondere weil cancas.draw() bereits in C++ Code ausgeführt wird. Der Trick liegt wahrscheinlich eher darin Hardwarebeschleunigung zu verwenden und nicht alles auf einem kleinen niedriggetakteten CPU Kern laufen zu lassen.

Eine Bitmap halte ich auch für eine grauenhafte Idee. Auf einem Smartphone hat man einen Heap von vielleicht 64mb zur Verfügung.
Eine bildschirmgroße Bitmap sprengt doch schon die Hardwareanforderungen.

Mein Gegenvorschlag wäre es das Spiel einfach zu pausieren solange man sich im Menü befindet wie bereits von @schlingel vorgeschlagen.

[QUOTE=Unregistered]Es gibt immer mehrere Möglichkeiten aus denen man auswählen kann.

Entweder man berechnet ständig neu dann braucht man halt CPU-Power und Zeit oder man cacht, dann braucht man eben Speicher.

Im ungünstigsten Fall, der hier wohl eingetreten ist, versuchst du alle 20 ms eine Operation anzustoßen die 50 ms (cv.drawARGB(100, 0, 0, 0)) benötigt.

Was passiert denn im ungünstigstern Fall bei dieser Aktion?

Jeder einzelne Pixel wird genommen und dann wird ein Grau draufgerechnet und dies dann gezeichnet. Für jeden dieser 2073600 Pixel! Und das braucht 50 ms.
Ist halt so.

Bei jedem Durchlauf von onDraw ist nach dem Aufruf vom Graufilter das Bild das gleiche wie beim vorigen Aufruf, da das Spiel ja angehalten ist.

Also wird alle 20 ms eine Aktion getriggert die erstens lange braucht und zweitens jedesmal bis zu dem Punkt nach dem Zeichnen des Graufilters, das selbe Ergebnis (Spielfeld + Graufilter) produziert.

Warum also beim Starten des Pause Menus nicht

  • ein einziges mal ein Bitmap anlegen bei dem das Spielfeld + Graufilter gezeichnet werden
  • danach dieses Bitmap zeichnen lassen sowie darauf das Pausemenu.

Beim Beenden des Pause Menus das Angelegte Bitmap des (Spielfelds + Graufilter) disposen, null setzen und schauen das es der GC entsorgt. Kosten dieses Bitmaps sind bei 4 Byte pro Pixel und 2 Mio Pixeln etwa 8 - 10 MB an Arbeitsspeicher die währende der Pause gebraucht werden. Und dann zeichnen wie bisher, da dies ja soweit ganz gut zu funktionieren scheint.

Das geht zwar weg vom ursprünglichen Double-Buffering, sollte aber sich leicht adaptieren lassen.[/QUOTE]

Das ist wahrscheinlich in vielen Anwendungen eine sehr sinnvolle Methode :slight_smile:
Allerdings würde ich sie nur benutzen, wenn die Anwendung selbst nur sehr wenig Arbeitspeicher benötigt.

In meinem Fall z.B. sind mehrere Hintergründe auf einmal geladen (was auch problemlos läuft). Kommt dann der graue Filter hinzu, hängt das Spiel vor allem bei Tablets (wegen dem großen Bildschirm) merklich. Bei Geräten mit kleineren Displays gehen die FPS zwar auch stark runter, da man sich aber sowieso im Pause-Menü befindet, merkt man das kaum. Wenn ich jetzt gerade bei diesen Tablets eine Bitmap mit dem kompletten Bildschirm anlege wird der Heap recht schnell überschritten.

[QUOTE=TMII;122381]Cocos2D-X (!) und da bin ich aber mal gespannt. C++ auf Android, wird sicher witzig.
Insbesondere weil cancas.draw() bereits in C++ Code ausgeführt wird. Der Trick liegt wahrscheinlich eher darin Hardwarebeschleunigung zu verwenden und nicht alles auf einem kleinen niedriggetakteten CPU Kern laufen zu lassen.

Eine Bitmap halte ich auch für eine grauenhafte Idee. Auf einem Smartphone hat man einen Heap von vielleicht 64mb zur Verfügung.
Eine bildschirmgroße Bitmap sprengt doch schon die Hardwareanforderungen.

Mein Gegenvorschlag wäre es das Spiel einfach zu pausieren solange man sich im Menü befindet wie bereits von @schlingel vorgeschlagen.[/QUOTE]

Da bin ich auch extrem gespannt :smiley:
Habe bei mehreren guten Spielen (Welche auch auf mehreren Plattformen verfügbar sind) in den Credits entdeckt, dass sie mit der Cocos2D-X Engine arbeiten. Bestes Beispiel dafür: Kingdom Rush. Deswegen habe ich mich ein bisschen darüber informiert und die Beschreibung und Erklärungen der Engine haben mich echt positiv überzeugt :slight_smile:

Soooo wir haben so viele gute Ideen gesammelt!

Ich habe mich schon vor einer Weile für folgende Lösung entschieden:
Es gibt optional einen grauen Filter (der für ein schöneres Bild mit besserem Kontrast sorgt). Der Filter kann in den Einstellungen aus-/eingeschalten werden. Bei Geräten mit sehr großen Bildschirmen bzw. langsamer Rechenleistung ist diese Einstellung standardmäßig ausgestellt, bei den anderen Geräten ist sie von Anfang an aktiv.

Die Idee, das Spiel zu pausieren, könnte ich vielleicht noch zusätzlich anwenden. Die komplette Logik wird sowieso pausiert, aber die „Zeichen-Methode“ könnte ich auch noch pausieren bzw. verlangsamen (weil der Bildschirm während dem Pausemenü nicht komplett statisch ist, und dort noch mehrere Optionen auswählbar sind.

Den Thread habe ich noch erhalten um möglicherweise noch eine bessere Lösung zu finden & um Lösungen für andere Entwickler zu sammeln, die auf das selbe Problem stoßen (sind anscheinend recht viele Leute, die das Thema interessiert, wenn man die Thread-Klicks anschaut).

Danke für die vielen kreativen und guten Einfälle und Ideen, Leute :slight_smile: