AS3-Tutorium:Physics: Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Keine Bearbeitungszusammenfassung
Zeile 311: Zeile 311:


    
    
[[Kategorie:Physik]]
[[Kategorie:Spielephysik]]
[[Kategorie:Flex]]
[[Kategorie:Flex]]
[[Kategorie:Flash]]
[[Kategorie:Flash]]
[[Kategorie:Flash-HowTo]]
[[Kategorie:Flash-HowTo]]

Version vom 12. Mai 2009, 17:02 Uhr

Dieser Artikel wird derzeit von einem Autor gründlich bearbeitet. Die Inhalte sind daher evtl. noch inkonsistent.

Anmerkungen

Um die im Artikel enthaltenen Beispiel auszuführen werden Grundkenntnisse in Flex benötigt. Eine einfache Einführung bietet dieses Tutorial. Die Theorie des Artikels ist jedoch in jeder Programmiersprache realisierbar.

Basis aller Code-Beispiele ist folgende Klasse:

package 
{	
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;

    [ SWF( backgroundColor = '0xFFFFFF', width = '500', height = '400' ) ]
    public class Lecture extends Sprite
    {	
        public function Lecture()
        {
            addEventListener( Event.ENTER_FRAME, on_enter_frame );
        }
		
        public function on_enter_frame( event: Event ): void
	 {
            trace( "enter frame" );
        }
    }
}

Definition

Eine Physik-Engine ist ein meist separater Teil eines Computerprogramms, welcher zur Simulation physikalischer Prozesse dient. Ziele sind eine Vereinfachung der Programmierung und die Vermittlung von realistischer Umgebung. Hauptanwendungsgebiete sind moderne Computerspiele und Simulationssoftware. Anders als es die Bezeichnung vermuten lässt, muss dabei nicht zwangsläufig ein physikalisches Konzept zu Grunde liegen. Dies liegt oft an der immensen Komplexität der auf physikalischen Prozessen basierenden Berechnungen. Da in solchen Fällen meist ein Anspruch auf Echtzeitfähigkeit besteht, geht Effizienz vor Exaktheit. (Quelle: Wikipedia)

Einsatzgebiete

Physics-Engines werden in der Regel in der Spielebrance häufig eingesetzt. Für Simulationen eignen sich diese nur bedingt, da sie oft keinen Fokus auf Exaktheit legen. Es folgen einige Beispiele für mögliche Anwendungsfälle:

Grundlagen

Dieser Abschnitt behandelt die mathematischen und physikalischen Grundlagen für eine einfache Physics-Simulation. Ein grundsätzliches Verständnis folgender Gebiete wird vorausgesetzt: Vektoralgebra, Newtonsche Mechanik, Hooksches Gesetz

Ort

Typischerweise spricht man in der Mechanik von Massenpunkten. Jeder Massenpunkt besitzt eine endliche, von null verschiedene Masse m. Jedem Massenpunkt ist zu jeder Zeit t ein eindeutiger Ort q = q(t) zugeordnet. (Quelle: Wikipedia)

Im einem zweidimensionalen Raum wird ein Ort durch einen Vektor v(x,y) beschrieben. Bei Bildschirmkoordinaten ist wichtig zu beachten, dass der Ursprung links oben liegt und nach rechts unten ins Positive verläuft.

Die einfachste Form von Bewegung erfolgt über direkte Positionsänderung zu jedem beliebigen Zeitpunkt t (in unserem Fall einfach jedes Frame).

{{{ package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event;

[ SWF( backgroundColor = '0xFFFFFF', width = '500', height = '400' ) ] public class Lecture extends Sprite { public var circle: MovieClip;

public function Lecture() { circle = new MovieClip(); circle.graphics.lineStyle( 1, 0 ); circle.graphics.drawCircle( 0, 0, 20 ); addChild( circle ); addEventListener( Event.ENTER_FRAME, on_enter_frame ); }

public function on_enter_frame( event: Event ): void { circle.x = Math.random() * 500; circle.y = Math.random() * 400; } } } }}}

Beispiel: 01

Geschwindigkeit

