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.Updatable;
|
||||
import schule.ngb.zm.util.Validator;
|
||||
import schule.ngb.zm.util.events.EventDispatcher;
|
||||
|
||||
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 elapsed_time = 0;
|
||||
protected int elapsedTime = 0;
|
||||
|
||||
protected boolean running = false, finished = false;
|
||||
|
||||
@@ -23,7 +24,7 @@ public abstract class Animation<T> implements Updatable {
|
||||
|
||||
public Animation( DoubleUnaryOperator easing ) {
|
||||
this.runtime = Constants.DEFAULT_ANIM_RUNTIME;
|
||||
this.easing = easing;
|
||||
this.easing = Validator.requireNotNull(easing);
|
||||
}
|
||||
|
||||
public Animation( int runtime ) {
|
||||
@@ -33,7 +34,7 @@ public abstract class Animation<T> implements Updatable {
|
||||
|
||||
public Animation( int runtime, DoubleUnaryOperator easing ) {
|
||||
this.runtime = runtime;
|
||||
this.easing = easing;
|
||||
this.easing = Validator.requireNotNull(easing);
|
||||
}
|
||||
|
||||
public int getRuntime() {
|
||||
@@ -56,17 +57,17 @@ public abstract class Animation<T> implements Updatable {
|
||||
|
||||
public final void start() {
|
||||
this.initialize();
|
||||
elapsed_time = 0;
|
||||
elapsedTime = 0;
|
||||
running = true;
|
||||
finished = false;
|
||||
interpolate(easing.applyAsDouble(0.0));
|
||||
animate(easing.applyAsDouble(0.0));
|
||||
initializeEventDispatcher().dispatchEvent("start", this);
|
||||
}
|
||||
|
||||
public final void stop() {
|
||||
running = false;
|
||||
// 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();
|
||||
finished = true;
|
||||
initializeEventDispatcher().dispatchEvent("stop", this);
|
||||
@@ -82,11 +83,7 @@ public abstract class Animation<T> implements Updatable {
|
||||
|
||||
public final void await() {
|
||||
while( !finished ) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch( InterruptedException ex ) {
|
||||
// Keep waiting
|
||||
}
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,16 +94,16 @@ public abstract class Animation<T> implements Updatable {
|
||||
|
||||
@Override
|
||||
public void update( double delta ) {
|
||||
elapsed_time += (int) (delta * 1000);
|
||||
if( elapsed_time > runtime )
|
||||
elapsed_time = runtime;
|
||||
elapsedTime += (int) (delta * 1000);
|
||||
if( elapsedTime > runtime )
|
||||
elapsedTime = runtime;
|
||||
|
||||
double t = (double) elapsed_time / (double) runtime;
|
||||
double t = (double) elapsedTime / (double) runtime;
|
||||
if( t >= 1.0 ) {
|
||||
running = false;
|
||||
stop();
|
||||
} 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
|
||||
* wurde.
|
||||
*/
|
||||
public abstract void interpolate( double e );
|
||||
public abstract void animate( double e );
|
||||
|
||||
EventDispatcher<Animation, AnimationListener> eventDispatcher;
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ public class AnimationFacade<S> extends Animation<S> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
anim.interpolate(e);
|
||||
public void animate( double e ) {
|
||||
anim.animate(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,76 +1,116 @@
|
||||
package schule.ngb.zm.anim;
|
||||
|
||||
import schule.ngb.zm.shapes.Shape;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.DoubleUnaryOperator;
|
||||
|
||||
public class AnimationGroup extends Animation<Shape> {
|
||||
@SuppressWarnings( "unused" )
|
||||
public class AnimationGroup<T> extends Animation<T> {
|
||||
|
||||
Animation<? extends Shape>[] anims;
|
||||
|
||||
private boolean overrideRuntime = false;
|
||||
List<Animation<T>> anims;
|
||||
|
||||
|
||||
public AnimationGroup( DoubleUnaryOperator easing, Animation<? extends Shape>... anims ) {
|
||||
super(easing);
|
||||
this.anims = anims;
|
||||
private boolean overrideEasing = false;
|
||||
|
||||
int maxRuntime = Arrays.stream(this.anims).mapToInt((a) -> a.getRuntime()).reduce(0, Integer::max);
|
||||
setRuntime(maxRuntime);
|
||||
private int overrideRuntime = -1;
|
||||
|
||||
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 ) {
|
||||
super(runtime, easing);
|
||||
this.anims = anims;
|
||||
overrideRuntime = true;
|
||||
public AnimationGroup( int lag, Collection<Animation<T>> anims ) {
|
||||
this(lag, -1, null, anims);
|
||||
}
|
||||
|
||||
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
|
||||
public Shape getAnimationTarget() {
|
||||
return null;
|
||||
public T getAnimationTarget() {
|
||||
for( Animation<T> anim : anims ) {
|
||||
if( anim.isActive() ) {
|
||||
return anim.getAnimationTarget();
|
||||
}
|
||||
}
|
||||
return anims.get(anims.size() - 1).getAnimationTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( double delta ) {
|
||||
if( overrideRuntime ) {
|
||||
synchronized( anims ) {
|
||||
for( Animation<? extends Shape> anim: anims ) {
|
||||
if( anim.isActive() ) {
|
||||
anim.update(delta);
|
||||
elapsedTime += (int) (delta * 1000);
|
||||
// Animation is done. Stop all Animations.
|
||||
if( elapsedTime > runtime ) {
|
||||
for( int i = 0; i < anims.size(); i++ ) {
|
||||
if( anims.get(i).isActive() ) {
|
||||
anims.get(i).elapsedTime = anims.get(i).runtime;
|
||||
anims.get(i).stop();
|
||||
}
|
||||
}
|
||||
running = false;
|
||||
this.stop();
|
||||
}
|
||||
|
||||
while( active < anims.size() && elapsedTime >= active * lag ) {
|
||||
anims.get(active).start();
|
||||
active += 1;
|
||||
}
|
||||
|
||||
for( int i = 0; i < active; i++ ) {
|
||||
double t = 0.0;
|
||||
if( overrideRuntime > 0 ) {
|
||||
t = (double) (elapsedTime - i*lag) / (double) overrideRuntime;
|
||||
} else {
|
||||
super.update(delta);
|
||||
}
|
||||
t = (double) (elapsedTime - i*lag) / (double) anims.get(i).getRuntime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
synchronized( anims ) {
|
||||
for( Animation<? extends Shape> anim: anims ) {
|
||||
anim.interpolate(e);
|
||||
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
|
||||
public void initialize() {
|
||||
synchronized( anims ) {
|
||||
for( Animation<? extends Shape> anim: anims ) {
|
||||
anim.initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
synchronized( anims ) {
|
||||
for( Animation<? extends Shape> anim: anims ) {
|
||||
anim.finish();
|
||||
}
|
||||
}
|
||||
public void animate( double e ) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
public void interpolate( double e ) {
|
||||
public void animate( double e ) {
|
||||
object.setFillColor(new Color(fill, (int) Constants.interpolate(fillAlpha, tAlpha, e)));
|
||||
object.setStrokeColor(new Color(stroke, (int) Constants.interpolate(strokeAlpha, tAlpha, e)));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class FillAnimation extends Animation<Shape> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
public void animate( double e ) {
|
||||
object.setFillColor(Color.interpolate(oFill, tFill, e));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class MorphAnimation extends Animation<Shape> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
public void animate( double e ) {
|
||||
object.setX(Constants.interpolate(original.getX(), target.getX(), e));
|
||||
object.setY(Constants.interpolate(original.getY(), target.getY(), e));
|
||||
object.setFillColor(Color.interpolate(original.getFillColor(), target.getFillColor(), e));
|
||||
|
||||
@@ -31,7 +31,7 @@ public class MoveAnimation extends Animation<Shape> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
public void animate( double e ) {
|
||||
object.setX(Constants.interpolate(oX, tX, e));
|
||||
object.setY(Constants.interpolate(oY, tY, e));
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class RotateAnimation extends Animation<Shape> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
public void animate( double e ) {
|
||||
object.rotateTo(Constants.interpolate(oA, tA, e));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class StrokeAnimation extends Animation<Shape> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interpolate( double e ) {
|
||||
public void animate( double 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