2 Stimmen

Kernanimation mit contentRect Ruckeln

In meinem (Puzzle-)Spiel werden die Teile auf dem Bildschirm gezeichnet, indem ein CALayer für jedes Stück. Es gibt 48 Teile (in einem 8x6-Raster), wobei jedes Teil 48x48 Pixel groß ist. Ich bin nicht sicher, ob dies nur zu viele Schichten ist, aber wenn dies nicht die beste Lösung ist, weiß ich nicht, was ist, weil neu zeichnen die gesamte Anzeige mit Quartz2D jedes Bild scheint nicht wie es wäre schneller.

Wie auch immer, die Bilder für die Stücke kommen aus einer großen PNG-Datei, die 24 Frames der Animation für 10 verschiedene Zustände hat (so misst 1152 x 480 Pixel) und die Animation wird durch die Einstellung der contentsRect Eigenschaft eines jeden CALayer wenn ich sie bewege.

Dies scheint tatsächlich ziemlich gut mit bis zu 7 Stücken zu funktionieren, die einen Berührungspunkt im Fenster verfolgen, aber die seltsame Sache ist, dass, wenn ich anfange, die Stücke zu bewegen, für die ersten 0,5 eine Sekunde oder so, es sehr ruckelig ist, wie die CPU etwas anderes tut, aber danach wird es verfolgen und den Bildschirm bei 40+ FPS (nach Instrumenten) aktualisieren.

Hat jemand eine Idee, was der Grund für diese anfängliche Ruckelei sein könnte?

Die einzige Theorie, die ich mit kommen konnte, ist es dekomprimieren Bits der PNG-Datei in einen temporären Speicherort und dann verwerfen Sie, nachdem die Animation gestoppt hat, in diesem Fall gibt es eine Möglichkeit, Core Animation tun, dass zu stoppen?

Ich könnte natürlich die PNG-Datei in 10 Teile aufteilen, aber ich bin nicht überzeugt, dass das helfen würde, da sie alle (potenziell) immer noch gleichzeitig im Speicher sein müssten.

EDIT : OK, wie im Kommentar zur ersten Antwort beschrieben, habe ich das Bild in zehn Teile aufgeteilt, die jetzt 576 x 96 groß sind, damit es in die Beschränkungen der Hardware passt. Es ist aber immer noch nicht so glatt, wie es sein sollte, also habe ich ein Kopfgeld darauf ausgesetzt.

EDIT2: Ich habe eines der Bilder unten verlinkt. Im Wesentlichen wird die Berührung des Benutzers verfolgt, der Versatz vom Beginn der Verfolgung wird berechnet (sie können sich nur horizontal oder vertikal und nur an einer Stelle gleichzeitig bewegen). Dann wird eines der Bilder als Inhalt der Ebene ausgewählt (je nachdem, um welche Art von Teil es sich handelt und ob es sich horizontal oder vertikal bewegt). Dann wird die contentsRect ist so eingestellt, dass ein 48x48-Bild aus dem größeren Bild ausgewählt wird, etwa so:-

layer.position = newPos;
layer.contents = (id)BallImg[imgNum];
layer.contentsRect = CGRectMake((1.0/12.0)*(float)(frame % 12), 
                                0.5 * (float)(frame / 12), 
                                1.0/12.0, 0.5); 

btw. Meine Theorie, dass das Quellbild jedes Mal neu dekomprimiert wird, war nicht richtig. Ich habe einen Code geschrieben, der die rohen Pixel aus der dekodierten PNG-Datei in eine neue Datei kopiert. CGImage wenn die App geladen wird, und es hat keinen Unterschied gemacht.

Als Nächstes werde ich versuchen, jedes Einzelbild in eine separate Datei zu kopieren. CGImage die die hässlichen contentsRect zumindest die Berechnung.

Sample image

EDIT3: Weitere Untersuchungen haben ergeben, dass es sich um ein Problem mit dem Touch-Tracking handelt und nicht um ein Problem mit Core Animation. Ich habe eine einfache Beispielanwendung gefunden, die Berührungen verfolgt und den Code auskommentiert, der das Neuzeichnen des Bildschirms und die NSLog() zeigt genau das gleiche Problem, das auch bei mir auftritt: Eine längere Verzögerung zwischen dem touchesBegin und erste touchesMoved Veranstaltungen.

2009-06-05 01:22:37.209 TouchDemo[234:207] Begin Touch ID 0 Tracking with image 2
2009-06-05 01:22:37.432 TouchDemo[234:207] Touch ID 0 Tracking with image 2
2009-06-05 01:22:37.448 TouchDemo[234:207] Touch ID 0 Tracking with image 2
2009-06-05 01:22:37.464 TouchDemo[234:207] Touch ID 0 Tracking with image 2
2009-06-05 01:22:37.480 TouchDemo[234:207] Touch ID 0 Tracking with image 2

Typische Lücke zwischen touchesMoved Ereignisse beträgt 20ms. Der Abstand zwischen den touchesBegin und erste touchesMoved ist zehnmal so hoch. Und das ganz ohne Berechnungen oder Bildschirmaktualisierung, nur mit der NSLog rufen. Seufz. Ich schätze, ich werde das als separate Frage aufmachen.

3voto

Andrew Pouliot Punkte 5423

Ich glaube nicht, dass es ein Speicherproblem ist; ich denke, dass es mit der Ineffizienz eines so großen Bildes in Bezug auf Core Animation zu tun hat.

Core Animation kann es nicht nativ verwenden, da es die maximale Texturgröße auf der GPU (1024x1024) überschreitet. Ich würde es etwas auflockern Einzelne Bilder könnten die beste Leistung erbringen, aber das müssen Sie selbst herausfinden.

IIRC, UIImageView tut seine Animation durch Einstellung aufeinanderfolgende einzelne Bilder, also wenn es gut genug für Apple . ist

1voto

Nikolai Ruhe Punkte 80427

Wenn es um die Leistung geht, empfehle ich auf jeden Fall Shark (auch über Instruments). Im "Zeitprofil" können Sie sehen, was die Engpässe in Ihrer Anwendung sind, auch wenn es etwas im Code von Apple ist. Ich habe es bei der Entwicklung meiner iPhone-Applikation, die OpenGL und Core Animation verwendet, sehr oft benutzt.

0voto

Corey Floyd Punkte 25849

Haben Sie schon versucht, CATiledLayer zu verwenden?

Sie ist für diese Art von Arbeit optimiert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X