Rheinwerk Design < openbook > Rheinwerk Design - Know-how für Kreative.
Know-how für Kreative.

Inhaltsverzeichnis
Vorwort
1 Flash für ActionScript
2 ActionScript in Flash
3 Flash Pro für ActionScript
4 Grundlagen der Programmierung
5 Einfache Filmsteuerung
6 Bildschirme und Präsentationen
7 Drucken und das Kontextmenü
8 Textfelder
9 Tasten
10 Datum und Zeit
11 Rechnen
12 Farbe wechseln und Drag
13 Zeichnen und Zufall
14 Von Mäusen und Duplikaten
15 Kollisionstest
16 Sound
17 Video
18 Externe Filme
19 Vorladen und Player erkennen
20 Formulare und UI-Komponenten
21 Komponenten anpassen
22 Formulare versenden
23 Warenkorb
24 Ausblick auf ActionScript 3
Stichwort
Ihre Meinung?

Spacer
 <<   zurück
Einstieg in ActionScript von Christian Wenz, Tobias Hauser, Armin Kappler
Aktuell zu Flash 8
Buch: Einstieg in ActionScript

Einstieg in ActionScript
brosch., mit CD und QuickFinder und Referenz
416 S., 24,90 Euro
Rheinwerk Design
ISBN 978-3-89842-774-6
Pfeil 15 Kollisionstest
  Pfeil 15.1 Kollisionen abfangen
  Pfeil 15.2 Aus Kollisionen wird eine Anwendung

15 Kollisionstest

Zwei MovieClips treffen sich – die Grundlage für viele Animationen und Spiele

Sie werden lernen:

  • Wie führen Sie einen Kollisionstest durch?
  • Wie lässt sich die Kollision exakt feststellen?
  • Welche Nachteile haben handgeschriebene Lösungen?

Fahre wie der Teufel und du wirst ihn bald treffen. – Robert Lembke

Interaktiv wird ein Flash-Film, wenn der Nutzer mit Objekten interagiert. Aber auch Objekte können zueinander in Beziehung stehen. Damit aus vormals gesitteten Beziehungen nicht totales Chaos wird, müssen Sie Kollisionen zwischen den Objekten abfangen. Kollision heißt, dass sich zwei Objekte treffen. Und wie meist bei ActionScript handelt es sich bei diesen Objekten um MovieClips.


Rheinwerk Computing - Zum Seitenanfang

15.1 Kollisionen abfangen  topZur vorigen Überschrift

Für das Abfangen von Kollisionen gibt es zwei Möglichkeiten:

  • Die Methode hitTest() des MovieClip-Objekts liefert einen Wahrheitswert, ob eine Kollision vorliegt (true) oder nicht (false).
  • Eine handgeschriebene Lösung, die die Koordinaten von Objekten vergleicht.

Koordinatensystem

Die Koordinaten für hitTest() entstammen automatisch dem Koordinatensystem des Hauptfilms; sie heißen globale Koordinaten. Mit den Methoden localToGlobal() und globalToLocal() des MovieClip-Objekts können Sie normale Koordinaten eines MovieClips in globale Koordinaten umwandeln und umgekehrt. Dazu benötigen Sie ein Objekt (Object), das die beiden Koordinaten speichert. Mehr hierzu finden Sie in der Hilfe zu den beiden Methoden. Ein Beispiel sehen Sie im Abschnitt »Handgeschriebene Lösungen«.


Um die zweite Alternative drückt sich der Programmierer gerne, außer es geht wirklich nicht anders. Insofern ist von Interesse, was Sie mit hitTest() bewerkstelligen können und was nicht.

hitTest() ist in zwei Varianten einsetzbar:

1. mit einem beliebigen Punkt auf der Bühne des Hauptfilms:
       
