ActionScript 3
Leistung optimieren
Suche…
Vektorbasierte Grafiken
Vektorbasierte Grafiken werden durch eine Fülle von Daten dargestellt, die von der CPU berechnet werden müssen (Vektorpunkte, Bögen, Farben usw.). Alles andere als einfache Formen mit minimalen Punkten und geraden Linien beanspruchen viel CPU-Ressourcen.
Es gibt ein Flag "Cache as Bitmap", das aktiviert werden kann. Dieses Flag speichert das Ergebnis des Zeichnens des vektorbasierten DisplayObject für wesentlich schnellere Neuzeichnungen. Die Gefahr dabei ist, dass bei Transformationen des Objekts das gesamte Objekt neu gezeichnet und zwischengespeichert werden muss. Dies kann langsamer sein, als es überhaupt nicht einzuschalten, wenn Frame-by-Frame-Transformationen angewendet werden (Drehung, Skalierung usw.).
Im Allgemeinen ist das Rendern von Grafiken mit Bitmaps weitaus leistungsfähiger als das Verwenden von Vektorgrafiken. Bibliotheken wie Flixel nutzen dies zum Rendern von Sprites auf einer "Leinwand", ohne die Bildfrequenz zu reduzieren.
Text
Das Rendern von Text verbraucht viel CPU. Schriftarten werden ähnlich wie Vektorgrafiken gerendert und enthalten viele Vektorpunkte für jedes Zeichen. Wenn Sie den Text Bild für Bild ändern, wird die Leistung beeinträchtigt. Das Flag "Cache as Bitmap" ist bei korrekter Verwendung äußerst nützlich. Das bedeutet, dass Sie Folgendes vermeiden müssen:
- Den Text häufig ändern.
- Textfeld transformieren (drehen, skalieren).
Einfache Techniken, wie das Aktualisieren von Textaktualisierungen in einer if
Anweisung, bewirken einen wesentlichen Unterschied:
if (currentScore !== oldScore) {
field.text = currentScore;
}
Text kann mit dem in Flash integrierten Anti-Alias-Renderer oder mit "Geräteschriftarten" gerendert werden. Die Verwendung von "Geräteschriftarten" beschleunigt das Rendern von Text, obwohl der Text gezackt erscheint (Alias). Für Geräteschriftarten muss die Schriftart auch von Ihrem Endbenutzer vorinstalliert werden, oder der Text "verschwindet" möglicherweise auf dem Computer des Benutzers, obwohl dies auf Ihrem Computer fehlerfrei erscheint.
field.embedFonts = false; // uses "device fonts"
Vector und für jedes vs Arrays und für
Die Verwendung des Vector.<T>
-Typs und der for each
Schleife ist leistungsfähiger als bei einem herkömmlichen Array und for
Schleife:
Gut:
var list:Vector.<Sprite> = new <Sprite>[];
for each(var sprite:Sprite in list) {
sprite.x += 1;
}
Schlecht:
var list:Array = [];
for (var i:int = 0; i < list.length; i++) {
var sprite:Sprite = list[i];
sprite.x += 1;
}
Schnelle Entfernung von Array-Elementen
Wenn Sie nicht benötigen, dass ein Array in einer bestimmten Reihenfolge ist, bietet Ihnen ein kleiner Trick mit pop()
einen enormen Leistungszuwachs im Vergleich zu splice()
.
Wenn Sie ein Array splice()
, muss der Index nachfolgender Elemente in diesem Array um 1 reduziert werden. Dieser Vorgang kann viel Zeit in Anspruch nehmen, wenn das Array groß ist und sich das zu entfernende Objekt näher am Anfang des Arrays befindet .
Wenn Sie nicht über die Reihenfolge der Elemente in der Anordnung ist es egal, können Sie stattdessen das Element ersetzen Sie mit einem Element entfernen möchten , die Sie pop()
vom Ende des Arrays. Auf diese Weise bleiben die Indizes aller anderen Elemente im Array gleich, und die Leistung des Prozesses nimmt nicht ab, wenn die Länge des Arrays zunimmt.
Beispiel:
function slowRemove(list:Array, item:*):void {
var index:int = list.indexOf(item);
if (index >= 0) list.splice(index, 1);
}
function fastRemove(list:Array, item:*):void {
var index:int = list.indexOf(item);
if (index >= 0) {
if (index === list.length - 1) list.pop();
else {
// Replace item to delete with last item.
list[index] = list.pop();
}
}
}
Vektoren statt Arrays
In Flash Player 10 wurde der generische Listentyp Vector. <*> Eingeführt, der schneller als das Array war. Dies ist jedoch nicht ganz richtig. Nur die folgenden Vektortypen sind schneller als die Array-Gegenstücke, da sie in Flash Player implementiert werden.
-
Vector.<int>
- Vektor von 32-Bit-Ganzzahlen -
Vector.<uint>
- Vektor von 32-Bit-Ganzzahlen ohne Vorzeichen -
Vector.<Double>
- Vektor von 64-Bit-Floats
In allen anderen Fällen ist die Verwendung eines Arrays für alle Operationen (Erstellung, Manipulation usw.) leistungsfähiger als die Verwendung von Vektoren. Wenn Sie jedoch Ihren Code "stark eingeben" möchten, können Sie trotz der Verlangsamung Vektoren verwenden. FlashDevelop verfügt über eine Syntax, mit der Dropdowns für die Code-Vervollständigung mithilfe von /*ObjectType*/Array
auch für Arrays /*ObjectType*/Array
.
var wheels:Vector.<Wheel> // strongly typed, but slow
var wheels:/*Wheel*/Array // weakly typed, but faster
Grafiken wiederverwenden und zusammenfassen
Erstellen und Konfigurieren von Sprite
und TextField
Objekte zur Laufzeit kann teuer sein , wenn Sie Hunderttausende von ihnen auf einem einzigen Rahmen schaffen. Daher ist es ein üblicher Trick, diese Objekte für eine spätere Wiederverwendung zusammenzufassen. Denken Sie daran, dass wir nicht nur versuchen, die Erstellungszeit ( new Sprite()
) zu optimieren, sondern auch die Konfiguration (Einstellung der Standardeigenschaften).
Nehmen wir an, wir hätten eine Listenkomponente mit Hunderten von TextField-Objekten erstellt. Wenn Sie ein neues Objekt erstellen müssen, prüfen Sie, ob ein vorhandenes Objekt wiederverwendet werden kann.
var pool:Array = [];
if (pool.length > 0){
// reuse an existing TextField
var label = pool.pop();
}else{
// create a new TextField
label = new TextField();
// initialize your TextField over here
label.setDefaultTextFormat(...);
label.multiline = false;
label.selectable = false;
}
// add the TextField into the holder so it appears on-screen
// you will need to layout it and set its "text" and other stuff seperately
holder.addChild(label);
Wenn Sie Ihre Komponente später zerstören (oder vom Bildschirm entfernen), müssen Sie nicht verwendete Beschriftungen wieder in den Pool einfügen.
foreach (var label in allLabels){
label.parent.removeChild(label); // remove from parent Sprite
pool.push(label); // add to pool
}
In den meisten Fällen ist es am besten, einen Pool pro Nutzung anstelle eines globalen Pools zu erstellen. Das Erstellen eines globalen Pools hat den Nachteil, dass Sie das Objekt jedes Mal neu initialisieren müssen, um es aus dem Pool abzurufen, um die von anderen Funktionen vorgenommenen Einstellungen zu verwerfen. Dies ist gleichermaßen kostspielig und negiert den Leistungszuwachs beim Pooling in erster Linie.