mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 06:33:34 +02:00
Animation erbt zur Vereinfachung nun auch von Constants und dort gibt es schon eine interpolate Methode.
146 lines
3.5 KiB
Java
146 lines
3.5 KiB
Java
package schule.ngb.zm.anim;
|
|
|
|
import schule.ngb.zm.Constants;
|
|
import schule.ngb.zm.Updatable;
|
|
import schule.ngb.zm.util.Validator;
|
|
import schule.ngb.zm.util.events.EventDispatcher;
|
|
|
|
import java.util.function.DoubleUnaryOperator;
|
|
|
|
public abstract class Animation<T> extends Constants implements Updatable {
|
|
|
|
protected int runtime;
|
|
|
|
protected int elapsedTime = 0;
|
|
|
|
protected boolean running = false, finished = false;
|
|
|
|
protected DoubleUnaryOperator easing;
|
|
|
|
public Animation() {
|
|
this.runtime = Constants.DEFAULT_ANIM_RUNTIME;
|
|
this.easing = Constants.DEFAULT_EASING;
|
|
}
|
|
|
|
public Animation( DoubleUnaryOperator easing ) {
|
|
this.runtime = Constants.DEFAULT_ANIM_RUNTIME;
|
|
this.easing = Validator.requireNotNull(easing);
|
|
}
|
|
|
|
public Animation( int runtime ) {
|
|
this.runtime = runtime;
|
|
this.easing = Constants.DEFAULT_EASING;
|
|
}
|
|
|
|
public Animation( int runtime, DoubleUnaryOperator easing ) {
|
|
this.runtime = runtime;
|
|
this.easing = Validator.requireNotNull(easing);
|
|
}
|
|
|
|
public int getRuntime() {
|
|
return runtime;
|
|
}
|
|
|
|
public void setRuntime( int pRuntime ) {
|
|
this.runtime = pRuntime;
|
|
}
|
|
|
|
public DoubleUnaryOperator getEasing() {
|
|
return easing;
|
|
}
|
|
|
|
public void setEasing( DoubleUnaryOperator pEasing ) {
|
|
this.easing = pEasing;
|
|
}
|
|
|
|
public abstract T getAnimationTarget();
|
|
|
|
public final void start() {
|
|
this.initialize();
|
|
elapsedTime = 0;
|
|
running = true;
|
|
finished = false;
|
|
animate(easing.applyAsDouble(0.0));
|
|
initializeEventDispatcher().dispatchEvent("start", this);
|
|
}
|
|
|
|
public final void stop() {
|
|
running = false;
|
|
// Make sure the last animation frame was interpolated correctly
|
|
animate(easing.applyAsDouble((double) elapsedTime / (double) runtime));
|
|
this.finish();
|
|
finished = true;
|
|
initializeEventDispatcher().dispatchEvent("stop", this);
|
|
}
|
|
|
|
public void initialize() {
|
|
// Intentionally left blank
|
|
}
|
|
|
|
public void finish() {
|
|
// Intentionally left blank
|
|
}
|
|
|
|
public final void await() {
|
|
while( !finished ) {
|
|
Thread.yield();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isActive() {
|
|
return running;
|
|
}
|
|
|
|
@Override
|
|
public void update( double delta ) {
|
|
elapsedTime += (int) (delta * 1000);
|
|
if( elapsedTime > runtime )
|
|
elapsedTime = runtime;
|
|
|
|
double t = (double) elapsedTime / (double) runtime;
|
|
if( t >= 1.0 ) {
|
|
running = false;
|
|
stop();
|
|
} else {
|
|
animate(easing.applyAsDouble(t));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setzt den Fortschritt der Animation auf den angegebenen Wert.
|
|
* <p>
|
|
* {@code e} liegt in der Regel zwischen 0 und 1. Je nach verwendeten
|
|
* {@link Easing} Funktion kann der Wert aber in Ausnahmefällen unter 0 oder
|
|
* über 1 liegen. Die {@code step()} Methode muss dem nicht Rechnung tragen
|
|
* und kann wenn sinnvoll den {@code e} Wert auf [0, 1] limitieren:
|
|
* <pre><code>
|
|
* e = Constants.limit(e, 0, 1);
|
|
* </code></pre>
|
|
*
|
|
* @param e Fortschritt der Animation nachdem die Easingfunktion angewandt
|
|
* wurde.
|
|
*/
|
|
public abstract void animate( double e );
|
|
|
|
EventDispatcher<Animation, AnimationListener> eventDispatcher;
|
|
|
|
private EventDispatcher<Animation, AnimationListener> initializeEventDispatcher() {
|
|
if( eventDispatcher == null ) {
|
|
eventDispatcher = new EventDispatcher<>();
|
|
eventDispatcher.registerEventType("start", ( a, l ) -> l.animationStarted(a));
|
|
eventDispatcher.registerEventType("stop", ( a, l ) -> l.animationStopped(a));
|
|
}
|
|
return eventDispatcher;
|
|
}
|
|
|
|
public void addListener( AnimationListener listener ) {
|
|
initializeEventDispatcher().addListener(listener);
|
|
}
|
|
|
|
public void removeListener( AnimationListener listener ) {
|
|
initializeEventDispatcher().removeListener(listener);
|
|
}
|
|
|
|
}
|