AS3-Tutorium: Flash: Butterfly 05 external code: Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Kowa (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
Kowa (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
 
(28 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 9: Zeile 9:
<noinclude>
<noinclude>


<swf width="367" height="267">http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/butterfly_05_external_code.swf</swf>
<swf width="367" height="267">http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/Butterfly05Flash11.swf</swf>
'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS5)]'''
'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS5)]'''
([http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ SVN-Repository])
([http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ SVN-Repository])


'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS4)]'''
'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS4)]'''
([http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ SVN-Repository])
([http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ SVN-Repository])
</noinclude>
</noinclude>


==Der Code des Hauptmovies wird ausgelagert==  
==Der Code des Butterfly-Movies wird in eine Klasse ausgelagert==  


* Klick auf <code>Szene 1</code> in der linken oberen Ecke der Bühne → Die Hauptbühne wird geöffnet.
# Die Datei <code>Butterfly04Flash.fla</code> unter dem Namen <code>Butterfly05Flash.fla</code> speichern und mit dieser Datei weiterarbeiten.
* Den Code in der Ebene <code>scripts</code> auskommentieren. (Der hier enthaltene Code wird in die Datei <code>Main.as</code> ausgelagert.)
# Klick auf <code>Szene 1</code> in der linken oberen Ecke der Bühne → Die Hauptbühne wird geöffnet.
* Klick auf den grauen Hintergrund außerhalb der Bühne → Alle Objekte auf der Bühne werden deselektiert.
# Den Code in der Ebene <code>scripts</code> auskommentieren. (Der hier enthaltene Code wird in die Datei <code>Main.as</code> ausgelagert.)
* Im Fenster <code>Eigenschaften</code>: Im Eigabefeld <code>Klasse</code> den Klassenamen <code>Main</code> eintragen (erster Buchstabe groß, keine Endung <code>.as</code>!).
# Klick auf den grauen Hintergrund außerhalb der Bühne → Alle Objekte auf der Bühne werden deselektiert.
* <code>Datei</code> → <code>Neu</code> → <code>ActionScript 3.0-Klasse</code> → <code>OK</code> -> Klassenname: <code>Main</code>
# Im Fenster <code>Eigenschaften</code>: Im Eigabefeld <code>Klasse</code> den Klassenamen <code>Main</code> eintragen (erster Buchstabe groß, keine Endung <code>.as</code>!).
* <code>Datei</code> → <code>Datei speichern unter</code> → <code>Main.as</code> (im selben Ordner wie die zugehörige <code>fla</code>-Datei.)
# <code>Datei</code> → <code>Neu</code> → <code>ActionScript 3.0-Klasse</code> (CS5) bzw.  <code>ActionScript-Datei</code> (CS4 und früher) → <code>OK</code> <br/> Nur in CS5: -> Klassenname: <code>Main</code> → <code>OK</code>
# <code>Datei</code> → <code>Datei speichern unter</code> → <code>Main.as</code> (im selben Ordner wie die zugehörige <code>fla</code>-Datei.)


In die Datei <code>Main.as</code> wird folgender Code eingefügt:
In die Datei <code>Main.as</code> wird folgender Code eingefügt:


<source lang="actionscript">package
<source lang="actionscript3" enclose="div">package
{
{
   import flash.display.MovieClip;
   import flash.display.MovieClip;
Zeile 40: Zeile 41:
     /////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////
      
      
     public var mc_user_input:     MovieClip;
     public var d_input:           MovieClip;
     public var mc_butterfly_movie: MovieClip;
     public var d_butterfly_movie: MovieClip;
      
      
     /////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////
Zeile 49: Zeile 50:
     public function Main()
     public function Main()
     {
     {
       mc_user_input.mc_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start);  
     }
     }
      
      
Zeile 58: Zeile 59:
     private function o_start(p_event: MouseEvent): void
     private function o_start(p_event: MouseEvent): void
     {
     {
       mc_user_input.visible = false;
       d_input.visible = false;
        
        
       var l_rounds_to_fly: Number = parseInt(mc_user_input.mc_input_rounds.text);
       var l_rounds_to_fly: Number = parseInt(d_input.d_input_rounds.text);


       if (isNaN(l_rounds_to_fly) || l_rounds_to_fly < 0)
       if (isNaN(l_rounds_to_fly) || l_rounds_to_fly < 0)
         l_rounds_to_fly = 0;
         l_rounds_to_fly = 0;


       mc_butterfly_movie.roundsToFly = l_rounds_to_fly;
       d_butterfly_movie.roundsToFly = l_rounds_to_fly;
       mc_butterfly_movie.gotoAndPlay("lbStart");
       d_butterfly_movie.gotoAndPlay("lbStart");
     }
     }


Zeile 79: Zeile 80:
nur noch auskommentierten Code.
nur noch auskommentierten Code.


===Anmerkungen===
=Namenskonventionen=
Folgende [[Multimedia-Programmierung: Style Guide|Namenskonventionen]] wurden im Code eingehalten:


====Packages====
In den Schmetterlingsmovies ([[Symbol (Flash)|Symbol]]/[[Klasse (OOP)|Klasse]] <code>ButterflyMovie</code>) wurden
die im [[AS3-Tutorium: Flash: Butterfly 04 variable number of rounds|4. Teil des Tutoriums]]
eingeführten „öffentlichen“ Namen
* <code>roundsToFly</code> (Zustandsvariable)
* <code>lbStart</code> und <code>lbEnd</code> (Label)
beibehalten, da auf diese Attribute weiterhin von außen zugegriffen wird,
und zwar vom Main-Objekt aus, d.h. von dem Objekt der Klasse <code>Main</code> aus, das Flash
bei Start des Flashfilms automatisch erzeugt.
(Eigentlich wird nur auf <code>lbStart</code> und nicht auf <code>lbEnd</code> „von außen“ zugegriffen.)
 
In der Klasse <code>Main</code> wurden die Moviclips
* <code>d_input</code>
* <code>d_butterfly_movie</code>
dagegen gemäß der Konvention für nicht öffentlich zugängliche (<code>private</code>) Eigenschaften benannt,
da es keine anderen Objekte gibt (und auch nicht geben soll), die auf diese Objekte
zugreifen.
 
=ActionScript=
==Packages==
Eine Flash-Klasse ist immer in einem <code>package</code> enhalten. Wenn die
Eine Flash-Klasse ist immer in einem <code>package</code> enhalten. Wenn die
Klasse im selben Ordner wie der Flash-Film gespeichert wird, gibt es keinen
Klasse im selben Ordner wie der Flash-Film gespeichert wird, gibt es keinen
Zeile 88: Zeile 108:
lautet der Package-Name <code>hsa.tutorium.butterfly</code>:
lautet der Package-Name <code>hsa.tutorium.butterfly</code>:


<source lang="actionscript">package hsa.tutorium.butterfly
<source lang="actionscript3">package hsa.tutorium.butterfly
{  
{  
   ...
   ...
}</source>
}</source>


====Genau eine öffentlich zugängliche Klasse====
==Genau eine öffentlich zugängliche Klasse==
Jede Klassen-Datei muss genau eine öffentliche Klasse (<code>public</code>)
Jede Klassen-Datei <code>&lt;Klassenname&gt;.as</code> muss genau eine öffentliche Klasse (<code>public</code>)
mit dem Namen der Datei (ohne Endung <code>.as</code>) enthalten. Weitere
mit dem Namen der Datei (ohne Endung <code>.as</code>) enthalten. Weitere
interne Klassen können in der Datei enthalten sein, aber keine weitere
interne Klassen können in der Datei enthalten sein, aber keine weitere
öffentlich zugängliche Klasse.
öffentlich zugängliche Klasse.


====Import-Anweisungen====
==Import-Anweisungen==
Wie in Java steht vor der Klasse eine Liste <code>import</code>-Anweisungen,
Wie in Java steht vor der Klasse eine Liste <code>import</code>-Anweisungen,
die den direkten Zugriff auf andere Klassen im Code ermöglicht. In der
die den direkten Zugriff auf andere Klassen im Code ermöglicht. In der
Zeile 108: Zeile 128:
<code>import</code>-Anweisungen angegeben werden.
<code>import</code>-Anweisungen angegeben werden.


====Namen von Objekten auf der Bühne in der Klasse deklarieren====
==Namen von Objekten auf der Bühne in der Klasse deklarieren==
Die Objekte, die auf der Bühne liegen und einen Objektnamen erhalten haben, sollten  
Die Objekte, die auf der Bühne liegen und einen Objektnamen erhalten haben, sollten  
in der Klasse als öffentliche <code>public</code> [[Zustandsvariable]]n (instance variables)
in der Klasse als öffentliche (<code>public</code>) [[Zustandsvariable]]n (instance variables)
deklariert werden. Sie werden von Flash automatisch initialisiert.
deklariert werden. Sie werden von Flash automatisch initialisiert.
Wenn sie nicht als <code>public</code> deklariet werden, kommt es zu Laufzeitfehlern,
da Flash die automatische Initialisierung dann nicht durchführen kann.


Man könnte auf die Deklaration diese Variablen verzichten, erhält damit aber Code der schwerer zu lesen ist.
Man könnte auf die Deklaration dieser Variablen ganz verzichten,
erhält damit aber Code, der schwerer zu lesen ist.
Falls man den Code nicht mit Flash, sondern mit dem [[Flash Builder]] bearbeitet, würde
Falls man den Code nicht mit Flash, sondern mit dem [[Flash Builder]] bearbeitet, würde
man außerdem Fehlermeldungen erhalten, sobald man im Code auf diese Objekte zugreift.
man außerdem Fehlermeldungen direkt im Flash-Builder-Editor erhalten,  
sobald man im Code auf diese Objekte zugreift.


====Überführung von Code aus der Zeitleiste in die externe Klasse====
==Überführung von Code aus der Zeitleiste in die externe Klasse==
Der eigentlich Code aus der Zeitleiste des ursprünglichen Movies wird in zwei Teile
Der eigentlich Code aus der Zeitleiste des ursprünglichen Movies wird in zwei Teile
geteilt:
geteilt:
Zeile 134: Zeile 158:
wird, wie man zusätzlich zur Maus-Steuerung eine Tastatur-Steuerung in einen Movie Clip integriet.)
wird, wie man zusätzlich zur Maus-Steuerung eine Tastatur-Steuerung in einen Movie Clip integriet.)


<source lang="actionscript">public function Main()
<source lang="actionscript3">public function Main()
{
{
   trace(stage);
   trace(stage);
Zeile 158: Zeile 182:
<noinclude>
<noinclude>


<swf width="367" height="267">http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/butterfly_05_external_code_multi.swf</swf>
<swf width="367" height="267">http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/Butterfly05MultiFlash11.swf</swf>
'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ Musterlösung (Flash CS5)]'''
'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS5)]'''
([http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ SVN-Repository])
([http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ SVN-Repository])


'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Musterlösung (Flash CS4)]'''
'''[http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS4)]'''
([http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ SVN-Repository])
([http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ SVN-Repository])
</noinclude>
</noinclude>


Zeile 170: Zeile 194:
implementieren:
implementieren:


<source lang="actionscript">stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);</source>
<source lang="actionscript3">stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);</source>


Die Methode <code>o_check_enter</code> kann dabei folgendenmaßen definiert werden.
Die Methode <code>o_check_enter</code> kann dabei folgendenmaßen definiert werden.
   
   
<source lang="actionscript">private function o_check_enter(p_event: KeyboardEvent): void
<source lang="actionscript3">private function o_check_enter(p_event: KeyboardEvent): void
{
{
   if (p_event.keyCode == Keyboard.ENTER) // Wenn die Enter-Taste gedrückt wird
   if (p_event.keyCode == Keyboard.ENTER) // Wenn die Enter-Taste gedrückt wird
Zeile 184: Zeile 208:
<code>null</code>-Pointer-Exception.  
<code>null</code>-Pointer-Exception.  


<source lang="actionscript">...
<source lang="actionscript3">...
     public function Main()
     public function Main()
     {
     {
       mc_user_input.mc_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start);  


       // Zugriff auf stage => null-Pointer-Exception
       // Zugriff auf stage => null-Pointer-Exception
Zeile 196: Zeile 220:
Das Problem lässt sich lösen, indem man die Initialisierung erst beim Betreten des ersten Frames durchführt.
Das Problem lässt sich lösen, indem man die Initialisierung erst beim Betreten des ersten Frames durchführt.


<source lang="actionscript">...
<source lang="actionscript3">...
     public function Main()
     public function Main()
     {
     {
Zeile 210: Zeile 234:


       // Nun existiert das stage-Objekt!
       // Nun existiert das stage-Objekt!
       mc_user_input.mc_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);   
       stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);   
     }
     }
Zeile 221: Zeile 245:
Anstelle von
Anstelle von


<source lang="actionscript">stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);</source>
<source lang="actionscript3">stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);</source>


schreibt man einfach
schreibt man einfach


<source lang="actionscript">this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);</source>
<source lang="actionscript3">this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);</source>