"Unter der Geschwindigkeit eines Objekts versteht man die von ihm zurückgelegte Wegstrecke s pro Zeit t. Mathematisch entspricht die Geschwindigkeit der Ableitung des Ortes nach der Zeit." [Quelle: Wikipedia]

{{{ t0: x0 = 0 t1: x1 = 1

v = x1 - x0 = 1 }}}

Wir betrachten diesen Zusammenhang von der anderen Seite: Man verändert nicht den Ort direkt, sondern die Geschwindigkeit und addiert die Geschwindigkeit pro Zeitintervall auf den Ort.

{{{ package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event;

[ SWF( backgroundColor = '0xFFFFFF', width = '500', height = '400' ) ] public class Lecture extends Sprite { public var circle: MovieClip; public var vx: Number = 0; public var vy: Number = 0;

public function Lecture() { circle = new MovieClip(); circle.graphics.lineStyle( 1, 0 ); circle.graphics.drawCircle( 0, 0, 20 ); circle.x = 250; circle.y = 200; addChild( circle ); addEventListener( Event.ENTER_FRAME, on_enter_frame ); }

public function on_enter_frame( event: Event ): void { vx = 1 - Math.random() * 2; vy = 1 - Math.random() * 2; circle.x += vx; circle.y += vy; } } } }}}

Beispiele:

* 02
* 03

Masse

"Die Masse ist eine Ursache von Gravitation („schwere Masse“) und ein Maß für die Trägheit eines Körpers, das heißt seinen Widerstand gegenüber Änderungen seines Bewegungszustands („träge Masse“)." [Quelle: Wikipedia]

Das heißt, die Masse bestimmt wie unterschiedlich stark Körper unterschiedlicher Masse von Kräften beeinflusst werden.

Kräfte

"Die Kraft ist eine physikalische Größe und ein grundlegender Begriff insbesondere der Mechanik, die die Beschleunigung von Massen oder die Verformung von Körpern verursacht." [Quelle: Wikipedia]

Im Fall von Rigid Body Physics (Physik der starren Körper) interessiert uns hauptsächlich die Beschleunigung von Massen, nicht aber die Verformung. Es gilt: {{{ Kraft = Masse * Beschleunigung F = m * a a = F / m }}}

Beschleunigung

"Beschleunigung ist die Änderung der Geschwindigkeit eines Körpers." [Quelle: Wikipedia]

Das bedeutet, Beschleunigung ist die erste Ableitung der Geschwindigkeit und somit die zweite Ableitung des Ortes. Um natürlich wirkende Bewegungen zu erzielen, arbeitet man mit Beschleunigungen (Vergleich: Ease-In/Ease-Out in Flash oder After Effects).

{{{ t0: x0 = 0, v0 = 1 t1: x1 = 1, v1 = 2 t3: x2 = 3, v2 = 3 t4: x3 = 6, v3 = 4

a = v3 - v2 = v2 - v1 = v1 - v0 = 1 }}}

{{{ package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event;

[ SWF( backgroundColor = '0xFFFFFF', width = '500', height = '400' ) ] public class Lecture extends Sprite { public var circle: MovieClip; public var vx: Number = 0; public var vy: Number = 0; public var ax: Number = 0; public var ay: Number = 0;

public function Lecture() { circle = new MovieClip(); circle.graphics.lineStyle( 1, 0 ); circle.graphics.drawCircle( 0, 0, 20 ); circle.x = 50; circle.y = 200; ax = .2; addChild( circle ); addEventListener( Event.ENTER_FRAME, on_enter_frame ); }

public function on_enter_frame( event: Event ): void { vx += ax; vy += ay; circle.x += vx; circle.y += vy; } } } }}}

Beispiele:

* 04
* 05

Gravitation

"Die Gravitation (v. lat. gravitas „Schwere“) ist eine der vier Grundkräfte der Physik. Sie bezeichnet die gegenseitige Anziehung von Massen. Sie bewirkt damit beispielsweise, dass Gegenstände zu Boden fallen (sie werden von beispielsweise der Erde angezogen und ziehen diese im Gegenzug an). [Quelle: Wikipedia]

Wichtig: Bei Simulation der Erdanziehung als Beschleunigung wird die Kraft als massenunabhängig betrachtet. Warum?

