/* * Engine Alpha ist eine anfängerorientierte 2D-Gaming Engine. * * Copyright (c) 2011 - 2014 Michael Andonie and contributors. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package ea.internal.ani; import ea.*; /** * Ein <code>StreckenAnimierer</code> lässt ein Raum-Objekt sich auf einem Pfad von * beliebig vielen Punkten "wandern". * * @author Michael Andonie */ @SuppressWarnings ( "serial" ) public class StreckenAnimierer extends Animierer { /** * Das Array aller Punkte, die von diesem Animierer nacheinander abgefahren werden. */ private final Punkt[] punkte; /** * Der Vektor, der die animationsschrittweise Bewegung beschreibt. */ private Vektor vektor; /** * Der Vektor, der die Modulo-Bewegung fuer Bewegung festhaelt.<br /> Bei einer nichtrestlosen * Teilung der Bewegung wird der Rest auf diesen Vektor uebertragen. */ private Vektor modulo; /** * Der Count, der Angibt, an welchen Punkt sich das zu animierende Objekt gerade naehern soll. */ private int punkteCount; /** * Gibt an, ob gerade vorwaerts animiert wird. */ private boolean vorwaerts = true; /** * Gibt die Anzahl an Tick-Schritten an, die pro Etappe nötig sind. */ private final int schritteProEtappe; /** * Gibt an, ob prinzipiell im Kreis, oder strickt vorwaerts und anschliessend rueckwaerts * animiert wird.<br /> Ist nur von Belang, wenn die Animation geloopt sein soll. */ private boolean circuit = true; /** * Leicht vereinfachter Konstruktor der Klasse * * @param ziel * Das zu animierende Objekt * @param loop * Ob die Animation dauerhaft wiederholt (geloopt) werden soll, <b> sowie</b>, ob die * animation im Kreislauf stattfinden soll * @param m * Der Manager, an dem animiert werden soll. * @param geschwindigkeit * Die Geschwindigkeit, mit der die Bewegung stattfinden soll.<br /> Sie gibt in Millisekunden * an, wie lang die Bewegung zwischen 2 angegebenen Punkten dauern soll. * @param listener * Der AnimationsEndeReagierbar-Listener, der am Ende der Animation aufgerufen wird. * @param zielPunkte * Nacheinander alle Punkte, die die Animation ueberlaufen soll. */ public StreckenAnimierer (Raum ziel, boolean loop, Manager m, int geschwindigkeit, AnimationsEndeReagierbar listener, Punkt... zielPunkte) { this(ziel, loop, loop, m, geschwindigkeit, listener, zielPunkte); } /** * Erstellt ein Objekt dieser Klasse zum Animieren. * * @param ziel * Das zu animierende Objekt * @param loop * Ob die Animation dauerhaft wiederholt (geloopt) werden soll. * @param circuit * Gibt an, ob der letzte und der erste Punkt bei Wiederholung ebenfalls miteinander verbunden * animiert werden sollen (So dass immer ein geschlossener Kreislauf entsteht) * @param m * Der Manager, an dem animiert werden soll. * @param geschwindigkeit * Die Geschwindigkeit, mit der die Bewegung stattfinden soll.<br /> Sie gibt in Millisekunden * an, wie lang die Bewegung zwischen 2 angegebenen Punkten dauern soll. * @param listener * Der AnimationsEndeReagierbar-Listener, der am Ende der Animation aufgerufen wird. * @param zielPunkte * Nacheinander alle Punkte, die die Animation ueberlaufen soll. */ public StreckenAnimierer (Raum ziel, boolean loop, boolean circuit, Manager m, int geschwindigkeit, AnimationsEndeReagierbar listener, Punkt... zielPunkte) { super(ziel, loop, m, listener); this.schritteProEtappe = geschwindigkeit/Animierer.MILLISPERTICK; this.circuit = circuit; punkte = new Punkt[zielPunkte.length + 1]; this.punkte[0] = ziel.zentrum(); System.arraycopy(zielPunkte, 0, punkte, 1, punkte.length - 1); punkteCount = 1; Punkt p2 = punkte[1]; vektor = new Vektor((p2.realX() - punkte[0].realX()) / schritteProEtappe, (p2.realY() - punkte[0].realY()) / schritteProEtappe); modulo = new Vektor((p2.realX() - punkte[0].realX()) % schritteProEtappe, (p2.realY() - punkte[0].realY()) % schritteProEtappe); } /** * Vereinfachter Konstruktor der Klasse.<br /> Hierbei wird <b>automatisch</b> in einer * Dauerschleife und als Kreislauf animiert. * * @param ziel * Das zu animierende Objekt * @param m * Der Manager, an dem animiert werden soll. * @param geschwindigkeit * Die Dauer der Bewegung zwischen 2 "Etappen"-Punkten in Millisekunden.<br /> Sie gibt in * Millisekunden an, wie lang die Bewegung zwischen 2 angegebenen Punkten dauern soll. * @param listener * Der AnimationsEndeReagierbar-Listener, der am Ende der Animation aufgerufen wird. * @param zielPunkte * Nacheinander alle Punkte, die die Animation ueberlaufen soll. */ public StreckenAnimierer (Raum ziel, Manager m, int geschwindigkeit, AnimationsEndeReagierbar listener, Punkt... zielPunkte) { this(ziel, true, true, m, geschwindigkeit, listener, zielPunkte); } public void animationsSchritt () { ziel.bewegen(vektor); if (count == schritteProEtappe) { //Testweise ausgeklammert, da float-Rechnung kein Modulo braucht. //ziel.bewegen(modulo); Punkt p1 = punkte[punkteCount]; Punkt p2 = null; if (punkteCount == (punkte.length - 1) && vorwaerts) { if (loop) { if (circuit) { punkteCount = 0; p2 = punkte[punkteCount]; } else { vorwaerts = true; } } else { beenden(); return; } } else if (punkteCount == 0 && !vorwaerts) { if (loop) { if (!circuit) { vorwaerts = false; } else { // Passiert nie. // TODO Was soll dieses If hier, wenn der zweite Fall nie eintritt? } } else { beenden(); return; } } if (p2 == null) { if (!vorwaerts) { punkteCount--; } else { punkteCount++; } p2 = punkte[punkteCount]; } vektor = new Vektor((p2.realX() - p1.realX()) / schritteProEtappe, (p2.realY() - p1.realY()) / schritteProEtappe); modulo = new Vektor((p2.realX() - p1.realX()) % schritteProEtappe, (p2.realY() - p1.realY()) % schritteProEtappe); count = 0; } } }