|
Dieses
Tutorial stammt aus dem Buch "Flash 5 und Actionscript professionell
- Tutorials und Workshops für fortgeschrittene Techniken". vielen Dank für die Genehmigung an den Autoren und den Verlag. |
|
Einleitung
Was
bringt dieses Tutorial?
Ermitteln der Mausposition
Lösungsansätze
Lösung
1 - unsichtbare 'Sensoren'
Lösung
2 - angehängtes unsichtbares Symbol
Verfolgung der Maus mit Objekten
Das
Grundprinzip
Beispiel
1 - Uhrzeiger
Beispiel
2- Objekt folgt Maus
Maus-/Objektverfolgung
in Flash 5
Objektorientiertes
Skripten
Beispiel
3
Was bringt dieses Tutorial?
![]()
Oft sieht man auf diversen Seiten, wie Objekte wie magnetisiert der Maus folgen,
obwohl die direkte Abfrage der Mausposition in Flash 4 nicht möglich ist.
Für diesen und verschiedene andere Effekte ist es aber unerläßlich
die Position der Maus zu kennen. Mein Ziel ist es die Grundlagen zur Positionsermittlung
und Mausverfolgung möglichst einfach zu erklären. Darauf aufbauend
sollten sich einige andere Effekte verwirklichen lassen. Den Umgang mit Filmsequenzen
sollte man bereits beherrschen.
Ich habe ein Kapitel zu Flash 5 angehängt, da ich aber denke, daß
viele Flash 4 noch eine Weile benutzen werden, habe ich den alten Teil so belassen.
Sollten Sie noch Ideen oder Kritik haben, bin ich hier per E-mail
erreichbar.
![]()
![]()
![]()
Ermitteln der Mausposition - Lösungsansätze
![]()
Um die Mausposition in Flash 4 feststellen zu können gibt es meines Wissens
2 Ansätze. Einen etwas einfacheren, der aber auch etwas ungenauer ist bzw.
Fleißarbeit bedeutet, wenn er genau sein soll und auf der anderen Seite
die genaue Ermittlung der Position durch einen kleinen Trick.
1.
Lösung: unsichtbare 'Sensoren'
Diese Lösung beruht darauf, auf der betreffenden Fläche, in der die
Mausposition abgefragt werden soll, viele kleine unsichtbare Buttons anzulegen.
Versieht man diese Buttons mit einer Rollover-Aktion, weiss man auch, an welcher
Stelle sich die Maus befindet. BEISPIEL
zu Lösungsansatz 1 anzeigen.
Der Vorteil liegt darin, daß die Buttons einfach
zu erstellen sind, man die Position nicht ständig abfragen muss (durch
die Rollover-Aktion meldet sich der Button von allein) und daß man die
Form der 'Sensorflächen' vollkommen frei bestimmen kann.
Der Nachteil liegt darin, daß man je genauer
die Abfrage sein soll, auch die Anzahl der Buttons erhöhen muss. Diese
kann einen so hohen Arbeitsaufwand erfordern, daß man über Lösung
2 vielleicht einfacher an sein Ziel kommt. Desweiteren verändert sich der
Mauszeiger zur Hand, sobald er über einen Button bewegt wird, dieses ist
in einigen Fällen auch störend.
2.
Lösung: angehängtes unsichtbares Symbol
In diesem Fall wird beim Starten des Flashfilms (oder bei Bedarf auch an anderer
Stelle) ein unsichtbares Symbol an den Mauszeiger gehängt, dessen Position
man jederzeit abfragen kann, womit man auch gleichzeitig die Position der Maus
bekommt (in Flash 5 geht das einfach mit _xmouse und _ymouse). BEISPIEL
zu Lösungsansatz 2 anzeigen.
Hier die einzelnen Schritte.
1. Schritt:
Man erzeuge ein neues Symbol ohne Inhalt mit der Eigenschaft
Filmsequenz und gebe dem ganzen einen Instanznamen (im Beispiel 'unsichtbarer_clip').
2. Schritt:
Dieses Symbol wird jetzt an den Mauszeiger gehängt in dem
man in das erste Frame der Zeitleiste unter Eigenschaften/Aktionen folgende
Aktion einträgt :
Start Drag ("unsichtbarer_clip")
Die Option 'Lock mouse to center' sollte aktiviert werden damit man die genauen Koordinaten erhält.
3. Schritt:
Nun legt man im ersten Frame des Hauptfilmes die Variablen position_x
und position_y an.
Diese geht mit der Aktion:
Set Variable: "position_x" = "" und Set Variable: "position_y" = ""
Die Werte kann man vorerst leer lassen.
4. Schritt:
Erstellen eines Movieclip-Symbols für die Positionsabfrage.
(Ich erzeuge für die Abfrage absichtlich ein eigenes Symbol, und setze
dieses in einen eigenen Layer / Ebene. Somit ist die Abfrage unabhängig
von dem Rest des Films aktiv. Sie kann aber nach Bedarf auch an anderer Stelle
eingesetzt werden)
- neues Symbol erzeugen mit 2 Frames
- In das erste Frame kommt die Abfrage, im 2. Frame ein Goto Frame (genaueres
zur Abfrage finden Sie in Beispiel 2)
![]()
![]()
Verfolgen der Maus mit Objekten
![]()
Das Grundprinzip:
Wenn man erst mal die Position ermittelt hat, kann man einem anderen Objekt
über SetProperty sagen, auf welche Position es sich bewegen soll oder wie
dieses Objekt reagieren soll (z.B. skalieren oder rotieren). Es gibt auch noch
etliche andere Wege, auf die ich hier aber erstmal nicht eingehen will.
Im Beispiel 1 wird über den weiter oben beschriebenen 1. Lösungsansatz
ein Uhrzeiger nach dem Mauszeiger ausgerichtet.
Im zweiten Beispiel wird die Position über den 2. Lösungsweg ermittelt
(angehängtes Objekt) und ein anderes Objekt verfolgt über SetProperty
den Mauszeiger.
Beispiel
1 - Uhrzeiger:
Wen man den Mauszeiger über das Ziffernblatt der Uhr bewegt, richtet sich
der Minutenzeiger nach der Maus aus.
Der Mauszeiger ist hier ein einzelnes Symbol, als Filmsequenz definiert mit
dem Instanznamen 'stunde' (nur Filmsequenzen lassen sich mit SetProperty ansprechen,
mit Buttons bzw. Grafiken geht dieses nicht).
Als 'Mausdetektor' habe ich einen Button erzeugt, der den Bereich einer Stunde
auf dem Ziffernblatt abdeckt. Diesen habe ich dann für jede weitere Stunde
kopiert und entsprechend der benötigten Position um jeweils 30° rotiert
und richtig ausgerichtet. BEISPIEL
1 anzeigen.
Damit der Stundenzeiger der Maus folgt habe ich die Buttons mit folgender Aktion belegt:
On (Roll Over)
Set Property ("/stunde", Rotation) = "0"
End On
"/stunde" steht hierbei für den Instanznamen des Symbols, Rotation
natürlich für das rotieren.
Die 0 steht für 0° Rotation (angefangen bei Stunde 12). Entsprechend
habe ich für jede weiteren Button bzw. Stunde 30° addiert (360°
/ 12 = 30°).
Das war schon alles !
Entsprechend könnte man das gleiche für den Minutenzeiger machen, wobei hier dann schon 60 Buttons erstellt werden müßten, und die Rotation pro Minute 360° / 60 = 6° entsprechen würde. Das ganze währe schon etwas mehr Aufwand, was auch sehr gut zeigt, welchen Nachteil diese Methode evtl. hat.
(Eine andere Möglichkeit wäre auch noch, eine Filmsequenz mit entsprechend vielen Frames für jede Zeigerstellung zu erstellen und mit den Buttons die Filmsequenz in das passende Frame springen zu lassen. Dazu benötigt man den TellTarget-Befehl, der Thema eines anderen Tutorials ist.)
Beispiel
2 - Objekt folgt dem Mauszeiger:
In diesem Beispiel wird, wie in Lösungsansatz 2 beschrieben, die X- und
Y-Position ermittelt und in den Variablen position_x und position_y gespeichert.
Das Symbol, welches dem Mauszeiger folgen soll wurde als Filmsequenz definiert
(nur hier kann man die Position mit SetProperty verändern).
Der Instanzname heißt 'verfolger' (nicht besonders Einfallsreich, aber
darum geht es hier ja auch nicht :-).
Die Aktionen für die Bewegung des Verfolgers habe ich mit in das gleiche
Symbol geschrieben (theoretisch könnte Sie aber auch in der Hauptzeitleiste
oder einem anderen Symbol liegen). Damit die Positionen ständig verglichen
werden, habe ich 2 Frames angelegt, wobei im zweiten Frame die Anweisung 'Go
to and Play (1)' steht, damit ein Loop entsteht.
In Frame 1 steht das wichtige Action-Script, als erstes:
Set Variable: "verfolger_x" = GetProperty ("/verfolger",_x)
Set Variable: "verfolger_y" = GetProperty ("/verfolger",_y)
Hiermit bekommen die Variablen verfolger_x und verfolger_y immer die aktuellen X- und Y-Koordinaten des Verfolger-Symbols zugewiesen. Normalerweise kann man auch im weiteren Skript direkt mit GetProperty ("/verfolger",_x) arbeiten, wenn man aber bedenkt das evtl. noch sehr viele Vergleiche gemacht werden müssen, ist das arbeiten mit Variablen (die dann kurz vielleicht nur noch vx und vy heißen) wesentlich einfacher.
Damit sich der Verfolger auch noch bewegt, kann man folgende Aktion benutzen:
If (_level0/:position_x<verfolger_x)
Set Property ("/verfolger", X Position) = verfolger_x-1
End If
Hier prüfe ich, ob position_x der maus (_level0/:position_x weil die variable
in der hauptebene liegt) kleiner ist als die x-position des verfolgers (verfolger_x).
Wenn ja, setzte ich mit SetProperty die X-Position des Verfolgers um 1 niedriger,
er bewegt sich also nach links.
Ähnlich ist die Abfrage ob die Maus rechts vom Verfolger steht, x also
größer ist, nur das verfolger_x um 1 erhöht wird:
If (_level0/:position_x>verfolger_x)
Set Property ("/verfolger", X Position) = verfolger_x+1
End If
Das gleiche macht man dann nochmal mit position_y und verfolger_y und man ist
fertig.
![]()
![]()
Maus-/Objektverfolgung in Flash 5
![]()
Die neue Version von Flash bringt wesentliche Erleichterungen was das Skripten
angeht. Ursprünglich wollte ich nur das vorhandene Flash 4 Skript an Flash
5 anpassen. Beim rumprobieren merkte ich aber, daß man mit der objektorientierten
Programmierung ziemlich einfach ein Objekt bauen kann, welches individuell der
Maus oder auch einem anderen Objekt folgen kann. Das will ich euch natürlich
nicht vorenthalten, Ihr könnt es in Beispiel
3 sehen.
Im letzten Jahr habe ich natürlich auch dazugelernt und deshalb einen Verzögerungseffekt
mit eingebaut (ich hoffe, daß er bei schnellen Rechnern genauso wirkt
wie auf meinem alten PII :-)).
Objektorientiertes Skripten
Vereinfacht bedeutet es, daß man z.B. Funktionen, die öfter (von
verschiedenen Programmteilen) aufgerufen werden auch als einzelne Funktion programmiert
und nicht widerholt an verschiedenen Stellen eingibt. Diese Funktion kann man
dann von allen anderen Stellen aufrufen und man spart somit Speicherplatz im
Quellcode.
In diesem Beispiel bedeutet es, daß ich eine Filmsequenz habe, welches
ein eigenes Skript ausführt und somit seine Position selbst bestimmt. Dadurch,
daß ich bestimmte Befehle / Variablen auf das Objekt (die Filmsequenz)
selber beziehe, kann jede Instanz dieses Objektes eigenständig arbeiten.
Objektorientiertes Programmieren geht noch wesentlich weiter und ist eigentlich
ein Studium für sich, ich denke aber daß es in diesem Zusammenhang
übertrieben wäre, weiter darauf einzugehen.
Beispiel
3 - Mousfollow mit Flash 5:
Wie aus dem folgenden Screenshot zu sehen besteht das Beispiel nur noch
aus einem Symbol, das ich 'verfolger' genannt habe. Die Filmsequenz 'radar'
ist nur Bestandteil von 'verfolger' und enthält die Animation des 'Radars',
ist aber für die Funktion selber unwichtig. Von dem Symbol 'verfolger'
habe ich 2 Instanzen auf der Bühne plaziert und die Instanznamen 'verfolger1'
und 'verfolger2' vergeben. Die Instanz 'verfolger1' soll der Maus folgen und
Instanz 'verfolger2' soll 'verfolger1' folgen.