movieclip_mc.hitTest(x, y, Form)
    • Als Parameter geben Sie die x- und y-Koordinate des Punktes an. Form enthält einen Boolean. Beim Wert true wird nur die Form des MovieClips (der gefüllte Bereich) zum Testen herangezogen. Das heißt, nur wenn der Punkt innerhalb der Form des MovieClips liegt, liefert hitTest() den Wert true zurück. Ist der Wert false, zählt die Begrenzung um den Inhalt des MovieClips. Die Begrenzung ist der kleinstmögliche rechteckige Bereich, der sich um alle Inhalte des MovieClips legen lässt. In diesem Fall zählt also auch der transparente Bereich zwischen dem Inhalt und der Begrenzung dazu.

Abbildung 15.1 Form und Begrenzung eines MovieClips.

2. Die zweite Variante für den Einsatz von hitTest() wird mit einem anderen MovieClip realisiert:
       
movieclip_mc.hitTest(Ziel);
    • In diesem Fall ist das Ziel ein beliebiger anderer MovieClip, dessen Instanznamen Sie angeben. Relevant sind allerdings die Begrenzungen der beiden MovieClips, nicht der Inhalt selbst.
hitTest() im Test

Das Kernproblem bei hitTest() ist, dass beim Kollisionstest zweier MovieClips nur die Begrenzungen, nicht aber der Inhalt relevant sind.

Dies können Sie ganz einfach ausprobieren: Erzeugen Sie einen Kreis und wandeln Sie ihn in einen MovieClip um. Duplizieren Sie den MovieClip und geben Sie beiden einen Instanznamen (bei uns test1_mc und test2_mc). Einer der beiden Kreise wird nun per Drag & Drop beweglich, wenn Sie folgenden Code in die Aktion einfügen:

on (press) {

startDrag(this);

}

on (release, releaseOutside) {

stopDrag();

}

Ab nächstem Schritt müssen Sie im ersten Schlüsselbild des Hauptfilms mit einer Ereignisprozedur testen, ob sich die zwei MovieClips berühren:

_root.onEnterFrame = function() {
   if (this.test1_mc.hitTest(test2_mc)) {
      trace("Hit");
   }
};

Abbildung 15.2 Wie Sie sehen, treffen sich die beiden MovieClips schon am Rand der Begrenzungen.

Das Beispiel zeigt: Wenn absolute Genauigkeit zählt und die MovieClips ungewöhnlich geformt sind, hilft nur eine handgeschriebene Lösung. Überlegen Sie sich aber von Fall zu Fall, ob die hitTest()-Variante nicht doch ausreicht. Zum einen ist sie schneller, zum anderen wird sie auch mit Größenänderungen fertig.

Sie finden unser kleines Beispiel unter dem Namen hittest.fla für Flash MX 8 bzw. 2004 (Ordner Flash8 bzw. FlashMX2004) und Flash MX (Ordner FlashMX) auf der CD-ROM.

Handgeschriebene Lösungen

Väter der Gedanken

Für jede der Varianten gibt es Paradebeispiele, die zwar nicht nachweislich die ersten waren, aber am weitesten verbreitet sind. Für eine rein mathematische Berechnung der Kollision zweier Kreise ist der ActionScript-Experte Colin Moock zuständig. Die kleinen, unsichtbaren MovieClips sind hauptsächlich durch das Bounce- und Collide-Beispiel von Gary Fixler bekannt.


Bei den handgeschriebenen Lösungen schwirrt eine Unzahl an Varianten durch das Netz. Fischt man etwas intensiver, wird die Ähnlichkeit vieler Varianten offensichtlich. Im Kern gibt es drei Ideen, die Sie verfolgen könne:

  • Sie überprüfen jeden einzelnen Punkt eines Objekts. Diese Lösung kommt am seltensten zum Einsatz, da sie viel zu aufwendig ist.
  • Sie verwenden eine geometrische Formel, um den Abstand zwischen zwei Elementen festzustellen. Wird der Abstand zu gering, meldet das Skript eine Kollision.
  • Sie erzeugen leere, unsichtbare MovieClips, um die Form des MovieClips, der geprüft werden soll, näherungsweise darzustellen. Die kleinen MovieClips sind dabei dem eigentlich zu testenden MovieClip untergeordnet.

