Anzeige
Tutorialbeschreibung

Regen mit AS simulieren (Partikeleffekt)

Regen mit AS simulieren (Partikeleffekt)

Unter special effects spielen Partikeleffekte eine wichtige Rolle. Am Beispiel von Regen wollen wir uns eine Umsetzung in Actionscript anschauen.

Version: ab Flash MX, AS 1.0

Niveau: Fortgeschrittene Anfänger (eine neue Kategorie, die hiermit eingeführt wird)

Vorkenntnisse: Grundlagen Flash, Grundlagen Actionscript (MovieClip-Symbole, attachMovie, Schleifen, enterFrame, parametrisierte Funktionen, Arrays, Math.random, Math.ceil) – wer nun glaubt, bei all diesen Voraussetzungen gebe es eh' nichts Neues mehr zu lernen, irrt.

Lernziele: Partikeleffekte in AS skripten lernen


„Fiat lux“ spricht der Herr, „fiat pluvia“ entgegnet der Programmierer – zumindest wäre das in der schwülen Hitze des diesjährigen Sommers der zeitgemäße Anfang im Buch der Bücher. Wir verschaffen uns etwas virtuelle Abkühlung, indem wir mit Flash Regen simulieren wollen. Skripttechnisch gesehen zählt eine Regensimulation zu den Partikeleffekten. Einfach formuliert, sprechen wir dann von Partikeleffekten, wenn sich eine große Anzahl an ähnlichen oder gleichen Objekten ähnlich oder gleich verhält. Klassische Beispiele wären neben dem erwähnten Naß etwa Schnee, Explosionen oder Feuerwerk.

In der simpelsten Variante wollen wir die Momentaufnahme eines Regens skripten, will heißen: wenn unsere swf aufgerufen wird, dann erscheint der Regen sofort in vollständiger Pracht auf dem Monitor. Und mit einem Mausklick wird es auch wieder vollständig trocken, wer will, kann dann gerne auch noch die Sonne scheinen lassen. Langsam einsetzender und später auch langsam abebbender Regen soll hier nicht näher behandelt werden.

Um besser die benötigten Daten verwalten zu könenn, wollen wir alles, was sich auf den Regen bezieht, einem entsprechenden Objekt zuweisen. Damit orientieren wir uns an einem grundlegenden Arbeitsprinzip in AS (und in der Programmierung allgemein): alles, was von der Logik her zusammen hängt, wird mit Hilfe eines übergeordneten Objekts erfasst. Wenn also zum Regen die Erzeugung der Tropfen, ihre Positionierung und ihre Bewegung gehören, dann weisen wir alles einem einzigen übergeordneten MovieClip zu anstatt es in _root einzufügen. Auf diese Weise kann unser Regen prinzipiell zu jedem beliebigen Zeitpunkt an jeder beliebigen Stelle aufgerufen und wieder gelöscht werden, ohne anderen Objekten auf _root in die Quere zu kommen. Falls Interesse besteht, kann dieses Thema im Rahmen eines Einführungskurses AS behandelt werden.

  1. Erstellen Sie einen neue leere Datei mit folgenden Eigenschaften: Größe 550x400, Bildwiederholrate 18, Hintergrund weiß (eigentlich: beliebig, Hauptsache, die gewählte Farbe kontrastiert zur Farbe der Tropfen).
  2. Erstellen Sie mit <strg><F8> einen leeren MovieClip (Name und Verknüpfungsname „mc_regen“).
  3. Zeichnen Sie im Symbolbearbeitungsmodus des eben erstellten MCs einen einsamen, hellblauen Regentropfen (Breite: 2 Pixel, Höhe: 8 Pixel, x-Position: –1, y-Position: -4, hellblau).
  4. Benennen Sie in der Zeitleiste von _root die einzige vorhandene Ebene um in „actions“.
  5. Öffnen Sie das Skriptfenster und schreiben folgendes Bildskript (vergewissern Sie sich, daß Sie in der Szene 1, nicht jedoch im Symbolbearbeitungsmodus von mc_regen arbeiten):
this.createEmptyMovieClip("regen", 1);
regen._x = regen._y = 0;