in den Konstruktor. Dies funktioniert genauso gut. Da aber ein Zugriff auf das <code>stage</code>-Objekt unterbleibt,  
in den Konstruktor. Dies funktioniert genauso gut. Da aber ein Zugriff auf das <code>stage</code>-Objekt unterbleibt,  
gibt es bei folgenden Konstruktor keine <code>null</code>-Pointer-Exception:
gibt es bei folgenden Konstruktor keine <code>null</code>-Pointer-Exception:


<source lang="actionscript">...
<source lang="actionscript3">...
     public function Main()
     public function Main()
     {
     {
       mc_user_input.mc_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start);  


       // Zugriff auf this => keine null-Pointer-Exception
       // Zugriff auf this => keine null-Pointer-Exception
Zeile 246: Zeile 270:
der Tab-Taste oder der Maus den Fokus auf das Eingabefeld legen muss, muss man die Methode <code>setFocus</code> verwenden:
der Tab-Taste oder der Maus den Fokus auf das Eingabefeld legen muss, muss man die Methode <code>setFocus</code> verwenden:


<source lang="actionscript">mc_user_input.mc_input_rounds.setFocus();</source>
<source lang="actionscript3">d_input.d_input_rounds.setFocus();</source>


Die Methode <code>setFocus</code> greift intern auf das <code>stage</code>-Objekt zu.
Die Methode <code>setFocus</code> greift intern auf das <code>stage</code>-Objekt zu.
Zeile 253: Zeile 277:
Daher wurde er in der [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Flash-CS4-Version der erweiterten Musterlösung] auch eingesetzt.)
Daher wurde er in der [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Flash-CS4-Version der erweiterten Musterlösung] auch eingesetzt.)