Sehen Sie sich die letzten zwei Ideen für handgeschriebene Lösungen einmal an Beispielen an. Wir verwenden dazu die beiden Kreise aus dem vorigen Abschnitt. An Drag & Drop ändert sich nichts, dieses Mal soll die Kollisionsabfrage aber exakt erfolgen.

Werfen Sie zuerst einen Blick auf die geometrische Lösung (kollision_handgeschrieben.fla), die aus mehreren Teilen besteht:

1. Am Anfang erstellen Sie eine ZählervariableZählervariable und starten dann die Ereignisprozedur onEnterFrame (Ereignisprozedur)onEnterFrame, um den Kollisionstest in regelmäßigen Abständen durchzuführen:
       
var i:Number = 0;
_root.onEnterFrame = function() {
2. Im nächsten Schritt berechnen Sie die Entfernung der zwei zu testenden Kreise auf der x- und auf der y-Achse:
       
var entX_num:Number = this.test1_mc._x – this.test2_mc._x;
var entY_num:Number = this.test1_mc._y – this.test2_mc._y;
3. Die Entfernungen auf den beiden Achsen bilden zusammen zwei Schenkel eines rechtwinkligen Dreiecks. Hier kommt Ihnen der Satz des Pythagoras zu Hilfe:Math.pow() (Methode)
       
var entfernung_num:Number = Math.pow(entX_num, 2) + Math.pow(entY_num, 2);
4. Jetzt berechnen Sie den Radius der beiden Kreise:
       
var radius1_num:Number = this.test1_mc._height / 2;
var radius2_num:Number = this.test2_mc._height / 2;
5. Aus dem Radius entsteht die minimale Entfernung:
       
var minEntfernung_num:Number = Math.pow((radius1_num + radius2_num), 2);
6. Ist die minimale Entfernung größer als die gemessene, berühren sich die beiden Kreise:
       
   if (entfernung_num < minEntfernung_num) {
      trace("Hit" + ++i);
   }
};

Abbildung 15.3 Dank geometrischer Berechnung funktioniert der Kollisionstest nun exakt.

Als Nächstes widmen wir uns der Lösung mit den leeren, unsichtbaren MovieClips (kollision_handgeschrieben2.fla). Hier müssen Sie einiges an Vorbereitungsarbeit erledigen:

1. Sie erstellen ein neues MovieClip-Symbol, das ungefüllt in der Bibliothek landet.
       
2. Anschließend wechseln Sie in den MovieClip, den Sie mit dem Kollisionstest versehen möchten.
       
3. Ziehen Sie den leeren MovieClip von der Bibliothek in den zu testenden MovieClip.
       
4. Duplizieren Sie den leeren MovieClip und ordnen Sie die Duplikate an den Grenzen des zu testenden MovieClips an. Das Ergebnis dieser etwas stupiden Arbeit sehen Sie in der nächsten Abbildung und im Beispiel auf der CD-ROM, wenn Sie in den MovieClip des rechten Kreises wechseln.
       

Abbildung 15.4 Der Kreis wird von leeren MovieClips umrahmt. Ein leerer MovieClip besteht nur aus einem weißen Kreis. Wird er angeklickt, erhält der weiße Kreis ein schwarzes Kreuz.

Nach diesen Vorbereitungen kommen wir zu ActionScript. Der Code landet im ersten Schlüsselbild des Hauptfilms auf der Ebene ActionScript. Nun erledigen Sie die weiteren Schritte:

5. Wieder benötigen Sie zuerst die Zählervariable i und die Ereignisprozedur onEnterFrame:
       