Damit erzeugen wir auf _root einen leeren MovieClip namens „regen“, der als Behälter für alle Tropfen dienen wird. Die 2. Zeile positioniert ihn auf dem Koordinatenursprung der Hauptzeitleiste, so daß lokales Koodinatensystem des MCs und globales Koordinatensystem von _root identisch sind. Wir ersparen uns das mühsame Umrechnen diverser Koordinaten. Aus Sicht von AS hätten wir diese Zeile zwar nicht benötigt, da alle attachten Objekte, denen keine Position zugewiesen wurde, automatisch auf 0,0 gesetzt werden. Das verführt jedoch zu einem etwas schlampigen Stil, der so in anderen Sprachen, denen ein automatisches Initialisieren von Objekteigenschaften unbekannt ist, nicht funktioniert. Zeile 2 ist daher optional (zugegeben: aus Bequemlichkeit verzichte ich auch gerne darauf).

Übrigens: von der Schreibweise her ist Zeile 2 ist identisch mit:

regen._x = 0;
regen._y = 0;

Wir wollen im weiteren Verlauf jedoch bei der kürzeren Schreibweise von vorhin bleiben.

  1. Zu sehen ist natürlich noch nichts, da sich am hellen Himmel noch keine Wolkenberge auftürmen. Aber immerhin: einen Tropfen kann man schon hervorzaubern, indem man in Zeile 3 scheibt:

regen.attachMovie("mc_regen", "r", 1);

Da ist er wieder, unser einsamer Tropfen: beim Testen im Vollbildmodus taucht er links oben auf, scheinbar verhakt im Koordinatenursprung des MCs regen. Im Fenstermodus dagegen ist aufgrund der geringen Größe des Tropfens und der hellen Färbung kaum etwas zu erkennen. Da sich natürlicher Regen eher selten so verhält, sondern vielmehr einen intensiven Drang verspürt, geradezu unberechenbar aufzutauchen und sich nach unten zu bewegen, wollen wir auch unserem Tropfen zu mehr Realismus verhelfen.
  1. Schreiben Sie in Zeile 4:

regen.r._x = Math.ceil(Math.random()*Stage.width);
regen.r.onEnterFrame = function() {
  this._y += 20;
};

Beim Testen zeigt sich, daß wir dem natürlichen Drang eines Regentropfens nun besser gerecht werden: er taucht zufällig auf und macht sich schnell nach unten davon. Prima wäre es, wenn ihm andere Tropfen nacheifern könnten. Ein korrekter Test erfordert eigentlich den Fenstermodus, da Flash ansonsten Stage.width nicht richtig verwendet. Den Effekt selbst sieht man auch im Vollbildmodus, aber die Pixelwerte weichen vom Fenstermodus ab (was wir in diesem Fall allerdings optisch nicht wahrnehmen).

  1. Ersetzen Sie alle Zeilen ab 3 durch nachfolgende Zeilen (fett):
this.createEmptyMovieClip("regen", 1);
regen._x = regen._y = 0;
for (i=1; i<=60; i++) {
  regen.attachMovie("mc_regen", "r"+i, i);
  regen["r"+i]._x = Math.ceil(Math.random()*Stage.width);
  regen["r"+i].onEnterFrame = function() {
  this._y += 20;
  };
}

Mit der for-Schleife weisen wir Flash an, 60 mal unseren Tropfen einzufügen, jeweils eine zufällige x-Position zuzuweisen und alle Objekte nach unten zu bewegen. Um jedes einzelne Objekt korrekt anzusprechen, erzeugen wir Instanznamen, die, gebunden an die Zählvariable i, einfach um eins inkrementiert werden. Daraus entsteht dann regen.r1 für den ersten, regen.r2 für den zweiten usw. Regentropfen. Um jedem Tropfen eine Zufallsposition und ein enterFrame-Ereignis zuweisen zu können, müssen wir den Instanznamen dynamisch übergeben, eben als Konkatenation „r“ + i. Damit Flash diesen Ausdruck als MovieClip interpretiert, nmuß er ausgewertet, also evaluiert werden. Das geschieht mit Hilfe der eckigen Klammer regen[„r“+i] (das würde natürlich auch mit eval() funktionieren). Achten Sie beim Schreiben darauf, daß in diesem Fall unmittelbar vor der eckigen Klammer kein Punkt eingefügt wird. Da unter den Vorkenntnissen attachMovie, Schleife und Ereignisse genannt werden, erübrigt sich eine weitere Erläuterung der Syntax.