Bild 1: Bühne und Bibliothek mit den Symbolen
Damit das Objekt weiss, was es machen soll, setze ich ein paar
Variablen in den Objektaktionen der entsprechenden Instanz. Dorthin kommt man,
indem man die Instanz mit der rechten Maustaste anklickt (für Apple-User:
'Ctrl'-Taste und dann Mausklick) und dann auf 'Aktionen' klickt.
Das Skript sieht folgendermaßen aus:
onClipEvent (load) {
xpos1 = this._x;
ypos1 = this._y;
folge = "maus";
abstandx = 0;
abstandy = 0;
}
Beim Laden der Filmsequenz (onClipEvent (load)) werden Variablen
definiert, die sich auf das Objekt beziehen.
'xpos1' und 'ypos1' entsprechen der aktuellen X- und Y-Position der Filminstanz
beim Start. Das Schlüsselwort this. bezieht sich immer auf das Objekt,
in dem der Code steht.
Die Variable 'folge' muss auf "maus" gesetzt werden, wenn die Filminstanz
der Maus folgen soll. Soll die Filminstanz einem Objekt folgen, muss der absolute
Pfad der zur verfolgenden Filminstanz angegeben werden. In den Objektaktionen
der Instanz 'verfolger2' habe ich entsprechend folge = "/verfolger1" gesetzt.
Als letztes setze ich die Variablen 'abstandx' und 'abstandy', die den Abstand
zu dem verfolgtem Objekt oder der Maus in Pixeln angeben. Statt einer Zahl kann
man hier natürlich auch einen Ausdruck benutzen, zum Beispiel die Höhe
des Objekts (abstandx=this._width;), wie ich es in der Instanz 'verfolger2'
getan habe.
Das sind die einzigen Angaben, die für jede Filminstanz getrennt gemacht werden müssen. Man bedenke, daß man hier nicht das Ursprungssymbol verändert, sondern nur die jeweiligen Instanzen!
Als nächstes kommt das Skript, welches für die Bewegung zuständig ist. Es steht in der Zeitleiste der Filminstanz und ist verständlicherweise in jeder Instanz gleich. Es muss bzw. darf nicht abgeändert werden (ausser für Testzwecke natürlich)! Die Zeitleiste besteht aus zwei Frames, damit ich eine ständig laufende Schleife erzeugen kann.

