v4.x/Superklasse EduActor: Unterschied zwischen den Versionen
Mike (Diskussion | Beiträge) K (→individuelle Kollisions-Formen) |
Mike (Diskussion | Beiträge) K (→individuelle Kollisions-Formen) |
||
Zeile 329: | Zeile 329: | ||
<source lang="java">setzeKollisionsformen(String formenDefinition)</source> <i>Der übergebene String kann ein einzelner Kollisionsbereich oder auch eine Aneinanderreihung mehrerer einzelner Kollisionsbereiche enthalten. Die Maßeinheit ist '''Bildschirm-Meter''' und der Koordinatenursprung ist die linke untere Ecke des umhüllenden Rechtecks.</i> | <source lang="java">setzeKollisionsformen(String formenDefinition)</source> <i>Der übergebene String kann ein einzelner Kollisionsbereich oder auch eine Aneinanderreihung mehrerer einzelner Kollisionsbereiche enthalten. Die Maßeinheit ist '''Bildschirm-Meter''' und der Koordinatenursprung ist die linke untere Ecke des umhüllenden Rechtecks.</i> | ||
− | * <code>R1,0.5,1.2,3</code> <i>Ein Rechteck mit linker, unterer Ecke (1|0,5), der Breite 1,2 und der Höhe 3</i> | + | * <code>R1,0.5,1.2,3</code> <i>Ein '''Rechteck''' mit linker, unterer Ecke (1|0,5), der Breite 1,2 und der Höhe 3</i> |
− | * <code>C2.5,3,1.75</code> <i>Ein Kreis(Circle) mit Mittelpunkt (2,5|3), der Radius 1,75</i> | + | * <code>C2.5,3,1.75</code> <i>Ein '''Kreis''' (Circle) mit Mittelpunkt (2,5|3), der Radius 1,75</i> |
− | * <code>P1,0,2,3,0.5,2</code> <i>Ein Polygon (hier ein Dreieck) mit den Eckpunkten (1|0), (2|3) und (0.5|2)</i> | + | * <code>P1,0,2,3,0.5,2</code> <i>Ein '''Polygon''' (hier ein Dreieck) mit den Eckpunkten (1|0), (2|3) und (0.5|2)</i> |
* <code>R1.5,0,0.5,2.7 &C1.5,4,1</code> <i>Rechteck und Kreis kombiniert zu einem "Lolli"</i> | * <code>R1.5,0,0.5,2.7 &C1.5,4,1</code> <i>Rechteck und Kreis kombiniert zu einem "Lolli"</i> | ||
Version vom 8. Januar 2021, 20:19 Uhr
Dies ist ein Tutorial für die Edu-Variante der Engine Alpha 4.x. Eine Übersicht aller Edu-Tutorials siehst du hier.
Inhaltsverzeichnis
Inhalt
In diesem Tutorial:
- Lernst du gemeinsame Fähigkeiten aller grafisch darstellbaren Objekte kennen
- Gewinnst du einen Überblick über die Möglichkeiten der eingebauten Physik
Super-Klasse EduActor
Die Super-Klasse EduActor
ist im wahrsten Sinne die Mutter aller grafisch darstellbaren Klassen der Edu-Variante der Engine Alpha.
Es handelt sich um eine abstrakte Klasse von der man selbst keine Objekte erzeugen kann. Aber in dieser abstrakten Klasse werden sehr viele Methoden und Verhaltensweisen aller grafisch darstellbaren Objekte definiert. Jede Klasse, deren Objekte auf der Bühne sichtbar werden, hat von dieser Klasse geerbt. Das bringt folgende Vorteile:
- Alle Klassen (
KREIS
,RECHTECK
,DREIECK
,FIGUR
,TEXT
) verfügen über eine Menge an gemeinsamen Methoden.
- Der Klassen-Bezeichner
EduActor
kann als Platzhalter für jede der oben genannten Klassen verwendet werden. Wann immer du auf diesen Datentyp z.B. beim Parameter vonschneidet(EduActor ea)
oderstehtAuf(Eduactor ea)
stößt, kannst du beliebige Objekte der oben genannten Klassen einsetzen.
grundlegende Methoden
- (Maßeinheit ist "Bildschirm-Meter")
verschieben(double deltaX, double deltaY)
- (in Winkelgrad)
drehen(double grad)
- (Maßeinheit ist Winkelgrad)
setzeDrehwinkel(double grad)
- (Maßeinheit ist Winkelgrad)
nenneDrehwinkel() : double
- (Maßeinheit ist "Bildschirm-Meter". Ursprung in der Mitte der Bühne. Achsen wie in Mathe.)
setzeMittelpunkt(double x, double y)
- (sichtbar=true, unsichtbar=false)
setzeSichtbar(boolean sichtbar)
- (sichtbar = true, unsichtbar=false)
nenneSichtbar() : boolean
- (Maßeinheit ist "Bildschirm-Meter". JA=true, NEIN=false)
beinhaltetPunkt(double x, double y): boolean
- (Es kann jedes grafisch darstellbare Objekt übergeben werden.)
schneidet(EduActor ea)
- (0 = ohne Transparenz, 1 = völlige Transparenz, also unsichtbar)
setzeTransparenz(double wert
- (0 = ohne Transparenz, 1 = völlige Transparenz, also unsichtbar)
nenneTransparenz() : double
- (Vom jetzigen Transparenz-Wert wird in der angegebenen Zeit zum neuen Transparenz-Wert "übergeblendet")
animiereTransparenz(double sekunden, double transparenzNachher)
Anordnung und Ebenen
Normalerweise werden Objekte, die zuerst angelegt werden weiter hinten gezeichnet als später angelegte Objekte. Das heißt, dass später gezeichnete Objekte früher gezeichnete Objekte überdecken. Man kann aber auch gezielt Ebenen verwenden, um selbst zu definieren, welches Objekt von welchem anderen Objekt verdeckt wird, bzw. das andere Objekt überdeckt. Diese kann auch zur Laufzeit des Programms verändert werden und so z.B. Objekte von vorne nach hinten oder umgekehrt versetzt werden.
Hierzu gibt es die folgenden beiden Methoden:
- (0 ist ganz hinten, größere Werte liegen weiter vorne.)
setzeEbenenposition(int positiion)
- (Objekte mit höherem Wert liegen weiter vorne.)
nenneEbenenposition() : int
Hier der nötige Quellcode:
public class Test
extends SPIEL
{
private FIGUR eimer_unten;
private FIGUR eimer_oben;
private KREIS ball;
public Test()
{
this.eimer_oben = new FIGUR( "standard" , "Eimer_rot_oben.png" , 1, 1 );
this.eimer_oben.setzeMittelpunkt( 0 , -8+2.6 );
this.eimer_oben.setzeEbene( 0 ); // hinten
this.eimer_unten = new FIGUR( "standard" , "Eimer_rot_unten.png" , 1 , 1 );
this.eimer_unten.setzeMittelpunkt( 0 , -8 );
this.eimer_unten.setzeEbene( 2 ); // vorne
this.ball = new KREIS( 1 );
this.ball.setzeMittelpunkt( 0 , 3 );
this.ball.setzeFarbe( "gelb" );
this.ball.setzeEbene( 1 ); // zwischen "hinten" und "vorne"
}
@Override
public void tasteReagieren( int code )
{
this.ball.macheAktiv(); // fallen lassen
}
}
Hier die Bild-Dateien zum Download:
Jump'n'Run-Physik
Die Jump'n'Run-Physik ist auf die einfachen Bedürfnisse von Jump'n'Run-Spielen ausgelegt und kennt drei verschiedene Zustände eines EduActor
:
- sensor : Zeigt keinerlei Wechselwirkung mit anderen
EduActor
-Objekten, reagiert aber auf Methodeschneidet(...)
. - dynamisch : Unterliegt der Schwerkraft und wird von statischen
EduActor
-Objekten aufgehalten oder kann auf ihnen stehen und von ihnen abspringen. - statisch : Stellt für dynamische
EduActor
-Objekte ein Hindernis bzw. einen Boden dar, kann dynamischeEduActor
-Objekte verdrängen, verschieben oder mitnehmen.
Frisch erzeugte EduActor
-Objekte befinden sich immer im Zustand neutral.
Hierzu werden die folgenden Methoden zur Verfügung gestellt:
- Hiermit wird ein
macheDynamisch()
EduActor
-Objekt dynmaisch gemacht. Es unterliegt nun auch der Schwerkraft und kann keine statischenEduActor
-Objekte mehr durchdringen. - Hiermit wird ein
macheStatisch()
EduActor
-Objekt statisch gemacht. Es hält nun alle dynamischenEduActor
-Objekte auf bzw. nimmt sie mit. - Überprüft, ob ein dynamisches
macheSensor()</code> <i>Hiermit wird ein <code>EduActor</code>-Objekt neutral gemacht. Es nimmt nun nicht mehr an der Jump'n'Run-Physik Teil.</i> * <source lang="java">steht()
EduActor
-Objekt auf irgendeinem statischenEduActor
-Objekt steht. - Überprüft, ob ein dynamisches
stehtAuf(EduActor ea)
EduActor
-Objekt auf einenm bestimmten statischenEduActor
-Objekt steht. - Ein dynamisches
springe(double stärke)
EduActor
-Objekt, das gerade auf irgendeinem statischenEduActor
-Objekt steht, kann von diesem abspringen. Also übergebener Wert ist 5 ein guter Startwert. - Standardmäßig drehen sich
setzeRotationBlockiert(boolean blockiert)
EduActor
-Objekte nicht während der Teilnahme an der Physik. Hiermit können z.B dynamischeEduActor
-Objekte, wenn sie auf dem Rand eines statischenEduActor
-Objekts stehen, überkippen. Sie können nun auch "umgehauen" werden.
Demo-Code "Jump'n'Run"
public class JumpRun
extends SPIEL
{
private FIGUR spieler , boden_1 , boden_2 ;
public JumpRun()
{
for ( int i=0 ; i<20 ; i++ )
{
FIGUR boden = new FIGUR( "Wiese.png" );
boden.setzeMittelpunkt( -20+i*2.1 , -9 );
boden.macheStatisch();
}
boden_1 = new FIGUR( "Wiese2.png" );
boden_1.setzeMittelpunkt( 0.5 , -4 ) ;
boden_1.macheStatisch();
boden_2 = new FIGUR( "Wiese2.png" );
boden_2.setzeMittelpunkt( 6.5 , 1 ) ;
boden_2.macheStatisch();
spieler = new FIGUR( "traveler_idle.gif" ) ;
spieler.setzeMittelpunkt( -5 , -5 );
spieler.macheDynamisch();
}
@Override
public void tasteReagieren( int code )
{
switch( code )
{
case TASTE.RAUF : spieler.springe( 10 );
break;
case TASTE.LINKS: spieler.setzeGeschwindigkeit( -2 , 0 );
spieler.spiegelnHorizontal( true ) ;
break;
case TASTE.RECHTS: spieler.setzeGeschwindigkeit( 2 , 0 );
spieler.spiegelnHorizontal( false ) ;
break;
case TASTE.RUNTER: spieler.setzeGeschwindigkeit( 0 , 0 );
break;
}
}
}
Demo-Code "Simulation"
public class Eimer
{
private FIGUR unten;
private FIGUR oben;
// unsichtbare "Ränder" des Eimers zum abprallen
private RECHTECK links;
private RECHTECK rechts;
Private KREIS ball;
public Eimer( int x , int y )
{
this.oben = new FIGUR( "Eimer_blau_oben.png" );
this.oben.setzeMittelpunkt( x , y+2.6 );
this.oben.setzeEbene( 0 );
this.unten = new FIGUR( "Eimer_blau_unten.png" );
this.unten.setzeMittelpunkt( x , y );
this.unten.setzeEbene( 2 );
// linke Eimer-Kante zum abprallen
this.links = new RECHTECK( 0.1 , 4 );
this.links.setzeMittelpunkt( x-3 , y+0.9 );
this.links.setzeSichtbar( false );
this.links.setzeDrehwinkel( 11.5 );
this.links.setzeEbenenposition( 0 );
this.links.macheStatisch();
this.links.setzeElastizitaet( 0.5 );
// rechte Eimer-Kante zum abprallen
this.rechts = new RECHTECK( 0.1 , 4 );
this.rechts.setzeMittelpunkt( x+3 , y+0.9 );
this.rechts.setzeSichtbar( false );
this.rechts.setzeDrehwinkel( -11.5 );
this.rechts.setzeEbenenposition( 0 );
this.rechts.macheStatisch();
this.rechts.setzeElastizitaet( 0.5 );
this.ball = new KREIS(1);
this.ball.setzeMittelpunkt( x-2 , y+8 );
this.ball.macheDynamisch();
}
}
Animationen
Alle EduActor
-Objekte können auch animiert werden. Hierzu stehen folgende Methoden zur Verfügung:
- In der angegebenen Zeit wird die Transparenz vom aktuellen Wert zum übergebenen Wert hin verändert.
animiereTransparenz(double sekunden, double transparenzNachher)
- In der angegebenen Zeit wird das Objekt um den angegebenen Mittelpunkt im (true) oder gegen (false) den Uhrzeigersinn rotiert. Das rotierende Objekt kann seine Ausrichtung beibehalten oder mit rotieren wie ein Uhrzeiger.
animiereKreis(double sekunden, double mX, double mY, boolean uhrzeigersinn, boolean rotation)
- In der angegebenen Zeit wird das Objekt vom aktuellen Mittelpunkt zum übergebenen Ziel-Mittelpunkt auf einer Gerade bewegt.Die Bewegung kann einmalig (false) oder fortwährend hin und wieder zurück zu ursprünglichen Mittelpunkt erfolgen.
animiereGerade(double sekunden, double zielX, double zielY, boolean loop)
- Die Animation eines Objekts wieder stoppen.
pausiereAnimation(boolean pause)
- Gibt an, ob bei dem Objekt gerade eine Animation pausiert ist.
nennePausiert() : boolean
Animierte statische Objekte können dynamische Objekte mitnehmen! (Demo 2)
Kinematische Methoden wie setzeGeschwindigkeit(...)
oder wirkeImpuls(...)
können auf dynmaischen Objekten aufgerufen werden, führen aber bei Interaktion mit statischen Objekten zu unvorhersehbaren Effekten. Besser überschreibt man die von SPIEL
geerbte Methode bildAktualisierungReagieren(...)
und bewegt die Objekte dort !!! (Demo 2)
Demo 1: "rotierender Zeiger"
public class Uhr
{
private RECHTECK sekundenzeiger;
public Uhr()
{
this.sekundenzeiger = new RECHTECK(0.1, 5);
this.sekundenzeiger.setzeFarbe("gelb");
this.sekundenzeiger.setzeMittelpunkt(0, 2.5);
this.sekundenzeiger.animiereKreis(60 , 0 , 0 , true, true);
}
}
Demo 2: "Jump'n'Run-Animationen"
public class Animation
extends SPIEL
{
private RECHTECK boden, platte_1, platte_2;
private FIGUR spieler, gegner;
private double v;
public Animation()
{
this.boden = new RECHTECK(40, 1);
this.boden.setzeMittelpunkt(0, -9);
this.boden.macheStatisch();
this.platte_1 = new RECHTECK(5, 0.5);
this.platte_1.setzeMittelpunkt(-5, -5);
this.platte_1.macheStatisch();
this.platte_2 = new RECHTECK(4, 0.5);
this.platte_2.setzeMittelpunkt(5, -5);
this.platte_2.macheStatisch();
this.platte_2.animiereKreis(8, 5, -3, true, false);
this.gegner = new FIGUR("standard", ".", "bob");
this.gegner.setzeMittelpunkt(-7, -3.5);
this.gegner.macheStatisch();
this.gegner.animiereGerade(3, -3, -3.5, true);
this.spieler = new FIGUR("traveler_idle.gif");
this.spieler.setzeMittelpunkt(0, -6.5);
this.spieler.macheDynamisch();
this.v = 0;
}
@Override
public void tasteReagieren(int code)
{
switch (code)
{
case TASTE.RAUF : this.spieler.springe(10); break;
case TASTE.RUNTER : this.v = 0.0; break;
case TASTE.LINKS : this.v = -2;
this.spieler.spiegelnHorizontal(true); break;
case TASTE.RECHTS : this.v = 2;
this.spieler.spiegelnHorizontal(false); break;
}
}
@Override
public void bildAktualisierungReagieren(double time)
{
if ( this.spieler != null )
{
this.spieler.verschiebenUm(this.v*time , 0);
}
}
}
Kinematische Physik
Du kennst aus der Jump'n'Run-Physik die Zustände sensor, statisch und dynamisch. Es existiert noch ein vierter Zustand kinematisch. Damit verhlält sich ein EduActor
-Objekt physiklisch realistisch.
Ein kinematisches EduActor
-Objekt interagiert mit sensor- oder statisch-Objekten wie aus der Jump'n'Run-Physik gewohnt. Allerdings kann es zu unvorhersehbaren Effekten kommen, wenn kinematisch bewegte und animierte Objekte interagieren!
Auf kinematischen Objekten kann man aber zusätzliche Methoden aufrufen, um die mechanischen Eigenschaften wie Reibung und Elastizität oder Größen wie Dichte, Masse, Geschwindigkeit und Winkelgeschwindigkeit festzulegen. Außerdem kann ein Impuls (Kraft-Stoß) in beliebige Richtung auf ein Objekt einwirken.
Es stehen folgende Methoden zur Verfügung:
- Versetzt das
macheKinematisch()
EduActor
-Objekt in den kinematischen Zustand. - Damit wird der Reibungskoeffizient dieses Objekts bei Berührung mit einem anderen kinematischen oder statischen Objekt festgelegt. Diese Änderung wird aber erst dann aktiv, wenn das Objekt kein anderes dynamisches oder statisches Objekt berührt. In diesem Fall tritt der Effekt zeitverzögert in Kraft, sobald die Berührung gelöst wird.
setzeReibung(double reibungsKoeffizient)
- Gib den aktuellen Reibungskoeffizienten zurück.
nenneReibung() : double
- Ein Wert von 1 bedeutet einen vollkommen elastischen Stoß. Ein Wert von 0 ein vollkommen inelastischer Stoß. Werte dazwischen sind möglich und können zu sehr realistischen Stößen führen. Werte über 1 sind möglich aber unrealistisch - können aber zu witzigen Effekten führen ...
setzeElastizitaet(double elastizitaet)
- Gibt den aktuellen Elastizitätswert zurück.
nenneElastizitaet() : double
- Das Objekt bewegt sich ab jetzt mit dieser Geschwindigkeit und Richtung. Die Maßeinheit ist m/s.
setzeGeschwindigkeit(double vX, double vY)
- Gibt die x-Komponente der aktuellen Geschwindigkeit in m/s zurück.
nenneGeschwindigkeitX() : double
- Gibt die y-Komponente der aktuellen Geschwindigkeit in m/s zurück.
nenneGeschwindigkeitY() : double
- Legt die Dichte des Objekts fest. Da es sich um eine 2D-Game-Engine handelt ist es streng genommen eine Flächendichte, Die Maßeinheit ist deshalb kg/m2. Eine Änderung der Dichte zieht logischerweise auch eine Änderung der Masse nach sich.
setzeDichte(double flaechendichte)
- Gibt den aktuellen Wert der Dichte des Objekts in kg/m2 zurück.
nenneDichte() : double
- Gibt den aktuellen Wert der Masse zurück. Die Maßeinheit ist kg. Die Masse kann NICHT direkt gesetzt werden! Stattdessen muss man Dichte und Abmessungen ändern, um die Masse zu verändern.
nenneMasse() : double
- Wirkt einen Impuls (Kraft-Stoß, Schlag, Kick) auf das Objekt aus. Die Maßeinheit ist kg*m/s. Die Wirkung des Impulses auf das Objekt hängt natürlich von dessen Masse ab. Schwerere Objekte verhalten sich "träger" bzw. "schwerfälliger".
wirkeImpuls(double pX, double pY)
setzeRotationBlockiert(boolean b)
true
bewirkt, dass sich kinematische Objekte bei Stößen nicht in Drehung versetzen, aber auch, dass sie erst von statischen Objekten fallen, wenn sie diese an keinem Punkt mehr berühren.false
bewirkt realistisches Verhalten wie Rotationsbewegungen nach Stößen oder Überkippen beim Abstürzen, sobald der Schwerpunkt die Kante eines statischen Objekts überwunden hat.- Setzt die Winkelgeschwindigkeit des Objekts in Umdrehungen pro Sekunde.
setzeWinkelgeschwindigkeit(double wg)
individuelle Kollisions-Formen
Der Kollisions-Bereich der EduActor
-Unterklassen KREIS
, RECHTECK
und DREIECK
ist klar definiert. Bei den Unterklassen FIGUR
und TEXT
ist es dagegen standardmäßig ein umhüllendes Rechteck. Das führt - z.B. bei Bildern mit transparentem Hintergrund nicht immer zu den gewünschten Interaktionen mit anderen Objekten.
Deshalb kann man jedem EduActor
auch eine individuelle Kollisions-Form - bestehend aus Rechtecken, Kreisen und Polygonen - erstellen.
Hierfür gibt es die Methode
setzeKollisionsformen(String formenDefinition)
Der übergebene String kann ein einzelner Kollisionsbereich oder auch eine Aneinanderreihung mehrerer einzelner Kollisionsbereiche enthalten. Die Maßeinheit ist Bildschirm-Meter und der Koordinatenursprung ist die linke untere Ecke des umhüllenden Rechtecks.
R1,0.5,1.2,3
Ein Rechteck mit linker, unterer Ecke (1|0,5), der Breite 1,2 und der Höhe 3C2.5,3,1.75
Ein Kreis (Circle) mit Mittelpunkt (2,5|3), der Radius 1,75P1,0,2,3,0.5,2
Ein Polygon (hier ein Dreieck) mit den Eckpunkten (1|0), (2|3) und (0.5|2)R1.5,0,0.5,2.7 &C1.5,4,1
Rechteck und Kreis kombiniert zu einem "Lolli"
! ! ! WICHTIG ! ! ! Zwischen dem & und dem folgenden Buchstaben darf KEIN Leerzeichen sein! Am Ende einer Form darf KEIN Komma stehen!
TIPP In Verbindung mit setzeRotationBlockiert(false)
und der Jump'n'Run-Physik können SpielFigur
en z.B. sehr realistisch von Brüstungen fallen ;-)
Verbindungen zwischen Objekten
Es ist auch möglich, mehrere EduActor
-Objekte miteinander auf verschiedene Arten zu verbinden.
... bald ...
Methoden zeitverzögert ausführen
Es ist auch möglich, jede beliebige Methode eines EduActor
-Objekts zeitverzögert und damit nebenläufig zum restlichen Code anzusetzen.
... bald ...