v4.x/Scenes: Unterschied zwischen den Versionen
(→Ein Pausenmenü) |
(→Ein Pausenmenü) |
||
(3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 32: | Zeile 32: | ||
import ea.event.MouseButton; | import ea.event.MouseButton; | ||
import ea.event.MouseClickListener; | import ea.event.MouseClickListener; | ||
− | |||
import java.awt.Color; | import java.awt.Color; | ||
Zeile 64: | Zeile 63: | ||
public static void main(String[] args) { | public static void main(String[] args) { | ||
Game.start(600, 400, new MainScene()); | Game.start(600, 400, new MainScene()); | ||
− | |||
//Game.setDebug(true); | //Game.setDebug(true); | ||
} | } | ||
Zeile 144: | Zeile 142: | ||
public class MainScene | public class MainScene | ||
extends Scene { | extends Scene { | ||
+ | private Scene pauseMenu; | ||
//... | //... | ||
} | } | ||
Zeile 149: | Zeile 148: | ||
private class PauseMenu | private class PauseMenu | ||
extends Scene { | extends Scene { | ||
+ | private Scene mainScene; | ||
//... | //... | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Die Haupt-Szene wird per Knopfdruck pausiert. Wird der P-Knopf gedrückt, wird die Transition ausgeführt: | ||
+ | |||
+ | <source lang="java"> | ||
+ | private void gotoPause() { | ||
+ | Game.transitionToScene(pauseMenu); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Das Pausenmenü wird statt mit Tastatur per Mausklick geschlossen. Im internen Steuerelement <code>MenuItem</code> wird dafür die entsprechende Methode aufgerufen, wann immer ein Mausklick auf dem Element landet - dies wird durch die Methode [https://docs.engine-alpha.org/4.x/ea/actor/Actor.html#contains-ea.Vector- <code>contains(Vector)</code>] geprüft: | ||
+ | |||
+ | <source lang="java"> | ||
+ | @Override | ||
+ | public void onMouseDown(Vector clickLoc, MouseButton mouseButton) { | ||
+ | if(contains(clickLoc)) { | ||
+ | Game.transitionToScene(mainScene); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | === Kosmetische Kleinigkeiten === | ||
+ | |||
+ | Damit es zumindest irgendetwas zu sehen gibt in den zwei kahlen Szenen, hat die Hauptszene eine [[v4.x/Interpolation|Interpolierte Rotationsanimation]]. Diese rotiert ein oranges Rechteck wiederholend um den Punkt <code>(0|0)</code>. Eine volle Rotation im Uhrzeigersinn dauert 8 Sekunden. | ||
+ | |||
+ | <source lang="java"> | ||
+ | Rectangle toAnimate = new Rectangle(5, 2); | ||
+ | toAnimate.setCenter(0, -5); | ||
+ | toAnimate.setColor(Color.ORANGE); | ||
+ | |||
+ | CircleAnimation animation = new CircleAnimation(toAnimate, new Vector(0,0), 8, true, true); | ||
+ | addFrameUpdateListener(animation); | ||
+ | |||
+ | add(toAnimate); | ||
+ | </source> | ||
+ | |||
+ | Das Pausenmenü hat einen '''Hover-Effekt'''. Hierzu wird einfach jeden Frame überprüft, ob die Maus derzeit innerhalb des Steuerelementes liegt und abhängig davon die Rechtecksfarbe ändert. Hierzu wird die Methode [https://docs.engine-alpha.org/4.x/ea/Game.html#getMousePositionInCurrentScene-- <code>ea.Game.getMousePositionInCurrentScene()</code>] genutzt: | ||
+ | |||
+ | <source lang="java"> | ||
+ | @Override | ||
+ | public void onFrameUpdate(float v) { | ||
+ | if(contains(Game.getMousePositionInCurrentScene())) { | ||
+ | this.setColor(Color.MAGENTA); | ||
+ | } else { | ||
+ | this.setColor(Color.CYAN); | ||
+ | } | ||
} | } | ||
</source> | </source> | ||
Zeile 155: | Zeile 202: | ||
=== Anmerkungen und Beobachtungen === | === Anmerkungen und Beobachtungen === | ||
− | + | * '''Die Kreisrotation in der Hauptszene geht nicht weiter, solange das Pausenmenü die aktive Szene ist'''. Dies liegt daran, dass die Animation als <code>FrameUpdateListener</code> in der Hauptszene angemeldet wurde (<code>addFrameUpdateListener(animation)</code>). Alle Listener einer Szene können nur dann aufgerufen werden, wenn die Szene aktiv ist. | |
+ | * '''Deshalb lässt sich das Pausenmenü nicht durch drücken von P beenden'''. Der <code>KeyListener</code>, der bei Druck von P zum Pausenmenü wechselt, ist in der Hauptszene angemeldet. |
Aktuelle Version vom 5. Januar 2020, 18:20 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.
Inhaltsverzeichnis
Inhalt
In diesem Tutorial:
- Wechselst du zwischen mehreren Szenen
- Baust du ein Pausenmenü mit einem interaktiven Button-Element
Scenes in der Engine
Die bisherigen Beispiele waren simplistisch. Ein echtes Spiel hat mehrere verschiedene "Teile", zwischen denen der Spieler während des Spielens wechselt. Zum Beispiel gibt es neben der Hauptdarstellung: Pausenmenüs, Level-Selections, Inventare, Hauptmenüs, etc. Es wäre unnötig komplex, für den Wechsel zwischen diesen Szenen stets alle grafischen Objekte zu zerstören und wieder neu aufzubauen. Stattdessen werden alle grafischen Objekte in einer ea.Scene
hinzugefügt. Dies passiert - wie in den vorigen Tutorials - über die Methode add(...)
.
Über die Klasse Game
kann schnell zwischen Szenen gewechselt werden. Dazu gibt es die Methode Game.transitionToScene(Scene)
.
Ein Pausenmenü
Das folgende Beispiel enthält zwei Szenen: Eine einfache Animation und ein Pausenmenü.
import ea.*;
import ea.actor.Rectangle;
import ea.actor.Text;
import ea.animation.CircleAnimation;
import ea.event.KeyListener;
import ea.event.MouseButton;
import ea.event.MouseClickListener;
import java.awt.Color;
import java.awt.event.KeyEvent;
public class MainScene
extends Scene
implements KeyListener {
private PauseMenu pauseMenu;
public MainScene() {
pauseMenu = new PauseMenu(this);
Rectangle toAnimate = new Rectangle(5, 2);
toAnimate.setCenter(0, -5);
toAnimate.setColor(Color.ORANGE);
CircleAnimation animation = new CircleAnimation(toAnimate, new Vector(0,0), 8, true, true);
addFrameUpdateListener(animation);
add(toAnimate);
addKeyListener(this);
Text info = new Text("Pause mit P", 0.5f);
info.setCenter(-7, -5);
add(info);
}
public static void main(String[] args) {
Game.start(600, 400, new MainScene());
//Game.setDebug(true);
}
@Override
public void onKeyDown(KeyEvent keyEvent) {
if(keyEvent.getKeyCode() == KeyEvent.VK_P) {
gotoPause();
}
}
private void gotoPause() {
Game.transitionToScene(pauseMenu);
}
private class PauseMenu
extends Scene {
private Scene mainScene;
public PauseMenu(Scene mainScene) {
this.mainScene = mainScene;
MenuItem back = new MenuItem(new Vector(0,-5), "Zurück");
add(back, back.label);
Text headline = new Text("Mach mal Pause.", 2.5f);
headline.setCenter(0, 3);
add(headline);
}
private class MenuItem
extends Rectangle
implements MouseClickListener, FrameUpdateListener{
private Text label;
public MenuItem(Vector center, String labelText) {
super(10, 1.5f);
label = new Text(labelText, 1);
label.setLayerPosition(1);
label.setColor(Color.BLACK);
label.setCenter(center);
setLayerPosition(0);
setColor(Color.cyan);
setCenter(center);
}
@Override
public void onMouseDown(Vector clickLoc, MouseButton mouseButton) {
if(contains(clickLoc)) {
Game.transitionToScene(mainScene);
}
}
@Override
public void onFrameUpdate(float v) {
if(contains(Game.getMousePositionInCurrentScene())) {
this.setColor(Color.MAGENTA);
} else {
this.setColor(Color.CYAN);
}
}
}
}
}
Die zwei Szenen
Die Hauptszene ist MainScene
. Hierdrin könnte ein normaler Game Loop für ein Spiel stattfinden. Für dieses Tutorial ist in der Hauptszene stattdessen nur eine stumpfe Animation.
Die zweite Szene ist PauseMenu
. In ihr gibt es eine Textbotschaft und einen kleinen Button, um das Menü wieder zu verlassen.
public class MainScene
extends Scene {
private Scene pauseMenu;
//...
}
private class PauseMenu
extends Scene {
private Scene mainScene;
//...
}
Die Haupt-Szene wird per Knopfdruck pausiert. Wird der P-Knopf gedrückt, wird die Transition ausgeführt:
private void gotoPause() {
Game.transitionToScene(pauseMenu);
}
Das Pausenmenü wird statt mit Tastatur per Mausklick geschlossen. Im internen Steuerelement MenuItem
wird dafür die entsprechende Methode aufgerufen, wann immer ein Mausklick auf dem Element landet - dies wird durch die Methode contains(Vector)
geprüft:
@Override
public void onMouseDown(Vector clickLoc, MouseButton mouseButton) {
if(contains(clickLoc)) {
Game.transitionToScene(mainScene);
}
}
Kosmetische Kleinigkeiten
Damit es zumindest irgendetwas zu sehen gibt in den zwei kahlen Szenen, hat die Hauptszene eine Interpolierte Rotationsanimation. Diese rotiert ein oranges Rechteck wiederholend um den Punkt (0|0)
. Eine volle Rotation im Uhrzeigersinn dauert 8 Sekunden.
Rectangle toAnimate = new Rectangle(5, 2);
toAnimate.setCenter(0, -5);
toAnimate.setColor(Color.ORANGE);
CircleAnimation animation = new CircleAnimation(toAnimate, new Vector(0,0), 8, true, true);
addFrameUpdateListener(animation);
add(toAnimate);
Das Pausenmenü hat einen Hover-Effekt. Hierzu wird einfach jeden Frame überprüft, ob die Maus derzeit innerhalb des Steuerelementes liegt und abhängig davon die Rechtecksfarbe ändert. Hierzu wird die Methode ea.Game.getMousePositionInCurrentScene()
genutzt:
@Override
public void onFrameUpdate(float v) {
if(contains(Game.getMousePositionInCurrentScene())) {
this.setColor(Color.MAGENTA);
} else {
this.setColor(Color.CYAN);
}
}
Anmerkungen und Beobachtungen
- Die Kreisrotation in der Hauptszene geht nicht weiter, solange das Pausenmenü die aktive Szene ist. Dies liegt daran, dass die Animation als
FrameUpdateListener
in der Hauptszene angemeldet wurde (addFrameUpdateListener(animation)
). Alle Listener einer Szene können nur dann aufgerufen werden, wenn die Szene aktiv ist. - Deshalb lässt sich das Pausenmenü nicht durch drücken von P beenden. Der
KeyListener
, der bei Druck von P zum Pausenmenü wechselt, ist in der Hauptszene angemeldet.