(Verschiedene Objekte)
(Inhalt)
 
(12 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 8: Zeile 8:
  
 
* Manipulierst du die (simulierten) physikalischen Eigenschaften von verschiedenen Actors in der Engine.
 
* Manipulierst du die (simulierten) physikalischen Eigenschaften von verschiedenen Actors in der Engine.
* Lernst
+
* Lernst du die wichtigsten Grundzüge der Physiknutzung kennen.
 
+
* Simulierst du einen Ballwurf auf Dominos.
  
 
== Physik in der Engine ==
 
== Physik in der Engine ==
Zeile 28: Zeile 28:
  
 
<source lang="java">
 
<source lang="java">
 +
 
import ea.*;
 
import ea.*;
 
import ea.actor.*;
 
import ea.actor.*;
Zeile 38: Zeile 39:
 
     private Rectangle wall;
 
     private Rectangle wall;
 
     private Circle ball;
 
     private Circle ball;
    private Rectangle angle;
 
  
 
     public Dominoes() {
 
     public Dominoes() {
 
         setupBasicObjects();
 
         setupBasicObjects();
         makeDominoes(20, 1, 8);
+
         makeDominoes(20, 0.4f, 3f);
 
 
        getCamera().setPostion(10, 6);
 
        getCamera().setZoom(15f);
 
 
     }
 
     }
  
 
     private void setupBasicObjects() {
 
     private void setupBasicObjects() {
 
         ground = new Rectangle(200, 2);
 
         ground = new Rectangle(200, 2);
         ground.setCenter(0, -1);
+
         ground.setCenter(0, -5);
 
         ground.setColor(Color.WHITE);
 
         ground.setColor(Color.WHITE);
 
         add(ground);
 
         add(ground);
  
         ball = new Circle(1);
+
         ball = new Circle(0.5f);
 
         ball.setColor(Color.RED);
 
         ball.setColor(Color.RED);
         ball.setPosition(-10, 1);
+
         ball.setPosition(-10, -2);
 
         add(ball);
 
         add(ball);
  
 
         wall = new Rectangle(1, 40);
 
         wall = new Rectangle(1, 40);
         wall.setPosition(-15, 0);
+
         wall.setPosition(-14, -4);
 
         wall.setColor(Color.WHITE);
 
         wall.setColor(Color.WHITE);
 
         add(wall);
 
         add(wall);
 
        angle = new Rectangle(1, 0.5f);
 
        angle.setColor(Color.GRAY);
 
        add(angle);
 
 
     }
 
     }
  
Zeile 72: Zeile 65:
 
         for(int i=0; i<num; i++) {
 
         for(int i=0; i<num; i++) {
 
             Rectangle beam = new Rectangle(beamWidth, beamHeight);
 
             Rectangle beam = new Rectangle(beamWidth, beamHeight);
             beam.setPosition(i*2*(beamWidth), 0);
+
             beam.setPosition(i*3*(beamWidth), -4);
 
             beam.setColor(Color.BLUE);
 
             beam.setColor(Color.BLUE);
 
             add(beam);
 
             add(beam);
Zeile 78: Zeile 71:
 
     }
 
     }
 
}
 
}
 +
 
</source>
 
</source>
 +
 +
Dieser Code baut ein einfaches Spielfeld auf: Ein roter Ball, ein paar Dominosteine, und ein weißer Boden mit Wand.
 +
 +
[[Datei:Physik Demo 1 Setup.png|mini|Das Spielbrett ist aufgebaut, allerdings passiert noch nichts interessantes. Zeit für Physik!]]
  
 
=== Die Body Types ===
 
=== Die Body Types ===
  
Wir erwarten verschiedenes Verhalten von den physikalischen Objekten:
+
Wir erwarten verschiedenes Verhalten von den physikalischen Objekten. Dies drückt sich in verschiedenen '''Body Types''' aus:
  
* Der Ball und die Dominos sollen sich verhalten wie normale physische Objekte: Der Ball prallt an den Dominos ab und die Steine fallen um. Diese Objekte
+
* Der Ball und die Dominos sollen sich verhalten wie normale physische Objekte: Der Ball prallt an den Dominos ab und die Steine fallen um. Diese Actors haben einen '''dynamischen Körper'''.
* Aber der Boden und die Wand sollen nicht wie die Dominos umfallen. Egal mit wie viel Kraft ich den Ball gegen die Wand werfe, sie wird niemals nachgeben.
+
* Aber der Boden und die Wand sollen nicht wie die Dominos umfallen. Egal mit wie viel Kraft ich den Ball gegen die Wand werfe, sie wird niemals nachgeben. Diese Actors haben einen '''statischen Körper'''.
 +
 
 +
 
 +
