@Override public void load() { // Add background and set up blend mode FilledSprite background; Group particleLayer = new Group(); if (nextBlendMode == BlendMode.Add()) { background = new FilledSprite(prevBackgroundColor); background.fillColor.animateTo(BLACK, 500); particleLayer.setBlendMode(nextBlendMode); prevBackgroundColor = BLACK; nextBlendMode = BlendMode.Multiply(); } else { background = new FilledSprite(prevBackgroundColor); background.fillColor.animateTo(WHITE, 500); particleLayer.setBlendMode(nextBlendMode); prevBackgroundColor = WHITE; nextBlendMode = BlendMode.Add(); } add(background); particleLayer.alpha.set(0); addLayer(particleLayer); // Add particles for (int i = 0; i < particles; i++) { int[] x = new int[moves]; int[] y = new int[moves]; for (int j = 0; j < moves; j++) { x[j] = rand(border, Stage.getWidth() - border * 2); y[j] = rand(border, Stage.getHeight() - border * 2); } Timeline moveTimeline = new Timeline(); Sprite sprite = makeParticle(); particleLayer.add(sprite); int startTime = 0; for (int j = 0; j < moves; j++) { int lastX = x[j]; int lastY = y[j]; int newX = x[(j + 1) % moves]; int newY = y[(j + 1) % moves]; int dx = newX - lastX; int dy = newY - lastY; int moveDur = (int) (Math.sqrt(dx * dx + dy * dy) * 50); moveTimeline .at(startTime) .move(sprite, lastX, lastY, newX, newY, moveDur, Easing.ELASTIC_IN_OUT); startTime += moveDur; } moveTimeline.loopForever(); addTimeline(moveTimeline); // Create 3 mirror objects Sprite mirror = makeParticle(); mirror.x.bindTo(mirrorX(sprite)); mirror.y.bindTo(mirrorY(sprite)); particleLayer.add(mirror); mirror = makeParticle(); mirror.x.bindTo(mirrorX(sprite)); mirror.y.bindTo(sprite.y); particleLayer.add(mirror); mirror = makeParticle(); mirror.x.bindTo(sprite.x); mirror.y.bindTo(mirrorY(sprite)); particleLayer.add(mirror); } // Transition to the next blend mode int changeTime = 30000; Timeline timeline = new Timeline(); timeline.at(500).animate(particleLayer.alpha, 0, 255, 2000); timeline.at(changeTime - 2500).animate(particleLayer.alpha, 255, 0, 2000); timeline.add( new TimelineEvent(changeTime) { public void run() { reload(); } }); addTimeline(timeline); }
public class Compositing extends Scene2D { BlendMode nextBlendMode = BlendMode.Add(); int prevBackgroundColor = BLACK; int border = 100; int particles = 4; int moves = 4; @Override public void load() { // Add background and set up blend mode FilledSprite background; Group particleLayer = new Group(); if (nextBlendMode == BlendMode.Add()) { background = new FilledSprite(prevBackgroundColor); background.fillColor.animateTo(BLACK, 500); particleLayer.setBlendMode(nextBlendMode); prevBackgroundColor = BLACK; nextBlendMode = BlendMode.Multiply(); } else { background = new FilledSprite(prevBackgroundColor); background.fillColor.animateTo(WHITE, 500); particleLayer.setBlendMode(nextBlendMode); prevBackgroundColor = WHITE; nextBlendMode = BlendMode.Add(); } add(background); particleLayer.alpha.set(0); addLayer(particleLayer); // Add particles for (int i = 0; i < particles; i++) { int[] x = new int[moves]; int[] y = new int[moves]; for (int j = 0; j < moves; j++) { x[j] = rand(border, Stage.getWidth() - border * 2); y[j] = rand(border, Stage.getHeight() - border * 2); } Timeline moveTimeline = new Timeline(); Sprite sprite = makeParticle(); particleLayer.add(sprite); int startTime = 0; for (int j = 0; j < moves; j++) { int lastX = x[j]; int lastY = y[j]; int newX = x[(j + 1) % moves]; int newY = y[(j + 1) % moves]; int dx = newX - lastX; int dy = newY - lastY; int moveDur = (int) (Math.sqrt(dx * dx + dy * dy) * 50); moveTimeline .at(startTime) .move(sprite, lastX, lastY, newX, newY, moveDur, Easing.ELASTIC_IN_OUT); startTime += moveDur; } moveTimeline.loopForever(); addTimeline(moveTimeline); // Create 3 mirror objects Sprite mirror = makeParticle(); mirror.x.bindTo(mirrorX(sprite)); mirror.y.bindTo(mirrorY(sprite)); particleLayer.add(mirror); mirror = makeParticle(); mirror.x.bindTo(mirrorX(sprite)); mirror.y.bindTo(sprite.y); particleLayer.add(mirror); mirror = makeParticle(); mirror.x.bindTo(sprite.x); mirror.y.bindTo(mirrorY(sprite)); particleLayer.add(mirror); } // Transition to the next blend mode int changeTime = 30000; Timeline timeline = new Timeline(); timeline.at(500).animate(particleLayer.alpha, 0, 255, 2000); timeline.at(changeTime - 2500).animate(particleLayer.alpha, 255, 0, 2000); timeline.add( new TimelineEvent(changeTime) { public void run() { reload(); } }); addTimeline(timeline); } Sprite makeParticle() { CoreImage image = CoreImage.load("particle.png"); int color = hue(rand(0, 255)); final ImageSprite sprite = new ImageSprite(image.tint(color), 0, 0); sprite.setAnchor(0.5, 0.5); sprite.pixelSnapping.set(true); Blur blur = new Blur(8); blur.quality.set(1); blur.radius.bindTo( new BindFunction() { public Number f() { int w = Stage.getWidth() / 2; double f = 1 - Math.abs(w - sprite.x.get()) / w; if (f < 0.10) { return 0; } else { return 16 * (f - 0.10); } } }); sprite.setFilter(blur); return sprite; } BindFunction mirrorX(final Sprite source) { return new BindFunction() { public Number f() { return (Stage.getWidth() - source.x.get()); } }; } BindFunction mirrorY(final Sprite source) { return new BindFunction() { public Number f() { return (Stage.getHeight() - source.y.get()); } }; } }