var i:Number = 0;
_root.onEnterFrame = function() {
6. Nun folgt eine Variable, die die Namen von einzelnen MovieClips aufnehmen soll:
       
var name_str:String;
7. Der nächste Schritt ist der große Trick:
       
for (name_str in this.test2_mc) {
    • Eine for-in-Schleife geht nach und nach alle MovieClips durch, die test2_mc direkt untergeordnet sind. Es handelt sich hier um die leeren MovieClips. Ihre Namen werden in die Variable name_str gespeichert. Das funktioniert, obwohl die MovieClips keine Instanznamen besitzen. Nun haben Sie vollen Zugriff auf die leeren, unsichtbaren MovieClips.
8. Den Zugriff nutzen Sie gleich, um die Koordinaten des jeweiligen MovieClips in das Objekt punkt als Eigenschaft zu speichern.
       
var punkt = new Object();
punkt.x = this.test2_mc[name_str]._x;
punkt.y = this.test2_mc[name_str]._y;
9. Der folgende Schritt verrät, warum Sie dieses Objekt benötigen: Mit der Funktion localToGlobal(Punkt) können Sie einen beliebigen Punkt aus dem lokalen (MovieClip-) Koordinatensystem in das globale Koordinatensystem des Hauptfilms umwandeln. Der Punkt muss allerdings als Objekt angegeben sein.
       
this.test2_mc.localToGlobal(punkt);
10. Nun folgt die Überprüfung, ob der Punkt, den Sie aus dem leeren MovieClip gewonnen haben, den zweiten Kreis berührt.
       
if (this.test1_mc.hitTest(punkt.x, punkt.y, true)) {
         trace("Hit" + ++i);
      }
   }
};
    • Da ein Punkt mit der exakten Form getestet werden kann, benötigen Sie die leeren MovieClips immer nur für einen der beiden MovieClips, deren Kollision Sie testen möchten.

Abbildung 15.5 Die Lösung mit leeren MovieClips ergibt ebenfalls eine exakte Kollisionsabfrage.

Prinzipiell gilt: Wenn es eine geometrische Lösung gibt, sollten Sie diese in der Regel vorziehen, da sie einfacher ist und eine bessere Performance besitzt.

Die geometrische Lösung scheitert allerdings dann, wenn es sich nicht um eine überprüfbare Form handelt. Deswegen ist in der Praxis die Lösung mit leeren, unsichtbaren MovieClips wesentlich häufiger.

hitArea – Kollision für Schaltflächen-MovieClips

Ab Flash MX können Sie MovieClips wie Schaltflächen behandeln. Eine neue Eigenschaft in der MovieClip-Klasse ist Ihnen dabei behilflich: hitArea. Diese Eigenschaft gibt für einen MovieClip an, welcher MovieClip seine Hitarea ist, also der Bereich, an dem er gedrückt wird:

movieclip_mc.hitArea = andererMovieclip_mc;

Was heißt das? Sie können Funktionalität mit einem MovieClip verbinden und sie wird nur aufgerufen, wenn der Nutzer einen anderen MovieClip drückt.

Auf der CD-ROM finden Sie unter dem Namen hitarea.fla ein Beispiel, bei dem die linke Schaltfläche (schalt1_mc) die rechte Schaltfläche (schalt2_mc) als Hitarea besitzt. Der linken Schaltfläche ist eine Ereignisprozedur zugeordnet, die etwas ausgibt, wenn der Nutzer auf die rechte Schaltfläche drückt (onPress):

this.schalt1_mc.hitArea = this.schalt2_mc;
this.schalt1_mc.onPress = function() {
   trace("Hit");
};

Der Effekt: Die linke Schaltfläche ist für den Nutzer funktionslos, wenn er aber die rechte drückt, wird die mit der linken verknüpfte Meldung ausgegeben.

Abbildung 15.6 Die linke Schaltfläche besitzt die Funktionalität, aber aufgerufen wird sie, wenn der Nutzer auf die rechte Schaltfläche klickt.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 <<   zurück
  
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: ActionScript 3 – Das Praxisbuch
ActionScript 3
Das Praxisbuch

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: JavaScript






 JavaScript


Zum Rheinwerk-Shop: jQuery






 jQuery


Zum Rheinwerk-Shop: Responsive Webdesign






 Responsive Webdesign


Zum Rheinwerk-Shop: Suchmaschinen-Optimierung






 Suchmaschinen-
 Optimierung


Zum Rheinwerk-Shop: Schrödinger lernt HTML5, CSS3 und JavaScript






 Schrödinger lernt
 HTML5, CSS3
 und JavaScript


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern