mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 06:33:34 +02:00
interpolate zu animate umbenannt
Animation erbt zur Vereinfachung nun auch von Constants und dort gibt es schon eine interpolate Methode.
This commit is contained in:
@@ -2,15 +2,16 @@ package schule.ngb.zm.anim;
|
|||||||
|
|
||||||
import schule.ngb.zm.Constants;
|
import schule.ngb.zm.Constants;
|
||||||
import schule.ngb.zm.Updatable;
|
import schule.ngb.zm.Updatable;
|
||||||
|
import schule.ngb.zm.util.Validator;
|
||||||
import schule.ngb.zm.util.events.EventDispatcher;
|
import schule.ngb.zm.util.events.EventDispatcher;
|
||||||
|
|
||||||
import java.util.function.DoubleUnaryOperator;
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
public abstract class Animation<T> implements Updatable {
|
public abstract class Animation<T> extends Constants implements Updatable {
|
||||||
|
|
||||||
protected int runtime;
|
protected int runtime;
|
||||||
|
|
||||||
protected int elapsed_time = 0;
|
protected int elapsedTime = 0;
|
||||||
|
|
||||||
protected boolean running = false, finished = false;
|
protected boolean running = false, finished = false;
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ public abstract class Animation<T> implements Updatable {
|
|||||||
|
|
||||||
public Animation( DoubleUnaryOperator easing ) {
|
public Animation( DoubleUnaryOperator easing ) {
|
||||||
this.runtime = Constants.DEFAULT_ANIM_RUNTIME;
|
this.runtime = Constants.DEFAULT_ANIM_RUNTIME;
|
||||||
this.easing = easing;
|
this.easing = Validator.requireNotNull(easing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Animation( int runtime ) {
|
public Animation( int runtime ) {
|
||||||
@@ -33,7 +34,7 @@ public abstract class Animation<T> implements Updatable {
|
|||||||
|
|
||||||
public Animation( int runtime, DoubleUnaryOperator easing ) {
|
public Animation( int runtime, DoubleUnaryOperator easing ) {
|
||||||
this.runtime = runtime;
|
this.runtime = runtime;
|
||||||
this.easing = easing;
|
this.easing = Validator.requireNotNull(easing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRuntime() {
|
public int getRuntime() {
|
||||||
@@ -56,17 +57,17 @@ public abstract class Animation<T> implements Updatable {
|
|||||||
|
|
||||||
public final void start() {
|
public final void start() {
|
||||||
this.initialize();
|
this.initialize();
|
||||||
elapsed_time = 0;
|
elapsedTime = 0;
|
||||||
running = true;
|
running = true;
|
||||||
finished = false;
|
finished = false;
|
||||||
interpolate(easing.applyAsDouble(0.0));
|
animate(easing.applyAsDouble(0.0));
|
||||||
initializeEventDispatcher().dispatchEvent("start", this);
|
initializeEventDispatcher().dispatchEvent("start", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void stop() {
|
public final void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
// Make sure the last animation frame was interpolated correctly
|
// Make sure the last animation frame was interpolated correctly
|
||||||
interpolate(easing.applyAsDouble((double) elapsed_time / (double) runtime));
|
animate(easing.applyAsDouble((double) elapsedTime / (double) runtime));
|
||||||
this.finish();
|
this.finish();
|
||||||
finished = true;
|
finished = true;
|
||||||
initializeEventDispatcher().dispatchEvent("stop", this);
|
initializeEventDispatcher().dispatchEvent("stop", this);
|
||||||
@@ -82,11 +83,7 @@ public abstract class Animation<T> implements Updatable {
|
|||||||
|
|
||||||
public final void await() {
|
public final void await() {
|
||||||
while( !finished ) {
|
while( !finished ) {
|
||||||
try {
|
Thread.yield();
|
||||||
Thread.sleep(1);
|
|
||||||
} catch( InterruptedException ex ) {
|
|
||||||
// Keep waiting
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,16 +94,16 @@ public abstract class Animation<T> implements Updatable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( double delta ) {
|
public void update( double delta ) {
|
||||||
elapsed_time += (int) (delta * 1000);
|
elapsedTime += (int) (delta * 1000);
|
||||||
if( elapsed_time > runtime )
|
if( elapsedTime > runtime )
|
||||||
elapsed_time = runtime;
|
elapsedTime = runtime;
|
||||||
|
|
||||||
double t = (double) elapsed_time / (double) runtime;
|
double t = (double) elapsedTime / (double) runtime;
|
||||||
if( t >= 1.0 ) {
|
if( t >= 1.0 ) {
|
||||||
running = false;
|
running = false;
|
||||||
stop();
|
stop();
|
||||||
} else {
|
} else {
|
||||||
interpolate(easing.applyAsDouble(t));
|
animate(easing.applyAsDouble(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +121,7 @@ public abstract class Animation<T> implements Updatable {
|
|||||||
* @param e Fortschritt der Animation nachdem die Easingfunktion angewandt
|
* @param e Fortschritt der Animation nachdem die Easingfunktion angewandt
|
||||||
* wurde.
|
* wurde.
|
||||||
*/
|
*/
|
||||||
public abstract void interpolate( double e );
|
public abstract void animate( double e );
|
||||||
|
|
||||||
EventDispatcher<Animation, AnimationListener> eventDispatcher;
|
EventDispatcher<Animation, AnimationListener> eventDispatcher;
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ public class AnimationFacade<S> extends Animation<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
anim.interpolate(e);
|
anim.animate(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,76 +1,116 @@
|
|||||||
package schule.ngb.zm.anim;
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
import schule.ngb.zm.shapes.Shape;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.function.DoubleUnaryOperator;
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
public class AnimationGroup extends Animation<Shape> {
|
@SuppressWarnings( "unused" )
|
||||||
|
public class AnimationGroup<T> extends Animation<T> {
|
||||||
|
|
||||||
Animation<? extends Shape>[] anims;
|
List<Animation<T>> anims;
|
||||||
|
|
||||||
private boolean overrideRuntime = false;
|
|
||||||
|
|
||||||
|
|
||||||
public AnimationGroup( DoubleUnaryOperator easing, Animation<? extends Shape>... anims ) {
|
private boolean overrideEasing = false;
|
||||||
super(easing);
|
|
||||||
this.anims = anims;
|
|
||||||
|
|
||||||
int maxRuntime = Arrays.stream(this.anims).mapToInt((a) -> a.getRuntime()).reduce(0, Integer::max);
|
private int overrideRuntime = -1;
|
||||||
setRuntime(maxRuntime);
|
|
||||||
|
private int lag = 0;
|
||||||
|
|
||||||
|
private int active = 0;
|
||||||
|
|
||||||
|
public AnimationGroup( Collection<Animation<T>> anims ) {
|
||||||
|
this(0, -1, null, anims);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnimationGroup( int runtime, DoubleUnaryOperator easing, Animation<? extends Shape>... anims ) {
|
public AnimationGroup( int lag, Collection<Animation<T>> anims ) {
|
||||||
super(runtime, easing);
|
this(lag, -1, null, anims);
|
||||||
this.anims = anims;
|
}
|
||||||
overrideRuntime = true;
|
|
||||||
|
public AnimationGroup( DoubleUnaryOperator easing, Collection<Animation<T>> anims ) {
|
||||||
|
this(0, -1, easing, anims);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimationGroup( int lag, DoubleUnaryOperator easing, Collection<Animation<T>> anims ) {
|
||||||
|
this(lag, -1, easing, anims);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimationGroup( int lag, int runtime, DoubleUnaryOperator easing, Collection<Animation<T>> anims ) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.anims = List.copyOf(anims);
|
||||||
|
this.lag = lag;
|
||||||
|
|
||||||
|
if( easing != null ) {
|
||||||
|
this.easing = easing;
|
||||||
|
overrideEasing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( runtime > 0 ) {
|
||||||
|
this.runtime = anims.size() * lag + runtime;
|
||||||
|
this.overrideRuntime = runtime;
|
||||||
|
} else {
|
||||||
|
this.runtime = 0;
|
||||||
|
for( int i = 0; i < this.anims.size(); i++ ) {
|
||||||
|
if( i * lag + this.anims.get(i).getRuntime() > this.runtime ) {
|
||||||
|
this.runtime = i * lag + this.anims.get(i).getRuntime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Shape getAnimationTarget() {
|
public T getAnimationTarget() {
|
||||||
return null;
|
for( Animation<T> anim : anims ) {
|
||||||
|
if( anim.isActive() ) {
|
||||||
|
return anim.getAnimationTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return anims.get(anims.size() - 1).getAnimationTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( double delta ) {
|
public void update( double delta ) {
|
||||||
if( overrideRuntime ) {
|
elapsedTime += (int) (delta * 1000);
|
||||||
synchronized( anims ) {
|
// Animation is done. Stop all Animations.
|
||||||
for( Animation<? extends Shape> anim: anims ) {
|
if( elapsedTime > runtime ) {
|
||||||
if( anim.isActive() ) {
|
for( int i = 0; i < anims.size(); i++ ) {
|
||||||
anim.update(delta);
|
if( anims.get(i).isActive() ) {
|
||||||
}
|
anims.get(i).elapsedTime = anims.get(i).runtime;
|
||||||
|
anims.get(i).stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
running = false;
|
||||||
super.update(delta);
|
this.stop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
while( active < anims.size() && elapsedTime >= active * lag ) {
|
||||||
public void interpolate( double e ) {
|
anims.get(active).start();
|
||||||
synchronized( anims ) {
|
active += 1;
|
||||||
for( Animation<? extends Shape> anim: anims ) {
|
}
|
||||||
anim.interpolate(e);
|
|
||||||
|
for( int i = 0; i < active; i++ ) {
|
||||||
|
double t = 0.0;
|
||||||
|
if( overrideRuntime > 0 ) {
|
||||||
|
t = (double) (elapsedTime - i*lag) / (double) overrideRuntime;
|
||||||
|
} else {
|
||||||
|
t = (double) (elapsedTime - i*lag) / (double) anims.get(i).getRuntime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( t >= 1.0 ) {
|
||||||
|
anims.get(i).elapsedTime = anims.get(i).runtime;
|
||||||
|
anims.get(i).stop();
|
||||||
|
} else {
|
||||||
|
double e = overrideEasing ?
|
||||||
|
easing.applyAsDouble(t) :
|
||||||
|
anims.get(i).easing.applyAsDouble(t);
|
||||||
|
|
||||||
|
anims.get(i).animate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void animate( double e ) {
|
||||||
synchronized( anims ) {
|
|
||||||
for( Animation<? extends Shape> anim: anims ) {
|
|
||||||
anim.initialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
synchronized( anims ) {
|
|
||||||
for( Animation<? extends Shape> anim: anims ) {
|
|
||||||
anim.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
39
src/main/java/schule/ngb/zm/anim/CircleAnimation.java
Normal file
39
src/main/java/schule/ngb/zm/anim/CircleAnimation.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.Vector;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class CircleAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object;
|
||||||
|
|
||||||
|
private double centerx, centery, radius, startangle;
|
||||||
|
|
||||||
|
public CircleAnimation( Shape target, double cx, double cy, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
object = target;
|
||||||
|
centerx = cx;
|
||||||
|
centery = cy;
|
||||||
|
Vector vec = new Vector(target.getX(), target.getY()).sub(cx, cy);
|
||||||
|
startangle = vec.heading();
|
||||||
|
radius = vec.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void animate( double e ) {
|
||||||
|
double angle = startangle + Constants.radians(Constants.interpolate(0, 360, e));
|
||||||
|
double x = centerx + radius * Constants.cos(angle);
|
||||||
|
double y = centery + radius * Constants.sin(angle);
|
||||||
|
object.moveTo(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
74
src/main/java/schule/ngb/zm/anim/ContinousAnimation.java
Normal file
74
src/main/java/schule/ngb/zm/anim/ContinousAnimation.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
@SuppressWarnings( "unused" )
|
||||||
|
public class ContinousAnimation<T> extends Animation<T> {
|
||||||
|
|
||||||
|
private final Animation<T> baseAnimation;
|
||||||
|
|
||||||
|
private int lag = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Speichert eine Approximation der aktuellen Steigung der Easing-Funktion,
|
||||||
|
* um im Fall {@code easeInOnly == true} nach dem ersten Durchlauf die
|
||||||
|
* passende Geschwindigkeit beizubehalten.
|
||||||
|
*/
|
||||||
|
private double m = 1.0, lastEase = 0.0;
|
||||||
|
|
||||||
|
private boolean easeInOnly = false;
|
||||||
|
|
||||||
|
public ContinousAnimation( Animation<T> baseAnimation ) {
|
||||||
|
this(baseAnimation, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContinousAnimation( Animation<T> baseAnimation, int lag ) {
|
||||||
|
this(baseAnimation, lag, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContinousAnimation( Animation<T> baseAnimation, boolean easeInOnly ) {
|
||||||
|
this(baseAnimation, 0, easeInOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContinousAnimation( Animation<T> baseAnimation, int lag, boolean easeInOnly ) {
|
||||||
|
super(baseAnimation.getRuntime(), baseAnimation.getEasing());
|
||||||
|
this.baseAnimation = baseAnimation;
|
||||||
|
this.lag = lag;
|
||||||
|
this.easeInOnly = easeInOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getAnimationTarget() {
|
||||||
|
return baseAnimation.getAnimationTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
elapsedTime += (int) (delta * 1000);
|
||||||
|
if( elapsedTime >= runtime + lag ) {
|
||||||
|
elapsedTime %= (runtime + lag);
|
||||||
|
|
||||||
|
if( easeInOnly && easing != null ) {
|
||||||
|
easing = null;
|
||||||
|
// runtime = (int)((1.0/m)*(runtime + lag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double t = (double) elapsedTime / (double) runtime;
|
||||||
|
if( t >= 1.0 ) {
|
||||||
|
t = 1.0;
|
||||||
|
}
|
||||||
|
if( easing != null ) {
|
||||||
|
double e = easing.applyAsDouble(t);
|
||||||
|
animate(e);
|
||||||
|
m = (e-lastEase)/(delta*1000/(asDouble(runtime)));
|
||||||
|
lastEase = e;
|
||||||
|
} else {
|
||||||
|
animate(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void animate( double e ) {
|
||||||
|
baseAnimation.animate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ public class FadeAnimation extends Animation<Shape> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
object.setFillColor(new Color(fill, (int) Constants.interpolate(fillAlpha, tAlpha, e)));
|
object.setFillColor(new Color(fill, (int) Constants.interpolate(fillAlpha, tAlpha, e)));
|
||||||
object.setStrokeColor(new Color(stroke, (int) Constants.interpolate(strokeAlpha, tAlpha, e)));
|
object.setStrokeColor(new Color(stroke, (int) Constants.interpolate(strokeAlpha, tAlpha, e)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class FillAnimation extends Animation<Shape> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
object.setFillColor(Color.interpolate(oFill, tFill, e));
|
object.setFillColor(Color.interpolate(oFill, tFill, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class MorphAnimation extends Animation<Shape> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
object.setX(Constants.interpolate(original.getX(), target.getX(), e));
|
object.setX(Constants.interpolate(original.getX(), target.getX(), e));
|
||||||
object.setY(Constants.interpolate(original.getY(), target.getY(), e));
|
object.setY(Constants.interpolate(original.getY(), target.getY(), e));
|
||||||
object.setFillColor(Color.interpolate(original.getFillColor(), target.getFillColor(), e));
|
object.setFillColor(Color.interpolate(original.getFillColor(), target.getFillColor(), e));
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class MoveAnimation extends Animation<Shape> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
object.setX(Constants.interpolate(oX, tX, e));
|
object.setX(Constants.interpolate(oX, tX, e));
|
||||||
object.setY(Constants.interpolate(oY, tY, e));
|
object.setY(Constants.interpolate(oY, tY, e));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class RotateAnimation extends Animation<Shape> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
object.rotateTo(Constants.interpolate(oA, tA, e));
|
object.rotateTo(Constants.interpolate(oA, tA, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class StrokeAnimation extends Animation<Shape> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate( double e ) {
|
public void animate( double e ) {
|
||||||
object.setStrokeColor(Color.interpolate(oFill, tFill, e));
|
object.setStrokeColor(Color.interpolate(oFill, tFill, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
src/main/java/schule/ngb/zm/anim/WaveAnimation.java
Normal file
37
src/main/java/schule/ngb/zm/anim/WaveAnimation.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class WaveAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object;
|
||||||
|
|
||||||
|
private double strength, sinOffset, previousDelta = 0.0;
|
||||||
|
|
||||||
|
private Options.Direction dir;
|
||||||
|
|
||||||
|
public WaveAnimation( Shape target, double strength, Options.Direction dir, double sinOffset, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
this.object = target;
|
||||||
|
this.dir = dir;
|
||||||
|
this.strength = strength;
|
||||||
|
this.sinOffset = sinOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void animate( double e ) {
|
||||||
|
double delta = this.strength * Constants.sin(Constants.interpolate(0.0, Constants.TWO_PI, e) + sinOffset);
|
||||||
|
object.move((delta - previousDelta) * dir.x, (delta - previousDelta) * dir.y);
|
||||||
|
previousDelta = delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user