Bild 2: Zeitleiste der Filmsequenz 'verfolger'
Skript in Frame 1:
if (this.folge == "maus") {
Xpos = _level0._xmouse;
Ypos = _level0._ymouse;
} else {
Xpos = eval(this.folge add "._x");
Ypos = eval(this.folge add "._y");
}
Hier prüfe ich, ob die Filminstanz der Maus folgen soll oder
einer anderen Filminstanz und bestimme die aktuelle Soll-Position (wo die Instanz
hin folgen soll).
Ist die Variable 'folge' dieser Intsanz auf "maus" gesetzt, belege
ich die Variablen Xpos und Ypos mit der aktuellen Position der Maus (_xmouse
und _ymouse).
Ich setze _level0. davor, damit ich den absoluten Wert von der oberen linken
Bühnenecke aus bekomme. Ohne bekommt man den Wert relativ zur Filminstanz,
der in diesem Fall nicht weiterhilft.
Steht etwas anderes in der Variable 'folge', gehe ich davon aus, daß eine
Filminstanz angegeben ist und hole mir die X- und Y-Position von dieser Filminstanz.
Wenn ich also "/verfolger1" angebe, würde daraus eval("/verfolger1"
add "._x"), dieses wiederum entspricht eval("/verfolger1._x"),
womit ich die X-Position hätte. Lasse ich das eval() weg, würde Xpos
nur eine Zeichenkette mit dem Wert "/verfolger1._x" übergeben
und das ganze würde nicht mehr funktionieren. Gleiches gilt natürlich
entsprechend für Ypos.
xpos1 = (Xpos+3*xpos1)/4; ypos1 = (Ypos+3*ypos1)/4; this._x = int(xpos1+abstandx); this._y = int(ypos1+abstandy);
Als nächstes berechne ich die neue Position der Filminstanz und weise sie den Variablen xpos1 und ypos1 zu. Die Formel (Xpos+3*xpos1)/4 ergibt eine Teilstrecke zwischen den beiden Objekten (Instanz/Maus oder Instanz/Instanz) um die die verfolgende Filminstanz verschoben wird. Diese Teilstrecke wird prozentual immer kleiner, wodurch der Verzögerungseffekt entsteht.
Mit this.x und this.y setze ich dann die Position der aktuellen Filminstanz neu, welche aus der ganzzahligen (int) Summe aus 'xpos' + 'abstandx' bzw. 'ypos' + 'abstandy' besteht.
Skript in Frame 2:
gotoAndPlay (1);
Hiermit erzeuge ich eine ständig laufende Schleife, damit die Position auch immer wieder neu berechnet wird.
Das war schon alles!
Wie man sieht kann man mit einem kleinen Skript große Wirkung erzielen,
der komplette Film hat gerade mal 6kb (mit eingebundener Schriftart 23kb).
![]()
![]()