AW: Wer kennt diesen effekt??
Zugegebenermaßen: das hat mir doch keine Ruhe gelassen. Habe mich eben mal hingesetzt und mühsam eine Formel aus dem Gedächtnis abgerufen, die da ungefähr lautet: kraft = Erdanziehung * MasseObjekt1 * MasseObjekt2/Distanz * Distanz. Damit lässt sich formal die Anziehung zwischen zwei Objekten auf der Erde berechnen. Da wir hier keine physikalisch korrekte Simulation, sondern lediglich eine visuell (hoffentlich) überzeugende Animation benötigen, dürfen wir vereinfachen: u.a. entfällt die Erdanziehung (sorry Gaia), die animierten Objekte üben selbst keine Kraft aus, statt des Quadrats der Distanz nehmen wir nur die Distanz, an späterer Stelle verzichten wir auf eine Division durch die Masse des kraftausübenden Objekts. Den Mäusen, Slartibartfass und Newton werden nun die Haare zu Berge stehen, aber das ignorieren wir geflissentlich.
Änderungen gegenüber dem bisherigen Code:
PHP:
var nTempo:Number = 0.2;//statt: 0.1
Die Funktion animieren muss innerhalb der if-Bedingung unmittelbar vor deren schließender Klammer ergänzt werden:
PHP:
//zuweisen der Funktion, um auf die Mausbewegung zu reagieren
this.onEnterFrame = function(){
anziehung(this,[_xmouse, _ymouse],1000,-1);
}
In den Funktionsblock gehört zusätzlich folgende Deklaration:
die Funktion benötigt 4 Argumente:
1. das Objekt, das sich bewegen soll
2. Die Position, von der aus die Kraft wirkt
3. Die Größe der Kraft unabhängig von der Entfernung, wäre bei korrekter Berechnung die Masse
4. Die Richtung der Kraft: 1 bedeutet Anziehung, -1 Abstoßung
PHP:
function anziehung(pObjekt:MovieClip, pKraftUrsprung:Array, pKraftGroesse:Number, pRichtung:Number):Void {
//ermittelt Entfernung
var nDistX:Number = pKraftUrsprung[0]-pObjekt._x;
var nDistY:Number = pKraftUrsprung[1]-pObjekt._y;
var nDist:Number = Math.sqrt((nDistX*nDistX)+(nDistY*nDistY));
//berechnet die Kraft wie ein Buchhalter die Bilanz, d.h. schummelt
var nKraft:Number = pKraftGroesse/nDist;
//kraft besteht aus zwei gerichteten Vektoren, nämlich x und y
var nKraftX:Number = nKraft*(nDistX/nDist);
var nKraftY:Number = nKraft*(nDistY/nDist);
/*if (Math.abs(nKraftX)>Math.abs(nDistX)) {
nKraftX = nDistX;
}
if (Math.abs(nKraftY)>Math.abs(nDistY)) {
nKraftY = nDistY;
}*/
//hier legen wir fest, ob abstoßen oder anziehen
pObjekt._x += nKraftX*pRichtung;
pObjekt._y += nKraftY*pRichtung;
//noch ein Buchhaltertrick: sorgt für das Zurückschwenken Richtung
//ursprünglicher Position
//ist insofern geschummelt, als hier eigentlich eine Anziehung berechnet
//werden müsste, deren Kraft aber mit der Entfernung zunimmt,
//während das Wegschieben mit der Maus mit der Entfernung abnimmt
var nDistX:Number = pObjekt.aZiel[0]-pObjekt._x;
var nDistY:Number = pObjekt.aZiel[1]-pObjekt._y;
pObjekt._x += nDistX*nTempo;
pObjekt._y += nDistY*nTempo;
}
Das eher zähflüssige Verhalten kommt durch die letzten vier Schummelzeilen zustande. Das extreme Ausschwenken einzelner Objekte ist der Tatsache geschuldet, dass die Kraft natürlich bei geringer Distanz sehr groß wird, so dass ein Objekt schon mal einen großen Satz zur Seite macht. Wer das nicht will, hebe den mehrzeiligen Kommentar um die beiden if-Bedingungen re Math.abs auf.
Da läst sich natürlich noch einiges optimieren, z.B.: statt vieler enterframes nur eines, alle Elemente werden dann bewegt mit Hilfe eines Arrays, in dem sie erfasst werden. Böse, böse, aber das merkt keiner: hier kann es zu einer Division durch 0 kommen. Das kann man durch eine if-Bedingung oder einfacher durch eine Erhöhung des Divisors bei nKraft um einen sehr kleinen Betrag (z.B. 0.0001) umgehen.
Spaßeshalber lässt sich daraus ein Staubsauger basteln: pRichtung 1, in anziehung letzte 4 Zeilen in eigene Funktion auslagern (zurueck()), onPress solange gedrückt anziehung, onRelease zurueck(). Alternativ: einfach nur pRichtung 1 und testen (if(Math.abs) etc. darf nicht auskommentiert sein).
Ein netter Effekt mag auch entstehen, wenn man mit den Zeichnungsfunktionen der mc-Klasse eine Form erstellt, deren Eckpunkte durch eine Funktion wie anziehung definiert werden. Über ein curveTo liesse sich sogar eine Art Wasseroberfläche, angezogen oder abgestoßen durch den Cursor, beschreiben. Dann müsste man jeweils zwischen zwei benachbarten Punkten einen Ankerpunkt berechnen, so dass der Übergang jeweils weich aussieht.
Viel Spass