Der Zugriff auf die Instanznamen läßt sich noch vereinfachen. Man könnte in den Parametern von attachMovie Instanzeigenschaften als neues Objekt innerhalb geschweifter Klammern übergeben. Dann erhalten wir eine wundervoll unlesbare und lange, aber umso professioneller wirkende Codezeile, auf die wir aber hier verzichten wollen. Alternativ ließe sich eine Variable zum Speichern der Instanzen einrichten.

  1. Ändern Sie daher in der Schleife den Code wie folgt (fett):
for (i=1; i<=60; i++) {
  var o = regen.attachMovie("mc_regen", "r"+i, i);
  o._x = Math.ceil(Math.random()*Stage.width);
  o.onEnterFrame = function() {
    this._y += 20;
  };
}

Anstatt jedesmal den Instanznamen neu zu berechnen, weisen wir die regen.attachMovie()-Methode direkt der lokalen Variablen o zu. Nun verweist o immer auf die aktuelle Instanz. Das können Sie auch testen, indem Sie nach dem Einrichten von o und vor der Zuweisung von dessen x-Position ein trace(o) einfügen. Im Nachrichtenfenster erscheint dann _level0.regen.r1, _level0.regen.r2 usw (wobei _level0 sich auf _root bezieht). Gegenüber der vorhergehenden Variante sehen wir zwar keinen optischen Unterschied, aber der Code ist effektiver geschrieben.

Momentan gleicht unser Regen einem sehr kurzen Schauer, da alle beim Einfügen auf der y-Position 0 starten (oh, Mist, erwischt: ganz oben wurde doch gesagt, man solle auch 0-Positionen explizit initialisieren, und das wurde die ganze Zeit unterschlagen!).

  1. Fügen Sie daher nach der Definition der x-Position und vor der Zuweisung des enterFrame-Ereignisses eine neue Zeile ein:

o._y = Math.ceil(Math.random()*Stage.height);

Sowohl in x- wie auch in y-Richtung werden nun bei Start alle Tropfen zufallsverteilt auf dem Screen eingeblendet und fallen nach unten. Prima, denken wir, aber Puristen zucken zusammen, haben wir doch nicht kontrolliert, ob ein Tropfen exakt am linken oder rechten Rand eingeblendet wird. Denn immerhin kann unser Zufallswert 1 oder 550 betragen. Der eingeblendete Regentropfen wird dann grausam beschnitten. Diese Ungenauigkeit gönnen wir uns jetzt, da sie weder programmiertechnisch noch optisch ins Gewicht fällt. Wir haben momentan ohnehin ein anderes Problem. Denn nach dem hübschen Fall herrscht wieder augenblickliche Trockenzeit, schließlich verlassen die Tropfen den Screen am unteren Rand ungebremst und kommen – die Erde ist rund – vielleicht nach ein paar Tagen oben wieder zurück. In der hektischen Zeit, in der wir heutzutage leben, möchte jedoch niemand wirklich so lange warten.

  1. Ergänzen Sie das enterFrame-Ereignis folgendermaßen (fett):
o.onEnterFrame = function() {
  this._y += 20;
  if(this._y >= Stage.height){
    this._y = 0;
  }
};

Wir kontrollieren, ob die y-Position jedes einzelnen Tropfens größer oder gleich der Höhe der Bühne ist. Wenn ja, dann setzen wir ihn einfach an den oberen Rand. Da sein enterFrame nicht gelöscht wurde, bewegt er sich dann wieder ohne unser weiteres Zutun nach unten. Wichtig ist, daß die Positionskontrolle ebenfalls im enterFrame erfolgt. Denn wir müssen ja zu jedem beliebigen Zeitpunkt, also permanent, nachschauen, ob er schon die Grenze erreicht hat.

Im Vollbildmodus begrüßt Sie ein Februarschauer mit Regenpausen, im Fenstermodus herrlicher Dauerregen nach Novemberart. Zugegeben: das mit dem Novemberregen ist eher arglistige Täuschung, denn wie jedermann weiß, herrscht im Herbst Wind, unsere Tropfen fallen jedoch senkrecht!

  1. Fügen Sie innerhalb des enterFrames zwischen this._y und die if-Abfrage folgenden Zugriff auf die x-Position der Tropfen ein:

