Monthly Archive for August, 2008

Page 2 of 2

Flash Checker, Teil 2: Objektorientiertes JSFL

Im ersten Teil des Flash Checkers habe ich eine einfache Flash-Erweiterung verfasst, die die Dokumenteinstellungen einer FLA-Datei prüft. Dem einen oder anderen mag es übel aufstoßen, dass diese Erweiterung für die Flash Entwicklungsumgebung in JavaScript verfasst wurde. Mal abgesehen davon, dass – wer unbedingt will – auch DLLs programmieren und als Erweiterung einbinden kann, ist JavaScript jedoch besser als sein Ruf: Beispielsweise die objektorientiere Programmierung ist durchaus möglich. Wenn auch nur Prototypen basiert. Das heißt, dass man bei JavaScript die Vererbung per Hand über sogenannte Prototypen erreicht. Denn jedes Objekt in der JavaScript-Welt verfügt über eine Prototyp-Eigenschaft, die auf ein anderes Objekt verweist. Und sollte eine Methode oder Eigenschaft nicht in einem Objekt verfügbar sein, dann wird halt im Prototyp nachgeschaut. Und sollte in diesem Objekt die Methode oder Eigenschaft ebenfalls nicht verfügbar sein, dann wird halt in dessen Prototyp nachgeschaut. Und so weiter und so fort…

Das Pendant zu einer Klasse erstellen Sie in JavaScript mit einer Funktion.

1
2
3
function FlashChecker () {
	this.property = "foo";
}

Eine Instanz dieser „Klasse“ erzeugt das Schlüsselwort new, in dem erst ein neues Objekt angelegt und die Funktion ähnlich einem Konstruktor im Kontext dieses neuen Objektes ausgeführt wird (das Schlüsselwort this bezieht sich in diesem Fall auf das gerade neu erzeugte Instanzobjekt).

1
var checker = new FlashChecker();

Es ist gängige Praxis, die Methoden einer „Klasse“ in das Prototyp-Objekt zu schreiben, damit die Methoden nur einmal deklariert und nur einmal im Speicher abgelegt werden.

1
2
3
4
5
6
7
8
9
10
11
12
FlashChecker.prototype.checkDocumentSettings = function (currentDocument) {
	var playerVersion = currentDocument.getPlayerVersion();
	var asVersion = currentDocument.asVersion;
	var fps = currentDocument.frameRate;
	var height = currentDocument.height;;
	var width = currentDocument.width;
	if (playerVersion != "9") fl.trace("Warning: Wrong player version!");
	if (asVersion != 3) fl.trace("Warning: Wrong ActionScript version!");
	if (fps != 24) fl.trace("Warning: Wrong framerate!");
	if (height != 800) fl.trace("Warning: Wrong height!");
	if (width != 800) fl.trace("Warning: Wrong width!");	
}

Die Instanzen haben dann über den Prototyp implizit (also ohne dass man es extra hinschreiben muss) per __proto__-Eigenschaft Zugriff darauf, so dass der Verwendung durch die Instanzen nichts im Wege steht.

1
2
3
var checker = new FlashChecker();
var currentDocument = fl.getDocumentDOM();
checker.checkDocumentSettings(currentDocument);

Rundungsfehler im Flash Player?

Bei der Aufzeichnung unseres aktuellen Trainings kam Saban auf mich zu, da seine 3D-Versuche mit Rundungsfehlern zu kämpfen hätten. Und in der Tat, Math.sin(Math.PI) ergibt nicht die zu erwartende 0. Aber warum ist dieses Problem in älteren Projekten nie aufgefallen?

Meine Tests ergaben, dass Math.sin(Math.PI) nicht mehr nur 15 signifikante Stellen (wie z. B. auch Math.PI) sondern im aktuellen Flash Player ein paar Nachkommastellen mehr hat. Wenn ich die Genauigkeit nun einfach wieder auf das Verhalten älterer Flash Player ändere und Math.round(Math.sin(Math.PI)*1e15)/1e15 nutze, dann kommt auch wie erwartet 0 heraus. Eigentlich ist dieses Ergebnis ein gutes Zeichen, da die vom Flash Player verwendete Näherung für Sinus und Cosinus nun deutlich genauer zu arbeiten scheint (also mit mehr Stellen). Doch im Einzelfall kann diese Näherung auf Dauer zu Berechnungsfehlern führen, die es früher nicht gab – gerade bei umfangreichen 3D-Berechnungen sollte man das im Auge behalten.