<source lang="actionscript">...
<source lang="actionscript3">...
     public function Main()
     public function Main()
     {
     {
       // Zugriff auf this => keine null-Pointer-Exception       
       // Zugriff auf this => keine null-Pointer-Exception       
       mc_user_input.mc_input_rounds.setFocus();   
       d_input.d_input_rounds.setFocus();   


       mc_user_input.mc_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start);  


       this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);   
       this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);   
Zeile 269: Zeile 293:
indem man wie zuvor beschrieben die Initialisierung erst beim Betreten des ersten Frames durchführt.
indem man wie zuvor beschrieben die Initialisierung erst beim Betreten des ersten Frames durchführt.


<source lang="actionscript">...
<source lang="actionscript3">...
     public function Main()
     public function Main()
     {
     {
Zeile 283: Zeile 307:


       // Nun existiert das stage-Objekt!
       // Nun existiert das stage-Objekt!
       mc_user_input.mc_input_rounds.setFocus();   
       d_input.d_input_rounds.setFocus();   
       mc_user_input.mc_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start);  
       this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);
       this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);
     //stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter); // wäre hier auch OK!
     //stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter); // wäre hier auch OK!
Zeile 290: Zeile 314:
...
...
</source>
</source>
=Probleme der Implementierung=
Die im [[AS3-Tutorium: Flash: Butterfly 04 variable number of rounds#Probleme_der_Implementierung|vierten Teil des Flash-Tutoriums]]
genannte Problem wurden noch nicht behoben, da nur der Code der Hauptzeitleiste ausgelagert wurde.
Die schlechte Lesbarkeit der Timeline des Symbols <code>ButterflyMovie</code> sowie die Code-Duplikation,
falls ein zweites derartiges Symbol erstellt werden soll, bleiben bestehen.
Diese Probleme werden erst gelöst, wenn auch der Code des Symbols <code>ButterflyMovie</code> in eine externe Klasse ausgelagert wird
(siehe [[AS3-Tutorium: Flash: Butterfly 06 external code]]).


=Quellen=
=Quellen=
<noinclude>
<noinclude>
* [[Kowarschick, W.: Multimedia-Programmierung]]</noinclude>
# {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}</noinclude>
* [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS5)]
# [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS5)]
* [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS4)]
# [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS4)]
* [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS4)]
# [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS4)]
* [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS5)]
# [http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS5)]