this._x += 10;

Da wir nun in jedem enterFrame sowohl die y-Position (der vertikale Fall) wie auch die x-Position (der Seitenwind) verändern, bewegen sich die Tropfen nach rechts unten. Leider ist der Wind so stark geworden, daß er gleich auch die Regenwolken wegbläßt.

  1. Schreiben Sie daher nach der ersten if-Abfrage:
if(this._x > Stage.width){
  this._x = Stage.width-this._x;
}

So wie die y-Position muß auch die x-Position permanent kontrolliert werden. Sobald ein Regentropfen in x-Richtung rechts die Bühne verläßt, ermitteln wir seinen Abstand zum rechten Rand und positionieren ihn um diesen Betrag verschoben außerhalb des linken Bühnenrands. Da in dem Fall seine x-Position größer ist als die Bühnenbreite, ergibt die Berechnung eine negative Zahl. Diese können wir dann direkt als neue X-Position übernehmen und erhalten automatisch eine Position außerhalb der Bühne. Beim nächsten enterFrame taucht er dann wieder auf der Bühne auf, da er ja um den Betrag unserer Windstärke nach rechts versetzt wird.

Was gemeint ist, läßt sich besser verstehen, wenn wir einen einzelnen Tropfen unter dem Pixelelektronenmikroskop in dem Augenblick betrachten, wenn er gerade den rechten Rand überschreiten möchte (Abb. 2):

Bilder

Aufgrund der Anweisung innerhalb der if-Abfrage wird er am linken Rand neu positioniert (Abb. 3):

Bilder

Theoretisch könnte man auch für die y-Position eine derartige Berechnung durchführen, aber es reicht vollkommen, wenn der Tropfen einfach am oberen Rand auf 0 eingefügt wird.

Zu korrigieren bleibt noch die Ausrichtung der Tropfen. Hier hilft die Trigonometrie weiter. Bitte schwelgen Sie einen Augenblick in guten Erinnerungen an jene Schulstunden, in denen Geometrie und Trigonometrie auf dem Lehrplan standen. Dabei können Sie sich den Vorwurf „Ach hätte ich doch damals nur aufgepasst!“ ruhig sparen, denn wir holen jetzt das Verpaßte in aller Kürze nach.

Wenn in einem rechtwinkligen Dreieck Ankathete und Gegenkathete bekannt sind, dann läßt sich der erforderliche Winkel der Hypothenuse – der Bewegungsrichtung unserer Regentropfen - berechnen. Was vielleicht herrlich unverständlich klingt, sieht grafisch folgendermaßen aus (Abb. 4):

Bilder

Ankathete und Gegenkathete ergeben sich in unserem Fall einfach aus der Fall- und der Windgeschwindigkeit. Da sich diese Werte im Laufe der Animation nicht ändern, können wir sie direkt in die Gleichung übernehmen. Mit Hilfe von Math.atan2 können wir die Ausrichtung errechnen, wenn wir die Zielposition (genau genommen: die Entfernung zum Ziel in y-Richtung sowie die Entfernung zum Ziel in x-Richtung) als Parameter übergeben.

Bevor wir die benötigte Formel verwenden können, bleiben noch zwei kleine Probleme zu lösen. Ein Winkel von 0 Grad ist in der Mathematik dann gegeben, wenn ein betreffendes Objekt sich entsprechend der x-Achse ausrichtet. Wir müssen also entweder jeweils 90 Grad bei der noch zu errechnenden Drehung hinzuaddieren (letztlich ein überflüssiger Rechenvorgang), oder wir drehen unseren Tropfen von Anfang an in die richtige Richtung.

  1. Öffnen Sie mc_regen im Symbolbearbeitungsmodus und ändern Sie seine Werte im Eigenschaftsfenster wie folgt: Breite 8, Höhe 2, x-Position –4, y-Position –1. Damit weist er nach rechts und ist wie zuvor mittig ausgerichtet. Wie in der guten alten Waschmittelwerbung gibt uns ein vorher – nachher-Bild die richtige Vorstellung:

Bilder

