Ich habe versucht, den "besten" Weg zu finden, um einen Hintergrund aus gekachelten Bitmaps auf einem Android SurfaceView zu scrollen. Es ist mir tatsächlich gelungen, aber ich wollte herausfinden, ob es eine effizientere Technik gibt oder ob meine Technik nicht auf allen Android-Telefonen funktioniert.
Grundsätzlich erstelle ich eine neue veränderbare Bitmap, die etwas größer ist als die Abmessungen meiner SurfaceView. Insbesondere enthält meine Bitmap eine zusätzliche Reihe von Kacheln oben, unten, links und rechts. Ich erstelle eine Leinwand um meine neue Bitmap herum und zeichne meine Bitmap-Kacheln darauf. Dann kann ich zu einer Kachel in beliebiger Richtung scrollen, indem ich einfach eine "Surfaceview-size" -Untermenge meiner Hintergrund-Bitmap auf die Leinwand des SurfaceHolders zeichne.
Meine Fragen sind:
Gibt es eine bessere Bit-Blit-Technik als das Zeichnen einer Hintergrund-Bitmap auf die Leinwand meines SurfaceHolders?
Was ist die beste Vorgehensweise, wenn ich zum Rand meiner Hintergrund-Bitmap blättern und die Karte um eine Kachellänge verschieben möchte? Wie ich es sehe, sind meine Optionen:
a. Zeichne alle Kacheln in meinem Hintergrund einzeln neu, verschiebe die Kachellänge in eine Richtung. (Dies erscheint mir ineffizient, da es viele kleine Bitmap-Draws beinhalten würde).
b. Machen Sie die Hintergrund-Bitmap einfach so groß, dass sie die gesamte scrollende Welt umfasst. (Dies könnte eine extrem große Bitmap erfordern, die jedoch nur einmal erstellt werden muss.)
c. Kopieren Sie die Hintergrund-Bitmap, zeichnen Sie sie auf sich selbst, verschieben Sie eine Kachellänge in die Richtung, in die wir scrollen, und zeichnen Sie die neu aufgedeckte Zeile oder Spalte der Kacheln mit einigen einzelnen Bitmap-Zeichnungen. (Hier mache ich die Annahme, dass eine große Bitmap-Zeichnung effizienter ist als mehrere kleine, die dieselbe Ausdehnung abdecken.)
Danke, dass Sie all das gelesen haben, und ich wäre für jeden Rat sehr dankbar.
Ich habe ursprünglich eine ähnliche Technik in meinem "Box Fox" -Platformer-Spiel und RTS verwendet, aber festgestellt, dass es ziemlich deutliche Verzögerungen verursacht, wenn Sie genug scrollen, dass die Bitmap neu gezeichnet werden muss.
Meine aktuelle Methode diese Spiele ist ähnlich wie Ihre Option C. Ich zeichne meine gekachelten Kartenschichten auf ein Raster großer Bitmaps (etwa 7x7), die einen Bereich einnehmen, der größer als der Bildschirm ist. Wenn der Benutzer auf den Rand dieses Rasters scrollt, verschiebe ich alle Bitmaps im Raster um (verschiebe die End-Bitmaps nach vorne), ändere den Versatz des Rasters und zeichne dann einfach die neue Kante neu.
Ich bin nicht ganz sicher, was schneller ist mit Software-Rendering (Ihre Option C oder meine aktuelle Methode). Ich denke, dass meine Methode vielleicht schneller ist, wenn Sie jemals zum OpenGL-Rendering wechseln, da Sie nicht so viele Texturdaten auf die Grafikkarte hochladen müssen, wie der Benutzer scrollt.
Ich würde Option A nicht empfehlen, da, wie Sie vorschlagen, die hunderte kleinen Bitmap-Draws für eine gekachelte Karte die Leistung beeinträchtigen und bei großen Bildschirmen ziemlich schlecht werden. Option B ist mit vielen Geräten möglicherweise nicht einmal möglich, da es ziemlich einfach ist, einen "Bitmap-Größe überschreitet VM-Budget" -Fehler zu erhalten, da die Heap-Speicherplatz-Grenze auf vielen Telefonen ziemlich niedrig eingestellt ist.
Auch wenn Sie keine Transparenz auf Ihrer Karte / im Hintergrund benötigen, versuchen Sie RGB_565 Bitmaps zu verwenden, da es viel schneller ist, in Software zu zeichnen, und weniger Speicherplatz verbraucht.
Übrigens, ich bekomme auf meinem Handy und meinem 10 "-Tablet in meinem RTS mit 60fps auf die oben genannte Methode gekappt, in Software gerendert und kann problemlos über die Karte scrollen. So können Sie auf jeden Fall eine ordentliche Geschwindigkeit herausholen Ich habe einen 2D-OpenGL-Wrapper, der für mein Spiel gebaut wurde, aber noch nicht benötigt wurde.
Meine Lösung in einer Mapping-App beruht auf einem 2-Level-Cache, erste Kacheln werden mit einer Bitmap und einer Position erstellt, diese werden entweder auf der Festplatte oder in einem Vector gespeichert (Synchronisierung ist wichtig für mich, Multithread-HTTP-Comms überall) der Ort).
Wenn ich den Hintergrund zeichnen muss, erkenne ich den sichtbaren Bereich und erhalte eine Liste aller Kacheln, die ich brauche (dies wird stark optimiert, da er so oft aufgerufen wird). Dann ziehe ich die Kacheln aus dem Speicher oder lade sie von der Festplatte. Ich bekomme sehr vernünftige Leistung sogar auf etwas älteren Telefonen und nettem glattem Scrollen ohne Schluckauf.
Als Vorbehalt lasse ich zu, dass die Kacheln nicht bereit sind und tausche sie gegen ein Ladebild aus. Ich weiß nicht, ob das für dich funktionieren würde, aber wenn du alle Kacheln in der APK geladen hast, sollte es dir gut gehen.
Ich denke, ein effizienter Weg wäre, canvas.translate zu verwenden.
In der ersten Zeichnung müsste die gesamte Leinwand mit Kacheln gefüllt werden. Neue Android-Handys können dies einfach und schnell tun.
Wenn der Hintergrund gescrollt wird, würde ich canvas.translate(scrollX, scrollY),
verwenden, dann würde ich einzeln eine Kachel zeichnen, um die Lücken zu füllen, ABER, würde ich verwenden
canvas.drawBitmap(tileImage[i], fromRect, toRect, null)
, die nur die Teile der Kacheln zeichnen würde, die angezeigt werden sollen, indem Sie fromRect und toRect so einstellen, dass sie scrollX und scrollY entsprechen.
Also würde alles durch Mathematik gemacht werden und keine neuen Bitmaps würden für den Hintergrund erstellt werden - etwas Speicher sparen.
BEARBEITEN: Es gibt jedoch ein Problem bei der Verwendung von canvas.translate mit der Oberflächenansicht, da es doppelt gepuffert ist und canvas.translate nur einen Puffer übersetzt, aber nicht den zweiten zur gleichen Zeit, so dass diese alternierenden Puffer berücksichtigt werden müssen, wenn sie abhängen auf der Oberfläche, um das gezeichnete Bild zu erhalten.
Ich verwende Ihre ursprüngliche Methode, um einen perspektivischen Scroll-Hintergrund zu zeichnen. Ich bin vor ein paar Tagen ganz zufällig auf diese Idee gekommen, als ich mit einer einfachen Technik experimentierte, um eine perspektive scrollende Sternfeldsimulation zu machen. Die App kann hier gefunden werden: Aurora2D.apk
Kippen Sie einfach Ihr Gerät oder schütteln Sie es, um den Hintergrund zu scrollen (entschuldigen Sie die 2 hüpfenden Sprites - sie sind da, um mir mit einer effizienten Methode zu helfen, Trails anzuzeigen). Bitte lassen Sie es mich wissen, wenn Sie einen besseren Weg finden, dies zu tun, da ich im Laufe der Jahre mehrere verschiedene Methoden codiert habe und diese scheint überlegen zu sein. Schreiben Sie mir einfach, wenn Sie Code vergleichen möchten.
Tags und Links android