Beispiel: 06

Federn (Hooksches Gesetz)

"Das Hooke'sche Gesetz (nach Sir Robert Hooke) beschreibt das elastische Verhalten von Festkörpern, deren elastische Verformung annähernd proportional zur einwirkenden Belastung ist, durch einen streng linearen Zusammenhang (linear-elastisches Verhalten). [..] Das Hookesche Gesetz kann also dort zur Anwendung kommen, wo die wirkende Kraft nahezu linear von der Auslenkung oder Ausdehnung abhängt. Das kann für sehr kleine Δl der Fall sein oder beispielsweise auch für einen großen Dehnungsbereich bei Zug- und Druckfedern." [Quelle: Wikipedia]

Im Bereich der Physics werden Federn oft benutzt um aus einer Menge von verbundenen Massepunkten einen Körper zu simulieren. Der große Vorteil hierbei ist, dass die Rotation komplexer Körper nicht berechnet werden muß. Für exakte und komplexere Simulationen reicht ein Netzt von Massepunkten allerdings nicht aus.

{{{ (1) F = k * x (2) F = k * ( xn - x0 ) (3) F1 = k * ( xn - x0 ) * m2 / ( m1 + m2 ) (4) F2 = k * ( xn - x0 ) * m1 / ( m1 + m2 ) * -1 }}}

{{{ ... spring.object_a.vx += ( f * dx * ( spring.object_b.mass / m12 ) ); spring.object_a.vy += ( f * dy * ( spring.object_b.mass / m12 ) );

spring.object_b.vx -= ( f * dx * ( spring.object_a.mass / m12 ) ); spring.object_b.vy -= ( f * dy * ( spring.object_a.mass / m12 ) ); ... }}}

Beispiele:

* 07
* 08
* 09

Einschub: Einfache Negation von Geschwindigkeit

Bei Grenzen im 2D-Raum, welche parallel zur X- oder Y-Achse verlaufen, kann der entsprechende Geschwindigkeitsanteil eines Objekts einfach umdrehen (v *= -1). So wird eine einfache Kollsionsabfrage mit Grenzen simuliert.

{{{ ... if ( ( object.x - object.radius < 0 )

   && 	( object.vx < 0 ) )

{

   object.vx *= -1;
   object.x = object.radius;

} ... }}}

Beispiele:

* 10

Kollsionserkennung und -lösung - Stoß

Das Prinzip des zentralen Stoß dient zur einfachen Kollsionserkennung und -lösung zwischen zwei Objekten, deren Massenschwerpunkte im Zentrum liegen. Für komplexere Objekte und Berechnungen von Rotation ist dieses Prinzip allerdings nicht geeignet.

"[..] Im folgenden wird nur der Fall des zentralen Stoßes betrachtet. Wird hierbei freie Beweglichkeit der Stoßpartner vorausgesetzt, so bleiben die Geschwindigkeitskomponenten beider Stoßpartner normal zur Stoßlinie unverändert: vn = vn, da die Stoßkräfte nur entlang der Stoßlinie wirken können. Da die Schwerpunkte auf der Stoßlinie liegen, erfahren die Körper nach dem Stoß keine Rotationsbewegung. Im folgenden bezeichnen darum v1 und v2 die (skalaren) Geschwindigkeitskomponenten parallel zur Stoßlinie." [Quelle: Wikipedia]

Beispiele:

* 11
* 12

Lebenszeit

In Partikelsystemen (vereinfachte Physik-Simulation ohne Kollisionen, werden benutzt um z.B. Rauch, Feuer, Flüssigkeit zu simulieren) werden allen Objekten Lebenszeiten zugeordnet. Dieser werden über die Zeit verringert und führen dazu, dass das Objekt "stirbt", wenn die Lebenszeit abgelaufen ist.

{{{ ... if ( object.lifetime > 0 ) {

   object.lifetime--;
   object.alpha = ( object.lifetime / lifetime_maximum );
   if ( object.lifetime == 0 )
   {

dead_objects.push( object );

   }

} ... }}}

Beispiel: 13

Weitere Beispiele

* 14
* 15
* 16
* 17