mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 14:43:33 +02:00
Animationssystem erweitert
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package schule.ngb.zm;
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import schule.ngb.zm.anim.Easing;
|
||||||
import schule.ngb.zm.util.ImageLoader;
|
import schule.ngb.zm.util.ImageLoader;
|
||||||
import schule.ngb.zm.util.Noise;
|
import schule.ngb.zm.util.Noise;
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ import java.awt.event.KeyEvent;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basisklasse für die meisten Objekte der Zeichemaschine, die von Nutzern
|
* Basisklasse für die meisten Objekte der Zeichemaschine, die von Nutzern
|
||||||
@@ -110,6 +112,10 @@ public class Constants {
|
|||||||
*/
|
*/
|
||||||
public static final int STD_BUFFER = 10;
|
public static final int STD_BUFFER = 10;
|
||||||
|
|
||||||
|
public static int DEFAULT_ANIM_RUNTIME = 1000;
|
||||||
|
|
||||||
|
public static DoubleUnaryOperator DEFAULT_EASING = Easing.DEFAULT_EASING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option für durchgezogene Konturen und Linien.
|
* Option für durchgezogene Konturen und Linien.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1408,6 +1408,10 @@ public class Zeichenmaschine extends Constants {
|
|||||||
if( state == Options.AppState.RUNNING ) {
|
if( state == Options.AppState.RUNNING ) {
|
||||||
state = Options.AppState.UPDATING;
|
state = Options.AppState.UPDATING;
|
||||||
update(delta);
|
update(delta);
|
||||||
|
|
||||||
|
for( Layer l: canvas.getLayers() ) {
|
||||||
|
l.update(delta);
|
||||||
|
}
|
||||||
state = Options.AppState.RUNNING;
|
state = Options.AppState.RUNNING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,131 @@
|
|||||||
package schule.ngb.zm.anim;
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.Updatable;
|
||||||
import schule.ngb.zm.events.EventDispatcher;
|
import schule.ngb.zm.events.EventDispatcher;
|
||||||
|
import schule.ngb.zm.tasks.FrameSynchronizedTask;
|
||||||
|
import schule.ngb.zm.tasks.TaskRunner;
|
||||||
|
|
||||||
public class Animation {
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public abstract class Animation<T> implements Updatable {
|
||||||
|
|
||||||
|
protected int runtime;
|
||||||
|
|
||||||
|
protected int elapsed_time = 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 = easing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Animation( int runtime ) {
|
||||||
|
this.runtime = runtime;
|
||||||
|
this.easing = Constants.DEFAULT_EASING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Animation( int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
this.runtime = runtime;
|
||||||
|
this.easing = 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();
|
||||||
|
elapsed_time = 0;
|
||||||
|
running = true;
|
||||||
|
finished = false;
|
||||||
|
interpolate(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));
|
||||||
|
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 ) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1);
|
||||||
|
} catch( InterruptedException ex ) {
|
||||||
|
// Keep waiting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
elapsed_time += (int) (delta * 1000);
|
||||||
|
if( elapsed_time > runtime )
|
||||||
|
elapsed_time = runtime;
|
||||||
|
|
||||||
|
double t = (double) elapsed_time / (double) runtime;
|
||||||
|
if( t >= 1.0 ) {
|
||||||
|
running = false;
|
||||||
|
stop();
|
||||||
|
} else {
|
||||||
|
interpolate(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
|
||||||
|
*/
|
||||||
|
public abstract void interpolate( double e );
|
||||||
|
|
||||||
EventDispatcher<Animation, AnimationListener> eventDispatcher;
|
EventDispatcher<Animation, AnimationListener> eventDispatcher;
|
||||||
|
|
||||||
|
|||||||
36
src/main/java/schule/ngb/zm/anim/AnimationFacade.java
Normal file
36
src/main/java/schule/ngb/zm/anim/AnimationFacade.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.util.Validator;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class AnimationFacade<S> extends Animation<S> {
|
||||||
|
|
||||||
|
private Animation<S> anim;
|
||||||
|
|
||||||
|
public AnimationFacade( Animation<S> anim, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
this.anim = Validator.requireNotNull(anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public S getAnimationTarget() {
|
||||||
|
return anim.getAnimationTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( double e ) {
|
||||||
|
anim.interpolate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
anim.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
anim.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
76
src/main/java/schule/ngb/zm/anim/AnimationGroup.java
Normal file
76
src/main/java/schule/ngb/zm/anim/AnimationGroup.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class AnimationGroup extends Animation<Shape> {
|
||||||
|
|
||||||
|
Animation<? extends Shape>[] anims;
|
||||||
|
|
||||||
|
private boolean overrideRuntime = false;
|
||||||
|
|
||||||
|
|
||||||
|
public AnimationGroup( DoubleUnaryOperator easing, Animation<? extends Shape>... anims ) {
|
||||||
|
super(easing);
|
||||||
|
this.anims = anims;
|
||||||
|
|
||||||
|
int maxRuntime = Arrays.stream(this.anims).mapToInt((a) -> a.getRuntime()).reduce(0, Integer::max);
|
||||||
|
setRuntime(maxRuntime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimationGroup( int runtime, DoubleUnaryOperator easing, Animation<? extends Shape>... anims ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
this.anims = anims;
|
||||||
|
overrideRuntime = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
if( overrideRuntime ) {
|
||||||
|
synchronized( anims ) {
|
||||||
|
for( Animation<? extends Shape> anim: anims ) {
|
||||||
|
if( anim.isActive() ) {
|
||||||
|
anim.update(delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.update(delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( double e ) {
|
||||||
|
synchronized( anims ) {
|
||||||
|
for( Animation<? extends Shape> anim: anims ) {
|
||||||
|
anim.interpolate(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import schule.ngb.zm.Color;
|
|||||||
import schule.ngb.zm.Constants;
|
import schule.ngb.zm.Constants;
|
||||||
import schule.ngb.zm.Vector;
|
import schule.ngb.zm.Vector;
|
||||||
import schule.ngb.zm.tasks.FrameSynchronizedTask;
|
import schule.ngb.zm.tasks.FrameSynchronizedTask;
|
||||||
|
import schule.ngb.zm.tasks.FramerateLimitedTask;
|
||||||
import schule.ngb.zm.tasks.TaskRunner;
|
import schule.ngb.zm.tasks.TaskRunner;
|
||||||
import schule.ngb.zm.util.Log;
|
import schule.ngb.zm.util.Log;
|
||||||
import schule.ngb.zm.util.Validator;
|
import schule.ngb.zm.util.Validator;
|
||||||
@@ -158,7 +159,7 @@ public class Animations {
|
|||||||
} while( t < 1.0 );
|
} while( t < 1.0 );
|
||||||
stepper.accept(easing.applyAsDouble(1.0));
|
stepper.accept(easing.applyAsDouble(1.0));
|
||||||
}, target);*/
|
}, target);*/
|
||||||
return TaskRunner.run(new FrameSynchronizedTask() {
|
return TaskRunner.run(new FramerateLimitedTask() {
|
||||||
double t = 0.0;
|
double t = 0.0;
|
||||||
final long starttime = System.currentTimeMillis();
|
final long starttime = System.currentTimeMillis();
|
||||||
@Override
|
@Override
|
||||||
@@ -185,15 +186,36 @@ public class Animations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public static <T> Future<?> animate( Animation<T> animation ) {
|
public static <T> Future<?> animate( Animation<T> animation ) {
|
||||||
animation.start();
|
return TaskRunner.run(new FramerateLimitedTask() {
|
||||||
return null;
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
animation.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
animation.update(delta);
|
||||||
|
running = animation.isActive();
|
||||||
|
}
|
||||||
|
}, animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Future<?> animate( Animation<T> animation, DoubleUnaryOperator easing ) {
|
public static <T> Future<Animation<T>> animate( Animation<T> animation, DoubleUnaryOperator easing ) {
|
||||||
animation.start(easing);
|
final AnimationFacade<T> facade = new AnimationFacade<>(animation, animation.getRuntime(), easing);
|
||||||
return null;
|
return TaskRunner.run(new FramerateLimitedTask() {
|
||||||
}*/
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
facade.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
facade.update(delta);
|
||||||
|
running = facade.isActive();
|
||||||
|
}
|
||||||
|
}, animation);
|
||||||
|
}
|
||||||
|
|
||||||
public static final Log LOG = Log.getLogger(Animations.class);
|
public static final Log LOG = Log.getLogger(Animations.class);
|
||||||
|
|
||||||
|
|||||||
33
src/main/java/schule/ngb/zm/anim/FillAnimation.java
Normal file
33
src/main/java/schule/ngb/zm/anim/FillAnimation.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class FillAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object;
|
||||||
|
|
||||||
|
private Color oFill, tFill;
|
||||||
|
|
||||||
|
public FillAnimation( Shape object, Color newFill, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
|
||||||
|
this.object = object;
|
||||||
|
oFill = object.getFillColor();
|
||||||
|
tFill = newFill;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( double e ) {
|
||||||
|
object.setFillColor(Color.interpolate(oFill, tFill, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
53
src/main/java/schule/ngb/zm/anim/MorphAnimation.java
Normal file
53
src/main/java/schule/ngb/zm/anim/MorphAnimation.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.shapes.Circle;
|
||||||
|
import schule.ngb.zm.shapes.Ellipse;
|
||||||
|
import schule.ngb.zm.shapes.Rectangle;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class MorphAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object, original, target;
|
||||||
|
|
||||||
|
public MorphAnimation( Shape object, Shape target, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
|
||||||
|
this.original = object.copy();
|
||||||
|
this.object = object;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( 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));
|
||||||
|
object.setStrokeColor(Color.interpolate(original.getStrokeColor(), target.getStrokeColor(), e));
|
||||||
|
object.rotateTo(Constants.interpolate(original.getRotation(), target.getRotation(), e));
|
||||||
|
object.scale(Constants.interpolate(original.getScale(), target.getScale(), e));
|
||||||
|
object.setStrokeWeight(Constants.interpolate(original.getStrokeWeight(), target.getStrokeWeight(), e));
|
||||||
|
|
||||||
|
if( object instanceof Rectangle ) {
|
||||||
|
Rectangle r = (Rectangle)object;
|
||||||
|
r.setWidth(Constants.interpolate(original.getWidth(), target.getWidth(), e));
|
||||||
|
r.setHeight(Constants.interpolate(original.getHeight(), target.getHeight(), e));
|
||||||
|
} else if( object instanceof Circle ) {
|
||||||
|
Circle r = (Circle)object;
|
||||||
|
r.setRadius(Constants.interpolate(original.getWidth()*.5, target.getWidth()*.5, e));
|
||||||
|
} else if( object instanceof Ellipse ) {
|
||||||
|
Ellipse r = (Ellipse)object;
|
||||||
|
r.setWidth(Constants.interpolate(original.getWidth(), target.getWidth(), e));
|
||||||
|
r.setHeight(Constants.interpolate(original.getHeight(), target.getHeight(), e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
39
src/main/java/schule/ngb/zm/anim/MoveAnimation.java
Normal file
39
src/main/java/schule/ngb/zm/anim/MoveAnimation.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.shapes.Circle;
|
||||||
|
import schule.ngb.zm.shapes.Ellipse;
|
||||||
|
import schule.ngb.zm.shapes.Rectangle;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class MoveAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object;
|
||||||
|
|
||||||
|
private double oX, oY, tX, tY;
|
||||||
|
|
||||||
|
public MoveAnimation( Shape object, double x, double y, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
|
||||||
|
this.object = object;
|
||||||
|
oX = object.getX();
|
||||||
|
oY = object.getY();
|
||||||
|
tX = x;
|
||||||
|
tY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( double e ) {
|
||||||
|
object.setX(Constants.interpolate(oX, tX, e));
|
||||||
|
object.setY(Constants.interpolate(oY, tY, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
src/main/java/schule/ngb/zm/anim/RotateAnimation.java
Normal file
32
src/main/java/schule/ngb/zm/anim/RotateAnimation.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class RotateAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object;
|
||||||
|
|
||||||
|
private double oA, tA;
|
||||||
|
|
||||||
|
public RotateAnimation( Shape object, double angle, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
|
||||||
|
this.object = object;
|
||||||
|
oA = object.getRotation();
|
||||||
|
tA = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( double e ) {
|
||||||
|
object.rotateTo(Constants.interpolate(oA, tA, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
src/main/java/schule/ngb/zm/anim/StrokeAnimation.java
Normal file
32
src/main/java/schule/ngb/zm/anim/StrokeAnimation.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package schule.ngb.zm.anim;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
import schule.ngb.zm.shapes.Shape;
|
||||||
|
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
|
public class StrokeAnimation extends Animation<Shape> {
|
||||||
|
|
||||||
|
private Shape object;
|
||||||
|
|
||||||
|
private Color oFill, tFill;
|
||||||
|
|
||||||
|
public StrokeAnimation( Shape object, Color newStroke, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
super(runtime, easing);
|
||||||
|
|
||||||
|
this.object = object;
|
||||||
|
oFill = object.getFillColor();
|
||||||
|
tFill = newStroke;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape getAnimationTarget() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interpolate( double e ) {
|
||||||
|
object.setStrokeColor(Color.interpolate(oFill, tFill, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,25 +1,35 @@
|
|||||||
package schule.ngb.zm.shapes;
|
package schule.ngb.zm.shapes;
|
||||||
|
|
||||||
import schule.ngb.zm.Layer;
|
import schule.ngb.zm.Layer;
|
||||||
|
import schule.ngb.zm.anim.Animation;
|
||||||
|
import schule.ngb.zm.anim.AnimationFacade;
|
||||||
|
import schule.ngb.zm.anim.Easing;
|
||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
public class ShapesLayer extends Layer {
|
public class ShapesLayer extends Layer {
|
||||||
|
|
||||||
protected boolean clearBeforeDraw = true;
|
protected boolean clearBeforeDraw = true;
|
||||||
|
|
||||||
private LinkedList<Shape> shapes;
|
private List<Shape> shapes;
|
||||||
|
|
||||||
|
private List<Animation<? extends Shape>> animations;
|
||||||
|
|
||||||
public ShapesLayer() {
|
public ShapesLayer() {
|
||||||
super();
|
super();
|
||||||
shapes = new LinkedList<Shape>();
|
shapes = new LinkedList<>();
|
||||||
|
animations = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShapesLayer( int width, int height ) {
|
public ShapesLayer( int width, int height ) {
|
||||||
super(width, height);
|
super(width, height);
|
||||||
shapes = new LinkedList<Shape>();
|
shapes = new LinkedList<>();
|
||||||
|
animations = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Shape getShape( int index ) {
|
public Shape getShape( int index ) {
|
||||||
@@ -103,6 +113,33 @@ public class ShapesLayer extends Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <S extends Shape> void play( Animation<S> anim ) {
|
||||||
|
this.animations.add(anim);
|
||||||
|
anim.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S extends Shape> void play( Animation<S> anim, int runtime ) {
|
||||||
|
play(anim, runtime, Easing.DEFAULT_EASING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S extends Shape> void play( Animation<S> anim, int runtime, DoubleUnaryOperator easing ) {
|
||||||
|
AnimationFacade<S> facade = new AnimationFacade<>(anim, runtime, easing);
|
||||||
|
play(facade);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
Iterator<Animation<? extends Shape>> it = animations.iterator();
|
||||||
|
while( it.hasNext() ) {
|
||||||
|
Animation<? extends Shape> anim = it.next();
|
||||||
|
anim.update(delta);
|
||||||
|
|
||||||
|
if( !anim.isActive() ) {
|
||||||
|
animations.remove(anim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw( Graphics2D pGraphics ) {
|
public void draw( Graphics2D pGraphics ) {
|
||||||
if( clearBeforeDraw ) {
|
if( clearBeforeDraw ) {
|
||||||
|
|||||||
@@ -20,17 +20,31 @@ public abstract class FrameSynchronizedTask extends Task {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
int lastTick = 0;
|
|
||||||
Object lock = Zeichenmaschine.globalSyncLock;
|
Object lock = Zeichenmaschine.globalSyncLock;
|
||||||
|
|
||||||
|
// start of thread in ms
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
// current time in ns
|
||||||
|
long beforeTime = System.nanoTime();
|
||||||
|
// store for deltas
|
||||||
|
long overslept = 0L;
|
||||||
|
// internal counters for tick and runtime
|
||||||
|
int _tick = 0;
|
||||||
|
|
||||||
|
double delta = 0.0;
|
||||||
|
|
||||||
while( running ) {
|
while( running ) {
|
||||||
lastTick = Constants.tick;
|
// delta in seconds
|
||||||
this.update(lastTick);
|
delta = (System.nanoTime() - beforeTime) / 1000000000.0;
|
||||||
|
beforeTime = System.nanoTime();
|
||||||
|
|
||||||
|
_tick = Constants.tick;
|
||||||
|
this.update(delta);
|
||||||
|
|
||||||
synchronized( lock ) {
|
synchronized( lock ) {
|
||||||
while( lastTick >= Constants.tick ) {
|
while( _tick >= Constants.tick ) {
|
||||||
try {
|
try {
|
||||||
lock.wait();
|
lock.wait();
|
||||||
} catch( InterruptedException e ) {
|
} catch( InterruptedException e ) {
|
||||||
@@ -46,10 +60,5 @@ public abstract class FrameSynchronizedTask extends Task {
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isActive() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user