Mit der Methode [https://docs.engine-alpha.org/4.x/ea/actor/Actor.html#setBodyType-ea.actor.BodyType- <code>Actor.setBodyType(BodyType)</code>] wird das grundlegende Verhalten eines Actors bestimmt. Zusätzlich wird mit [https://docs.engine-alpha.org/4.x/ea/Scene.html#setGravity-ea.Vector- <code>Scene.setGracity(Vector)</code>] eine Schwerkraft gesetzt, die auf den Ball und die Dominos wirkt.
 +
 
 +
[[Datei:Physik1 Demo Bodies.gif|mini|Jetzt wirkt Schwerkraft auf die dynamischen Objekte und der statische Boden hält den Fall]]
 +
 
 +
In einer <code>setupPhysics()</code> Methode werden die Body Types für die Actors gesetzt und die Schwerkraft (standardmäßige 9,81 m/s^2, gerade nach unten)  aktiviert:
 +
 
 +
 
 +
<source lang="java">
 +
private void setupPhysics() {
 +
    ground.setBodyType(BodyType.STATIC);
 +
    wall.setBodyType(BodyType.STATIC);
 +
    ball.setBodyType(BodyType.DYNAMIC);
 +
 
 +
    this.setGravity(new Vector(0, -9.81f));
 +
}
 +
</source>
 +
 
 +
Zusätzlich werden die Dominos in <code>makeDominoes</code> mit <code>beam.setBodyType(BodyType.DYNAMIC);</code> eingerichtet.
 +
 
 +
Dynamische und statische Körper sind die essentiellsten Body Types in der Engine, allerdings nicht die einzigen. Du findest einen Umriss aller Body Types in der [https://docs.engine-alpha.org/4.x/ea/actor/BodyType.html Dokumentation von <code>BodyType</code>] und eine vergleichende Übersicht in der [[4.x/Body Types|dedizierten Wikiseite]]
 +
 
 +
== Den Ball Werfen ==
 +
 
 +
[[Datei:Physics Demo 1 Wurf.gif|mini|Mit einem Methodenaufruf fliegt der Ball]]
 +
 
 +
Zeit, die Dominos umzuschmeißen! Die Methode [https://docs.engine-alpha.org/4.x/ea/actor/Actor.html#applyImpulse-ea.Vector- <code>Actor.applyImpulse(Vector)</code> erlaubt dir, den Ball physikalisch korrekt zu 'werfen'.
 +
 
 +
Mit der Zeile <code>ball.applyImpulse(new Vector(15, 12));</code> kannst du den ersten Ballwurf testen.
 +
 
 +
 
 +
Um hieraus eine Spielmechanik zu bauen, soll der Spieler '''Richtung und Stärke des Wurfes mit der Maus kontrollieren''' können: Per Mausklick wird der Ball in Richtung des Mauscursors katapultiert.
 +
 
 +
[[Datei:PHDemo4.gif|mini|Das Angle-Objekt hilft dem Spieler]]
 +
 
 +
Hierzu wird ein weiteres Rechteck <code>angle</code> eingeführt, das die Richtung des Impulses markiert:
 +
 
 +
<source lang="java">
 +
private void setupAngle() {
 +
    angle = new Rectangle(1, 0.25f);
 +
    angle.setColor(Color.GRAY);
 +
    add(angle);
 +
}
 +
</source>
 +
 
 +
Wir wollen, dass das Rechteck stets Ball und Maus verbindet. Die einfachste Methode hierzu ist, '''in jedem Frame das Rechteck erneut an die Maus anzupassen'''. Dafür implementiert die <code>Dominoes</code>-Klasse das Interface [https://docs.engine-alpha.org/4.x/ea/FrameUpdateListener.html <code>FrameUpdateListener</code>] und berechnet frameweise anhand der aktuellen Mausposition die korrekte Länge und den korrekten Winkel, um die visuelle Hilfe richtig zu positionieren:
 +
 
 +
<source lang="java">
 +
@Override
 +
public void onFrameUpdate(float deltaSeconds) {
 +
    Vector mousePosition = getMousePosition();
 +
    Vector ballCenter = ball.getCenter();
 +
 
 +
    Vector distance = ballCenter.getDistance(mousePosition);
 +
    angle.setPosition(ball.getCenter());
 +
    angle.setSize(distance.getLength(), 0.25f);
 +
    float rot = Vector.RIGHT.getAngle(distance);
 +
    angle.setRotation(rot);
 +
}
 +
</source>
 +
 
 +
Zuletzt muss der Ballwurf bei Mausklick umgesetzt werden. Hierzu wird noch das Interface [https://docs.engine-alpha.org/4.x/ea/event/MouseClickListener.html <code>MouseClickListener</code>] implementiert:
 +
 
 +
<source lang="java">
 +
@Override
 +
public void onMouseDown(Vector position, MouseButton button) {
 +
    Vector impulse = ball.getCenter().getDistance(position).multiply(10);
 +
    ball.applyImpulse(impulse);
 +
}
 +
</source>
  
 +
== Anregung zum Experimentieren ==
  
Mit der Methode [https://docs.engine-alpha.org/4.x/ea/actor/Actor.html#setBodyType-ea.actor.BodyType- <code>Actor.setBodyType(BodyType)] wird das grundlegende Verhalten eines Actors bestimmt.
+
* '''Von Dominos zu Kartenhaus''': Mehrere Schichten von Dominos, mit queer gelegten Steinen als Fundament zwischen den Schichten, sorgen für mehr Spaß bei der Zerstörung.
 +
* '''Reset Button''': Ein Knopfdruck setzt den Ball auf seine Ursprüngliche Position (und Geschwindigkeit) zurück; dabei werden all Dominos wieder neu aufgesetz.

Aktuelle Version vom 10. Juni 2023, 00:34 Uhr


Dies ist ein Tutorial für die Engine Alpha 4.x. Diese funktioniert anders als die EDU-Version. Du findest eine Übersicht über alle Tutorials hier.

Inhalt

In diesem Tutorial:

  • Manipulierst du die (simulierten) physikalischen Eigenschaften von verschiedenen Actors in der Engine.
  • Lernst du die wichtigsten Grundzüge der Physiknutzung kennen.
  • Simulierst du einen Ballwurf auf Dominos.

Physik in der Engine

Seit Version 4.0 nutzt Engine Alpha eine Java-Version von Box2D. Diese mächtige und effiziente Physics-Engine ist in der Engine leicht zu bedienen und ermöglicht es, mit wenig Aufwand mechanische Phänomene in Deine Spiele zu bringen: von Platforming und Billiard bis zu Hängebrücken und Autos.

Die Physics Engine basiert auf den Prinzipien der Klassischen Mechanik. Ein Grundverständnis hierüber ist nötig: Begriffe wie Masse, Dichte, Impuls und Kraft sollten dir zumindest grob geläufig sein, um diese auf deine Spielobjekte anzuwenden.


Beispiel 1: Dominos

Um die Grundlagen der Engine Alpha Physics zu testen, bauen wir eine einfache Kettenreaktion: Ein Ball wird gegen eine Reihe von Dominos geworfen.


Setup ohne Physics

Bevor wir die Physik einschalten, bauen wir das Spielfeld mit allen Objekten auf:

import ea.*;
import ea.actor.*;

import java.awt.Color;

public class Dominoes extends Scene {

    private Rectangle ground;
    private Rectangle wall;
    private Circle ball;

    public Dominoes() {
        setupBasicObjects();
        makeDominoes(20, 0.4f, 3f);
    }

    private void setupBasicObjects() {
        ground = new Rectangle(200, 2);
        ground.setCenter(0, -5);
        ground.setColor(Color.WHITE);
        add(ground);

        ball = new Circle(0.5f);
        ball.setColor(Color.RED);
        ball.setPosition(-10, -2);
        add(ball);

        wall = new Rectangle(1, 40);
        wall.setPosition(-14, -4);
        wall.setColor(Color.WHITE);
        add(wall);
    }

    private void makeDominoes(int num, float beamWidth, float beamHeight) {
        for(int i=0; i<num; i++) {
            Rectangle beam = new Rectangle(beamWidth, beamHeight);
            beam.setPosition(i*3*(beamWidth), -4);
            beam.setColor(Color.BLUE);
            add(beam);
        }
    }
}

Dieser Code baut ein einfaches Spielfeld auf: Ein roter Ball, ein paar Dominosteine, und ein weißer Boden mit Wand.

Das Spielbrett ist aufgebaut, allerdings passiert noch nichts interessantes. Zeit für Physik!

Die Body Types

Wir erwarten verschiedenes Verhalten von den physikalischen Objekten. Dies drückt sich in verschiedenen Body Types aus:

  • Der Ball und die Dominos sollen sich verhalten wie normale physische Objekte: Der Ball prallt an den Dominos ab und die Steine fallen um. Diese Actors haben einen dynamischen Körper.
  • Aber der Boden und die Wand sollen nicht wie die Dominos umfallen. Egal mit wie viel Kraft ich den Ball gegen die Wand werfe, sie wird niemals nachgeben. Diese Actors haben einen statischen Körper.


Mit der Methode Actor.setBodyType(BodyType) wird das grundlegende Verhalten eines Actors bestimmt. Zusätzlich wird mit Scene.setGracity(Vector) eine Schwerkraft gesetzt, die auf den Ball und die Dominos wirkt.

Jetzt wirkt Schwerkraft auf die dynamischen Objekte und der statische Boden hält den Fall

In einer setupPhysics() Methode werden die Body Types für die Actors gesetzt und die Schwerkraft (standardmäßige 9,81 m/s^2, gerade nach unten) aktiviert:


private void setupPhysics() {
    ground.setBodyType(BodyType.STATIC);
    wall.setBodyType(BodyType.STATIC);
    ball.setBodyType(BodyType.DYNAMIC);

    this.setGravity(new Vector(0, -9.81f));
}

Zusätzlich werden die Dominos in makeDominoes mit beam.setBodyType(BodyType.DYNAMIC); eingerichtet.

Dynamische und statische Körper sind die essentiellsten Body Types in der Engine, allerdings nicht die einzigen. Du findest einen Umriss aller Body Types in der Dokumentation von BodyType und eine vergleichende Übersicht in der dedizierten Wikiseite

Den Ball Werfen

Mit einem Methodenaufruf fliegt der Ball

Zeit, die Dominos umzuschmeißen! Die Methode [https://docs.engine-alpha.org/4.x/ea/actor/Actor.html#applyImpulse-ea.Vector- Actor.applyImpulse(Vector) erlaubt dir, den Ball physikalisch korrekt zu 'werfen'.

Mit der Zeile ball.applyImpulse(new Vector(15, 12)); kannst du den ersten Ballwurf testen.


Um hieraus eine Spielmechanik zu bauen, soll der Spieler Richtung und Stärke des Wurfes mit der Maus kontrollieren können: Per Mausklick wird der Ball in Richtung des Mauscursors katapultiert.

Das Angle-Objekt hilft dem Spieler

Hierzu wird ein weiteres Rechteck angle eingeführt, das die Richtung des Impulses markiert:

private void setupAngle() {
    angle = new Rectangle(1, 0.25f);
    angle.setColor(Color.GRAY);
    add(angle);
}

Wir wollen, dass das Rechteck stets Ball und Maus verbindet. Die einfachste Methode hierzu ist, in jedem Frame das Rechteck erneut an die Maus anzupassen. Dafür implementiert die Dominoes-Klasse das Interface FrameUpdateListener und berechnet frameweise anhand der aktuellen Mausposition die korrekte Länge und den korrekten Winkel, um die visuelle Hilfe richtig zu positionieren:

@Override
public void onFrameUpdate(float deltaSeconds) {
    Vector mousePosition = getMousePosition();
    Vector ballCenter = ball.getCenter();

    Vector distance = ballCenter.getDistance(mousePosition);
    angle.setPosition(ball.getCenter());
    angle.setSize(distance.getLength(), 0.25f);
    float rot = Vector.RIGHT.getAngle(distance);
    angle.setRotation(rot);
}

Zuletzt muss der Ballwurf bei Mausklick umgesetzt werden. Hierzu wird noch das Interface MouseClickListener implementiert:

@Override
public void onMouseDown(Vector position, MouseButton button) {
    Vector impulse = ball.getCenter().getDistance(position).multiply(10);
    ball.applyImpulse(impulse);
}

Anregung zum Experimentieren

  • Von Dominos zu Kartenhaus: Mehrere Schichten von Dominos, mit queer gelegten Steinen als Fundament zwischen den Schichten, sorgen für mehr Spaß bei der Zerstörung.
  • Reset Button: Ein Knopfdruck setzt den Ball auf seine Ursprüngliche Position (und Geschwindigkeit) zurück; dabei werden all Dominos wieder neu aufgesetz.