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:

  • 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).

Szenen in der Engine: Beispiel mit Pausenmenü

Ein Pausenmenü

Das folgende Beispiel enthält zwei Szenen: Eine einfache Animation und ein Pausenmenü.

Ein Wechsel zwischen Hauptszene zu Pausenmenü und wieder zurück
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 eatutorials.util.Util;

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());
        Util.addScreenshotKey("Scenes");
        //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

Pausenbutton funktioniert nicht im PauseMenu.