Das Berechnen von Werten scheint sich aber auch an anderen Stellen seltsam zu verhalten. Bei Saban ergab beispielsweise trace(4.4 + 2.9) im Flash Player 10 den Wert 7.300000000000001. Woher auch immer die Nachkommastelle kommt. Und bei einem eigenen Versuch wurde aus 1.0000000000000005 (also der 5 auf der 16. Nachkommstelle) die Zahl 1.00000000000000004 (also eine 4 auf der 16. Nachkommstelle). Mit ActionScript 2 (also der alten AVM) passen die Werte jedoch auch im Flash Player 10 bzw. werden korrekt gerundet.

Flash Checker, Teil 1: JavaScript Flash (JSFL)

Ich weiß nicht warum, aber irgendwie habe ich es in den letzten Jahren versäumt, die ganzen kleinen JavaScript-Erweiterungen für Flash (JSFL) zu sammeln, die bei den verschiedenen Projekten so entstanden sind. Nun bin ich in einem großen Projekt engagiert, in dem viele externe Entwickler und Agenturen Flash-Dateien anliefern, die möglichst automatisch geprüft werden sollen und da nutze ich doch die Chance das nachzuholen. Zumal die Prüfung von Flash-Dateien (FLA) ja nicht das einzige ist, was sich damit erledigen lässt: Einige Kunden nutzen JSFL sogar, um Prozesse zu automatisieren und z. B. Teile eines Projektes automatisch zu generieren. Gerade bei sehr gleichförmigen Inhalten lässt sich so sehr viel Zeit sparen.

Wer selber in das Thema einsteigen möchte, kann sich im Verlauf-Bedienfeld (History-Panel) nicht nur seine Aktionen in Flash, sondern auch die dahinter versteckten JavaScript-Befehle anzeigen lassen. Wenn man das dann noch über das Menü „Befehle“ (Commands) ähnlich einem Makro aufzeichnet, dann erhält man eine fertige JSFL-Datei, die sich im Benutzerverzeichnis für Flash findet: Bei Flash CS3 unter Windows Vista ist das meist C:\Users\[Benutzername]\AppData\Local\Adobe\Flash CS3\[Sprache]\Configuration\Commands. Und an diesem Ort kann man gleich auch selbst verfasste Befehle als JSFL-Datei ablegen (oder automatisch als Extension installieren lassen), die dann ebenfalls im Befehle-Menü erscheinen.

Ein einfacher Befehl könnte z. B. grundsätzliche Einstellungen wie die Flash Player-Version und ActionScript-Variante, die Dokumentgröße und die Bildrate prüfen und Abweichungen im Ausgabefenster (Output) anzeigen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Clear output panel
fl.outputPanel.clear(); 
 
// Check Flash Player Version
var playerVersion;
playerVersion = fl.getDocumentDOM().getPlayerVersion();
if (playerVersion != "9" ) fl.trace("Warning: Export should be for Flash Player 9!");
 
// Check ActionScript version
var asVersion;
asVersion = fl.getDocumentDOM().asVersion;
if (asVersion != 3) fl.trace("Warning: Use ActionScript 3 and not " + asVersion + "!");
 
// Check framerate
var fps;
fps = fl.getDocumentDOM().frameRate;
if (fps != 24) fl.trace("Warning: Framerate should be 24 but it is " + fps + "!");
 
// Check document size
var height;
var width;
height = fl.getDocumentDOM().height;
width = fl.getDocumentDOM().width;
if ( height != 600 || width != 800 ) fl.trace("Warning: Document size should be 800 x 600 and not " + width + " x " + height + "!");

Der nächste Teil des „Flash Checkers“ soll Die nächsten Teile des “Flash Checkers” werden sich um die objektorientierten Programmierung und um die Innereien wie Zeitleiste und Bibliothek kümmern. Über Anregungen würde ich mich sehr freuen…