Das zweite Problem betrifft die Maßeinheit. Winkel lassen sich sowohl in Bogenmaß (radiant) wie in Grad angeben. Die von uns einzusetzende Funktion verwendet Bogenmaß, die Eigenschaft _rotation erwartet aber Grad. In Grad gemessen ergibt ein Vollkreis 360, in Bogenmaß 2 PI. Da diese Werte unabhängig vom konkreten Kreis immer im gleichen Verhältnis zueinander stehen, kann man Bogenmaß in Grad umrechnen.

  1. Fügen Sie in eine neue Zeile unmittelbar vor das enterFrame-Ereignis ein:

o._rotation = (Math.atan2(20, 10))*(180/Math.PI);

Damit müßte Ihr Skript zu diesem Zeitpunkt so aussehen:

this.createEmptyMovieClip("regen", 1);
regen._x = regen._y = 0;
for (i=1; i<=60; i++) {
  var o = regen.attachMovie("mc_regen", "r"+i, i);
  o._x = Math.ceil(Math.random()*Stage.width);
  o._y = Math.ceil(Math.random()*Stage.height);
  o._rotation = (Math.atan2(20, 10))*(180/Math.PI);
  o.onEnterFrame = function() {
    this._y += 20;
    this._x += 10;
    if(this._y >= Stage.height){
      this._y = 0;
    }
    if(this._x > Stage.width){
      this._x = Stage.width-this._x;
    }
  };
}

Wenn Sie jetzt testen, fällt der Regen schräg nach rechts unten. Experimentieren Sie ruhig mit verschiedenen Werten für Fall- und Windgeschwindigkeit. Sind beide Werte identisch, erhalten Sie eine diagonale Bewegung. Natürlich kann man auch völlig unsinnige Werte wie etwa eine negative Fallgeschwindigkeit eingeben; so etwas müsste man im Fall der Fälle per Skripting einschränken, soll aber hier nicht weiter thematisiert werden.

Nun müssen wir das Skript noch etwas polieren.

Generell sollte man viele enterFrame-Ereignisse vermeiden, da sie zum einen unübersichtlich sind und zum anderen den Flash-Player ausbremsen können. Besser wäre ein einziges enterFrame, in dem die Animation aller Tropfen vorgenomen wird.

  1. Fügen Sie daher nach der Einrichtung des MCs regen und vor der for-Schleife ein Array ein:

regen.aTropfen = [];

  1. In diesen Behälter wollen wir alle Tropfen speichern. Erweitern Sie die for-Schleife unmittelbar vor der schließenden Klammer um:

regen.aTropfen.push(o);

Sobald ein Tropfen in den MovieClip regen eingefügt wird, erfassen wir ihn mit unserem Array. Jetzt müssen wir regen nur noch ein enterFrame zuweisen, das für eine Animation aller in dem array enthaltenen Objekte sorgt.

  1. Löschen Sie dazu das vollständige o.onEnterFrame-Ereignis. Übrig bleibt dann nur noch folgendes Skript:
this.createEmptyMovieClip("regen", 1);
regen._x = regen._y=0;
regen.aTropfen = [];
for (var i = 1; i<=60; i++) {
  var o = regen.attachMovie("mc_regen", "r"+i, i);
  o._x = Math.ceil(Math.random()*Stage.width);
  o._y = Math.ceil(Math.random()*Stage.height);
  o._rotation = (Math.atan2(20, 10))*(180/Math.PI);
  regen.aTropfen.push(o);
}
  1. Nach der for-Schleife ergänzen Sie folgendes enterFrame-Ereignis:
regen.onEnterFrame = function() {
  for (e in this.aTropfen) {
    with (this.aTropfen[e]) {
      _x += 10;
      _y += 20;
      if (_y>Stage.height) {
        _y = 0;
      }
      if (_x>Stage.width) {
        _x = Stage.width-_x;
      }
    }
  }
};

In jedem enterFrame greift der MovieClip regen auf alle Objekte im Array regen.aTropfen zu. Er sorgt dafür, daß sich jeder Tropfen permanent um 20 Pixel nach unten und um 10 nach rechts bewegt. Wird eine Grenze (unten/rechts) überschritten, erfolgt der Neustart des Tropfens am oberen Rand. Genau das haben die Tropen zuvor ebenfalls getan – aber dazu benötigten wir 60 enterFrames und nicht eines. Die with-Anweisung ist eine bequeme Möglichkeit, alle Objekte anzusprechen, ohne jedesmal explizit den Instanznamen schreiben zu müssen.