== SVN-Repository-Verweise ==
== [[Subversion/HowTo|SVN]]-Repository-Verweise ==
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS5)]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs5/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS5)]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS4)]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs4/butterfly/butterfly_05_external_code/ Musterlösung (Flash CS4)]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS4)]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS4)]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS5)]<noinclude>[[Kategorie: AS3-Tutorium: Flash: Butterfly]][[Kategorie: Flash-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]
* [http://glossar.hs-augsburg.de/webdav/tutorium/flash_cs4/butterfly/butterfly_05_external_code_multi/ Erweiterte Musterlösung (Flash CS5)]<noinclude>[[Kategorie: AS3-Tutorium: Flash: Butterfly]][[Kategorie: Flash-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]
{{{{SITENAME}}-konformer Artikel}}
</noinclude>
</noinclude>

Aktuelle Version vom 25. Oktober 2014, 12:45 Uhr

Dieser Artikel ist veraltet und wird künftig evtl. entfernt.

Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:

Korrektheit: 4
(großteils überprüft)
Umfang: 3
(einige wichtige Fakten fehlen)
Quellenangaben: 5
(vollständig vorhanden)
Quellenarten: 5
(ausgezeichnet)
Konformität: 4
(sehr gut)

AS3-Tutorium: Butterfly: Flash | Flex

Flash: Übersicht | Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5 | Teil 6 | Teil 7a | Teil 7b | Teil 7c | Teil 8 | Teil 9 | Teil 10

Verbesserung der vierten Version des Schmetterling-Movies

In AS3-Tutorium: Flash: Butterfly 04 variable number of rounds wurde ein Schmetterling erzeugt, der eine vom Benutzer vorgegebene Anzahl von Runden auf einem Rundkurs fliegt bevor er die Bühne verlässt.

Das Verhalten des Schmetterlings wird nicht verändert. Allerdings wird der Code von der Hauptbühne in eines externe Klasse ausgelagert.


<swf width="367" height="267">http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code/Butterfly05Flash11.swf</swf> Musterlösung (Flash CS5) (SVN-Repository)

Musterlösung (Flash CS4) (SVN-Repository)


Der Code des Butterfly-Movies wird in eine Klasse ausgelagert

  1. Die Datei Butterfly04Flash.fla unter dem Namen Butterfly05Flash.fla speichern und mit dieser Datei weiterarbeiten.
  2. Klick auf Szene 1 in der linken oberen Ecke der Bühne → Die Hauptbühne wird geöffnet.
  3. Den Code in der Ebene scripts auskommentieren. (Der hier enthaltene Code wird in die Datei Main.as ausgelagert.)
  4. Klick auf den grauen Hintergrund außerhalb der Bühne → Alle Objekte auf der Bühne werden deselektiert.
  5. Im Fenster Eigenschaften: Im Eigabefeld Klasse den Klassenamen Main eintragen (erster Buchstabe groß, keine Endung .as!).
  6. DateiNeuActionScript 3.0-Klasse (CS5) bzw. ActionScript-Datei (CS4 und früher) → OK
    Nur in CS5: -> Klassenname: MainOK
  7. DateiDatei speichern unterMain.as (im selben Ordner wie die zugehörige fla-Datei.)

In die Datei Main.as wird folgender Code eingefügt:

package
{
  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.events.MouseEvent;
  
  public class Main extends MovieClip
  {
    /////////////////////////////////////////////////////////////////////////////
    // MovieClips on the stage
    /////////////////////////////////////////////////////////////////////////////
    
    public var d_input:           MovieClip;
    public var d_butterfly_movie: MovieClip;
    
    /////////////////////////////////////////////////////////////////////////////
    // Constructor
    /////////////////////////////////////////////////////////////////////////////
    
    public function Main()
    {
      d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start); 
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // Observer methods
    /////////////////////////////////////////////////////////////////////////////

    private function o_start(p_event: MouseEvent): void
    {
      d_input.visible = false;
      
      var l_rounds_to_fly: Number = parseInt(d_input.d_input_rounds.text);

      if (isNaN(l_rounds_to_fly) || l_rounds_to_fly < 0)
        l_rounds_to_fly = 0;

      d_butterfly_movie.roundsToFly = l_rounds_to_fly;
      d_butterfly_movie.gotoAndPlay("lbStart");
    }

    /////////////////////////////////////////////////////////////////////////////
    // End of class
    /////////////////////////////////////////////////////////////////////////////
  }
}

Wenn der Export des Codes aus der Ebene scripts des Haupt-Movies erfolgreich war, kann diese Eben komplett gelöscht werden. Sie enthält sowieso nur noch auskommentierten Code.

Namenskonventionen

Folgende Namenskonventionen wurden im Code eingehalten:

In den Schmetterlingsmovies (Symbol/Klasse ButterflyMovie) wurden die im 4. Teil des Tutoriums eingeführten „öffentlichen“ Namen

  • roundsToFly (Zustandsvariable)
  • lbStart und lbEnd (Label)

beibehalten, da auf diese Attribute weiterhin von außen zugegriffen wird, und zwar vom Main-Objekt aus, d.h. von dem Objekt der Klasse Main aus, das Flash bei Start des Flashfilms automatisch erzeugt. (Eigentlich wird nur auf lbStart und nicht auf lbEnd „von außen“ zugegriffen.)

In der Klasse Main wurden die Moviclips

  • d_input
  • d_butterfly_movie

dagegen gemäß der Konvention für nicht öffentlich zugängliche (private) Eigenschaften benannt, da es keine anderen Objekte gibt (und auch nicht geben soll), die auf diese Objekte zugreifen.

ActionScript

Packages

Eine Flash-Klasse ist immer in einem package enhalten. Wenn die Klasse im selben Ordner wie der Flash-Film gespeichert wird, gibt es keinen Package-Namen. Wird dagegen die Datei beispielsweise im Unterordner butterfly des Unterordners tutorium des Unterordners hsa gespeichert, so lautet der Package-Name hsa.tutorium.butterfly:

package hsa.tutorium.butterfly
{ 
  ...
}

Genau eine öffentlich zugängliche Klasse

Jede Klassen-Datei <Klassenname>.as muss genau eine öffentliche Klasse (public) mit dem Namen der Datei (ohne Endung .as) enthalten. Weitere interne Klassen können in der Datei enthalten sein, aber keine weitere öffentlich zugängliche Klasse.

Import-Anweisungen

Wie in Java steht vor der Klasse eine Liste import-Anweisungen, die den direkten Zugriff auf andere Klassen im Code ermöglicht. In der Flash-Zeitleiste müssen im Prinzip dieselben import-Anweisungen vorhanden sein. Allerdings werde in der Flash-Zeitleiste einige Standard-Klassen-Pakete defaultmäßig importiert, so dass eine Angabe von import-Anweisungen in diesem Fall unterbleiben kann. In eine Flash-Klasse dagegen müssen stets alle notwendigen import-Anweisungen angegeben werden.

Namen von Objekten auf der Bühne in der Klasse deklarieren

Die Objekte, die auf der Bühne liegen und einen Objektnamen erhalten haben, sollten in der Klasse als öffentliche (public) Zustandsvariablen (instance variables) deklariert werden. Sie werden von Flash automatisch initialisiert. Wenn sie nicht als public deklariet werden, kommt es zu Laufzeitfehlern, da Flash die automatische Initialisierung dann nicht durchführen kann.

Man könnte auf die Deklaration dieser Variablen ganz verzichten, erhält damit aber Code, der schwerer zu lesen ist. Falls man den Code nicht mit Flash, sondern mit dem Flash Builder bearbeitet, würde man außerdem Fehlermeldungen direkt im Flash-Builder-Editor erhalten, sobald man im Code auf diese Objekte zugreift.

Überführung von Code aus der Zeitleiste in die externe Klasse

Der eigentlich Code aus der Zeitleiste des ursprünglichen Movies wird in zwei Teile geteilt:

  • Im Konstruktor public function Main() wird derjenige Code eigefügt, der in der Zeitleiste direkt ausgeführt wird.
  • Hinter den Konstruktor werden alle Methoden eingefügt, die in der Zeiltleiste definiert wurden. Diese Methoden werden i. Allg. als private markiert, da der Zugriff auf diese Methoden i. Allg. nur innerhalb der Klasse erfolgt.

Im Code können und sollten Kommentare eingefügt werden (siehe ASDoc).

Das Problem mit der nicht-existierenden Bühne bei der Verwendung von TFL-Text-Objekten

In Flash CS5 gibt es das Problem, dass die Bühne (stage) beim Ausfügren des Konstruktors noch nicht initialsiert ist, wenn irgendwo auf der Bühne oder in einem Symbol ein TFL-Text verwendet wird. Diese Texte sind sehr mächtig, aber ihre Verwendung führt leider zu Problemen. (In Flash CS4 gibt es dieses Problem nicht, da TFL-Texte nicht unterstützt werden. Der folgende Text ist jedoch auch für Flash-CS4-Benutzer interessant, da auch gezeigt wird, wie man zusätzlich zur Maus-Steuerung eine Tastatur-Steuerung in einen Movie Clip integriet.)

public function Main()
{
  trace(stage);
}

Das Ergebnis dieses Trace-Aufrufes sollte [object Stage] sein, ist aber bei der Verwendung von TFL-Text gleich null. Dies hat zur Folge, dass Befehle, die direkt auf die Bühne (stage) zugreifen, nicht einfach in den Konstruktor geschrieben werden können, da zum Zeitpunkt der Konstruktion des zugehörigen Objekte die Bühnen nicht nicht existiert. Man erhält für derartige Befehle beim Starten des Filmes Null-Pointer-Exceptions.

In der Zeitleiste passieren derartige Fehler nicht, da der Code im ersten Frame erst ausgeführt wird, wenn die Bühne bereits existiert.

Workaround

In Flex gibt es ein spezielles Ereignis APPLICATION_COMPLETE, sobald die Bühne erzeugt wurde. In Flash gibt es ein derartiges Ereignis leider nicht. Man kann sich allerdings behelfen, indem man das Ereignis ENTER_FRAME abfängt. Sobald der erste Frame des Movies betreten wird, existiert die Bühne auf jeden Fall. Also tritt der Fehler nicht mehr auf.

Beispiel

<swf width="367" height="267">http://glossar.hs-augsburg.de/beispiel/tutorium/flash_cs5/butterfly/butterfly_05_external_code_multi/Butterfly05MultiFlash11.swf</swf> Erweiterte Musterlösung (Flash CS5) (SVN-Repository)

Erweiterte Musterlösung (Flash CS4) (SVN-Repository)


Bislang kann der Rundflug nur per Mausklick gestartet werden. Wenn dies auch per Tastatur möglich sein soll, muss man zusätlich einen Event Listener (Observer) für Tastatur-Ereignisse implementieren:

stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);

Die Methode o_check_enter kann dabei folgendenmaßen definiert werden.

private function o_check_enter(p_event: KeyboardEvent): void
{
  if (p_event.keyCode == Keyboard.ENTER) // Wenn die Enter-Taste gedrückt wird
    o_start(null);                       // wird der Rundflug gestartet.
}

Leider ist — sofern TFL-Texte verwendet werden — das Stage-Objekt bei Ausführung des Konstruktors noch nicht definiert. Der folgende Konstruktor erzeugt also in diesem Fall eine null-Pointer-Exception.

...
    public function Main()
    {
      d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start); 

      // Zugriff auf stage => null-Pointer-Exception
      stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);  
    }
