ActionScript 3
Ottimizzazione delle prestazioni
Ricerca…
Grafica basata vettoriale
La grafica vettoriale è rappresentata da una pletora di dati che devono essere calcolati dalla CPU (punti vettoriali, archi, colori, ecc.). Qualsiasi cosa diversa dalle forme semplici con punti e linee rette minimali consumerà grandi quantità di risorse della CPU.
C'è un indicatore "Cache as Bitmap" che può essere attivato. Questo flag memorizza il risultato del disegno di DisplayObject basato su vettori per ridisegni molto più veloci. La trappola di questo è che se ci sono trasformazioni applicate all'oggetto, l'intera cosa deve essere ridisegnata e ricollocata. Questo può essere più lento di non accenderlo affatto se sono applicate trasformazioni fotogramma per fotogramma (rotazione, ridimensionamento, ecc.).
Generalmente, il rendering della grafica tramite bitmap è molto più performante rispetto all'utilizzo della grafica vettoriale. Librerie come flixel ne approfittano per rendere gli sprite su una "tela" senza ridurre il framerate.
Testo
Il rendering del testo consuma molta CPU. I caratteri sono resi in modo simile alla grafica vettoriale e contengono molti punti vettoriali per ogni personaggio. Text alterazione fotogramma per fotogramma si degrada le prestazioni. Il flag "Cache as bitmap" è estremamente utile se usato correttamente, il che significa che devi evitare:
- Modifica del testo frequentemente.
- Trasformazione del campo di testo (rotazione, ridimensionamento).
Tecniche semplici come il wrapping degli aggiornamenti di testo in un'istruzione if
fanno la differenza principale:
if (currentScore !== oldScore) {
field.text = currentScore;
}
Il testo può essere renderizzato usando il renderer anti-alias incorporato in Flash, o usando "font dispositivo". L'uso di "tipi di carattere dispositivo" rende il rendering del testo molto più veloce, sebbene faccia apparire il testo frastagliato (alias). Inoltre, i caratteri del dispositivo richiedono che il font sia preinstallato dall'utente finale, oppure che il testo possa "scomparire" sul PC dell'utente, sebbene appaia bene sul tuo.
field.embedFonts = false; // uses "device fonts"
Vettore e per ogni vs matrici e per
Usando il tipo Vector.<T>
e il ciclo for each
loop è più performante di un array convenzionale e for
loop:
Buono:
var list:Vector.<Sprite> = new <Sprite>[];
for each(var sprite:Sprite in list) {
sprite.x += 1;
}
Male:
var list:Array = [];
for (var i:int = 0; i < list.length; i++) {
var sprite:Sprite = list[i];
sprite.x += 1;
}
Rimozione veloce degli elementi dell'array
Se non si richiede che un array sia in un ordine particolare, un piccolo trucco con pop()
ti consentirà enormi guadagni in termini di prestazioni rispetto a splice()
.
Quando si splice()
un array, l'indice degli elementi successivi in quell'array deve essere ridotto di 1. Questo processo può consumare una grande quantità di tempo se l'array è grande e l'oggetto che si sta rimuovendo è più vicino all'inizio di quell'array .
Se non ti interessa l'ordine degli elementi nell'array, puoi invece sostituire l'elemento che vuoi rimuovere con un oggetto pop()
dalla fine dell'array. In questo modo, gli indici di tutti gli altri elementi dell'array rimangono gli stessi e il processo non degrada in termini di prestazioni man mano che la lunghezza dell'array aumenta.
Esempio:
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();
}
}
}
Vettori invece di matrici
Flash Player 10 ha introdotto il vettore. <*> Tipo di elenco generico più veloce della matrice. Tuttavia, questo non è completamente vero. Solo i seguenti tipi di vettore sono più veloci rispetto alla controparte Array, a causa del modo in cui sono implementati in Flash Player.
-
Vector.<int>
- Vettore di numeri interi a 32 bit -
Vector.<uint>
- Vettore di numeri interi senza segno a 32 bit -
Vector.<Double>
- Vettore di galleggianti a 64 bit
In tutti gli altri casi, l'uso di una matrice sarà più performante rispetto all'utilizzo di Vettori, per tutte le operazioni (creazione, manipolazione, ecc.). Tuttavia, se desideri "scrivere con decisione" il tuo codice, puoi utilizzare i Vettori nonostante il rallentamento. FlashDevelop ha una sintassi che consente agli elenchi a discesa di completamento del codice di funzionare anche per gli array, utilizzando /*ObjectType*/Array
.
var wheels:Vector.<Wheel> // strongly typed, but slow
var wheels:/*Wheel*/Array // weakly typed, but faster
Riutilizzare e mettere in comune la grafica
La creazione e la configurazione di oggetti Sprite
e TextField
in fase di esecuzione può essere costosa se ne stai creando centinaia di migliaia su un singolo frame. Quindi un trucco comune è "mettere in comune" questi oggetti per un successivo riutilizzo. Ricorda che non stiamo solo cercando di ottimizzare il tempo di creazione ( new Sprite()
) ma anche la configurazione (impostazione delle proprietà di default).
Diciamo che stavamo costruendo un componente di lista usando centinaia di oggetti TextField. Quando hai bisogno di creare un nuovo oggetto, controlla se un oggetto esistente può essere riutilizzato.
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);
Successivamente, quando si distrugge il componente (o lo si rimuove dallo schermo), ricordarsi di aggiungere nuovamente le etichette non utilizzate nel pool.
foreach (var label in allLabels){
label.parent.removeChild(label); // remove from parent Sprite
pool.push(label); // add to pool
}
Nella maggior parte dei casi è preferibile creare un pool per utilizzo anziché un pool globale. Svantaggi per la creazione di un pool globale è necessario reinizializzare l'oggetto ogni volta per recuperarlo dal pool, per annullare le impostazioni eseguite da altre funzioni. Questo è altrettanto costoso e praticamente nega l'aumento delle prestazioni dell'utilizzo del pool in primo luogo.