Sie werden bemerkt haben, daß wir manche Werte wie z.B. die Fallgeschwindigkeit mehrfach eintragen mußten. Das ist bei einer Änderung fehleranfällig. Zudem müssen wir jedesmal, wenn wir unseren Regen verwenden wollen, alle Anweisungen neu eintragen. Erheblich flexibler sind wir, wenn wir eine parametrisierte Funktion verwenden.

  1. Packen Sie alles, was bisher geschrieben wurde, in eine Funktion hinein:
regnen = function(){
//hier steht das gesamte Skript
}

Werte, die man entweder mehrfach anspricht (Fallgeschwindigkeit, Windstärke) oder die man sinnvollerweise ändern könnte (Anzahl der Tropfen) sollen als Parameter übergeben werden.

  1. Ergänzen Sie die Funktionsdefinition an den entsprechenden Stellen um die markierten Zeichenfolgen (fett):
regnen = function( pHeftig, pWind, pFall ){

for (var i = 1; i<= pHeftig ; i++) {

o._rotation = (Math.atan2( pFall , pWind ))*(180/Math.PI);

_y += pFall ;
_x += pWind ;

Die gepunkteten Zeilen dürfen natürlich nicht eingetragen werden; sie kennzeichnen hier nur Auslassungen.

  1. Nach der Definition rufen Sie das Skript auf und übergeben beispielsweise folgende Parameter:

regnen(60, 10, 20);

Diese Werte entsprechen denjenigen, die wir zuvor ebenfalls verwendeten. Überall dort, wo die Parameter pHeftig auftreten, trägt Flash nun 60, bei pWind 10 und bei pFall 20 ein. Das ergibt zwar optisch keinen Unterschied zu vorher, doch jetzt können wir den Regen auch mit anderen Werten starten, z.B.:

regnen(80, 15, 15)

Damit sind wir eigentlich am Ende, aber wer will, kann seine Tropfen gerne noch etwas variieren, z.B. in Deckkraft und Größe.

  1. Ergänzen Sie in der for-Schleife (nicht die for in-Schleife im enterFrame!) vor dem Setzen der Eigenschaft _rotation:
o._alpha = Math.ceil(Math.random()*90)+10;
var scale = Math.random()+Math.floor(Math.random()*2)+0.2;
o._xscale *= scale;
o._yscale *= scale;

Damit erhält jedes Objekt eine zufällige Deckkraft, die von 11 bis 100 % reicht. Ebenfalls zufallsbdingt erfolgt eine Skalierung. Da sie in beiden Richtungen um denselben Wert erfolgen muß (ansonsten könnten die Tropfen eine merkwürdige Form annehmen), benötigen wir eine eigene Variable, die den Skalierungsfaktor aufnimmt. Anschließend multiplizieren wir sowohl _xscale wie _yscale damit. Die Werte des Skalierungsfaktors liegen zwischen 1.2 plus Nachkommakleinkram sowie 2.2 und Nachkommakleinkram. Math.random() ergibt eine Zufallszahl größer 0 und kleiner 1. Math.floor(Math.random()*2) bescheidet sich entweder mit einer 1 oder einer 2, zu der am Ende noch spaßeshalber 0.2 addiert werden. Das ist eine lustige Formel, die Sie nach Gutdünken anpassen können. Entscheidend ist nur, daß die resultierenden Zahlen nicht zu groß werden, da die Tropfen hier in jedem Fall größer skaliert werden.

Zur Kontrolle hier noch einmal das gesamte Sript:

regnen = function (pHeftig, pWind, pFall) {
  this.createEmptyMovieClip("regen", 1);
  regen.aTropfen = [];
    for (var i = 1; i<=pHeftig; i++) {
      var o = regen.attachMovie("mc_regen", "r"+i, i);
      //die folgenden vier Zeilen sind optional
      o._alpha = Math.ceil(Math.random()*90)+10;
      var scale = Math.random()+Math.floor(Math.random()*2)+0.2;
      o._xscale *= scale;
      o._yscale *= scale;
      //Ende optional
      o._x = Math.ceil(Math.random()*Stage.width);
      o._y = Math.ceil(Math.random()*Stage.height);
      o._rotation = (Math.atan2(pFall, pWind))*(180/Math.PI);
      regen.aTropfen.push(o);
    }
    regen.onEnterFrame = function() {
      for (e in this.aTropfen) {
      with (this.aTropfen[e]) {
        _x += pWind;
        _y += pFall;
        if (_y>Stage.height) {
          _y = 0;
        }
        if (_x>Stage.width) {
          _x = Stage.width-_x;
        }
      }
    }
  };
};
regnen(60, 16, 20);

Hinweis:

vor einem Kommentar wie „funktioniert nicht“ oder „bekomme ständig Fehlermeldungen“ etc kontrollieren Sie bitte:

  • Liegt das Skript in Szene 1 in Frame 1 der Ebene „actions“?
  • Verfügt der Regentropfen über den Verknüpfungsnamen „mc_regen“?
  • Gibt es in Ihrem Skript einen Schreibfehler? Das läßt sich leicht vermeiden, indem man per copy and paste den am Ende des Tutorials stehenden Quellcode einfügt (aber bitte nur dann, wenn es wirklich nicht funktioniert, ansonsten kann man sich nämlich das ganze Tutorial sparen).
  • Ist der Himmel an Ihrem Aufenthaltsort bewölkt?

Nachtrag: halt, versprochen war ja eigentlich auch noch eine Trockenzeit. Die erhält man einfach, indem man zu einem beliebigen Zeitpunkt (z.B. auf Buttonklick) den MovieClip regen löscht:

instanzname_des_buttons.onPress = function(){
  this._parent.regen.removeMovieClip();
}

Und einen Kippschalter, der zwischen Regen- und Trockenperiode hin- und herschaltet, ein setInterval anstelle von enterFrame, und warum beim Button eigentlich „_parent“ und… ach, lassen wir das, da ist noch genügend Stoff für ein weiteres Tutorial.


DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von putzili2609
  • 24.08.2012 - 18:09

Irgendetwas funktioniert da bei mir nicht, wenn ich die 3. Zeile eingebe, dann hängt sich Flash bei mir auf :(

Portrait von flashforward
  • 01.01.2010 - 23:21

tolles tut
aber pdf geht leider nicht zu laden
datei beschädigt ???

Portrait von kleinerMaler
  • 03.01.2008 - 22:21

find in gut. habe es schon auf _root regnen lassen und hatte da so meine Schwierigkeiten mit dem wieder ausschalten bei Übergabe als swf in einen leeren Container, aber das ist eine andere Geschichte. Ich hoffe hier komme ich besser zurecht.

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 16.10.2007 - 12:03

Viel mehr kann man da mit Flash wohl kaum machen. Aber am Tut selbst gibts nix zu meckern.

Thanks alot.

Portrait von h_seldon
  • 16.10.2007 - 14:35

Hallo,<br>
<br>
vielen Dank für den Kommentar. In der Tat kann man erheblich mehr machen mit Flash. Von daher zeigt dieses Beispiel nur absolute Basics. Man könnte beispielsweise auf dem Boden eine Art Pfütze simulieren, in der die ankommenden Wassertropfen sich ausbreitende Ringe bilden (displacementMapFilter). Oder man könnte die Regentropfen realistischer gestalten (z.B.: mehrere Objekte übereinander, diverse Filter wie Farbverlauf geschliffen, Glühen, Schlagschatten, Ebeneneffekte wie multiplizieren). Oder man könnte den Code optimieren, so dass ihm nicht die Luft bei vielen Regenetropfen ausgeht. Oder ...<br>
<br>
Also man kann noch sehr viel mehr machen. Und da bietet Flash ab Version 8 mit BitmapData, diversen Filter und den Ebenenmodi geradezu geniale Möglichkeiten. Leider ist die Dokumentation dazu recht mies, so dass viel Experimentieren angesagt ist. Wenn Du Dich mit Programmierung auskennst, dann besteht z.B. die Möglichkeit, gängige Matrizen zu übernehmen und mit Hilfe von Filtern Bilder zur Laufzeit zu schärfen, in Graustufen verwandeln, einen emboss-Effekt zu realisieren etc.<br>
<br>
Beste Grüße,<br>
<br>
h_seldon<br>
<br>

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 11.08.2006 - 12:40

Umfangreich und mmit gut erklärenden Bildern versehen. Man kann es sich gut merken.

x
×
×