...

Das Problem lässt sich lösen, indem man die Initialisierung erst beim Betreten des ersten Frames durchführt.

...
    public function Main()
    {
      // Wenn das Ereignis ENTER_FRAME eintritt, rufe o_init auf.
      this.addEventListener(Event.ENTER_FRAME, o_init); 
    }
    
    private function o_init(p_event: Event): void
    {
      // Da die Initialisierung nur im ersten Frame erfolgen soll,
      // muss der Event-Listener gleich wieder entfernt werden.
      this.removeEventListener(Event.ENTER_FRAME, o_init);      

      // Nun existiert das stage-Objekt!
      d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start); 
      stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);  
    }
...

Noch ein Beispiel

Für das vorherige Beispiel gibt es noch einen einfacheren Workaround. Anstelle von

stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);

schreibt man einfach

this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);

in den Konstruktor. Dies funktioniert genauso gut. Da aber ein Zugriff auf das stage-Objekt unterbleibt, gibt es bei folgenden Konstruktor keine null-Pointer-Exception:

...
    public function Main()
    {
      d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start); 

      // Zugriff auf this => keine null-Pointer-Exception
      this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);  
    }
...

Leider lassen sich Zugriffe auf das stage-Objekt manchmal nicht so leicht vermeiden. Wenn z.B. beim Filmstart der Eingabe-Fokus gleich auf das Eingabe-Feld gesetzt werden soll (das Eingabe-Feld, das den Fokus hält, wird von Flash durch einen blauen Rahmen gekennzeichnet), damit der Benutzer gleich die Rundenzahl mit der Tastatur eingeben kann und nicht erst mit der Tab-Taste oder der Maus den Fokus auf das Eingabefeld legen muss, muss man die Methode setFocus verwenden:

d_input.d_input_rounds.setFocus();

Die Methode setFocus greift intern auf das stage-Objekt zu. Der folgende Konstruktor erzeugt also eine null-Pointer-Exception. (Für Flash-CS4-Nutzer ist der folgende Code allerdings in Ordnung. Daher wurde er in der Flash-CS4-Version der erweiterten Musterlösung auch eingesetzt.)

...
    public function Main()
    {
      // Zugriff auf this => keine null-Pointer-Exception      
      d_input.d_input_rounds.setFocus();  

      d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start); 

      this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);  
    }
...

Das TLF-Text-Problem mit dem nicht-initialiserten stage-Objekt lässt sich hier nur lösen, indem man wie zuvor beschrieben die Initialisierung erst beim Betreten des ersten Frames durchführt.

...
    public function Main()
    {
      // Wenn das Ereignis ENTER_FRAME eintritt, rufe o_init auf.
      this.addEventListener(Event.ENTER_FRAME, o_init); 
    }
    
    private function o_init(p_event: Event): void
    {
      // Da die Initialisierung nur im ersten Frame erfolgen soll,
      // muss der Event-Listener gleich wieder entfernt werden.
      this.removeEventListener(Event.ENTER_FRAME, o_init);      

      // Nun existiert das stage-Objekt!
      d_input.d_input_rounds.setFocus();  
      d_input.d_button_start.addEventListener(MouseEvent.CLICK, o_start); 
      this.addEventListener(KeyboardEvent.KEY_UP, o_check_enter);
    //stage.addEventListener(KeyboardEvent.KEY_UP, o_check_enter); // wäre hier auch OK!
    }
...

Probleme der Implementierung

Die im vierten Teil des Flash-Tutoriums genannte Problem wurden noch nicht behoben, da nur der Code der Hauptzeitleiste ausgelagert wurde. Die schlechte Lesbarkeit der Timeline des Symbols ButterflyMovie sowie die Code-Duplikation, falls ein zweites derartiges Symbol erstellt werden soll, bleiben bestehen.

Diese Probleme werden erst gelöst, wenn auch der Code des Symbols ButterflyMovie in eine externe Klasse ausgelagert wird (siehe AS3-Tutorium: Flash: Butterfly 06 external code).

Quellen

  1. Kowarschick (MMProg): Wolfgang Kowarschick; Vorlesung „Multimedia-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2018; Quellengüte: 3 (Vorlesung)
  2. Musterlösung (Flash CS5)
  3. Musterlösung (Flash CS4)
  4. Erweiterte Musterlösung (Flash CS4)
  5. Erweiterte Musterlösung (Flash CS5)

SVN-Repository-Verweise