GIF example of what it looks like in action:
(400 frames total; 200 different frames in order, and in reverse for a seamless animation.)
The class has a main method which shows how to use it, but beware: It's undocumented.
PspBackground.java
Code: Select all
package misc;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.CubicCurve2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class PspBackground {
private List<Curve> curves = new ArrayList<Curve>();
private Dimension size;
private Timer timer;
private BufferedImage image;
private List<ActionListener> repaintListeners = new ArrayList<ActionListener>();
public PspBackground(Dimension size) {
this.size = new Dimension(size);
timer = new Timer(25, new ActionListener() {
public void actionPerformed(ActionEvent e) {
image = new BufferedImage(
(int) PspBackground.this.size.getWidth(),
(int) PspBackground.this.size.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2.setStroke(new BasicStroke(4F));
for (Curve c : curves) {
for (int i = 100; i > 0; i--) {
Color color = c.getColor();
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
g2.setColor(new Color(r, g, b, i));
g2.draw(c.getCurve());
g2.translate(0, 1);
}
g2.translate(0, -100);
c.update();
}
g2.dispose();
timer.setDelay(rand(1, 125));
for (ActionListener a : repaintListeners) {
a.actionPerformed(new ActionEvent(PspBackground.this,
ActionEvent.ACTION_PERFORMED, "repaint"));
}
}
});
timer.start();
}
private int rand(double lo, double hi) {
return (int) (lo + Math.random() * (1 + hi - lo));
}
public void setCurve(Curve c) {
CubicCurve2D curve2d = c.getCurve();
double diffy1 = curve2d.getCtrlY1() - curve2d.getY1();
double diffy2 = curve2d.getCtrlY2() - curve2d.getY2();
double qh = size.getHeight() * .25;
double q2h = size.getHeight() * .5;
double qw = size.getWidth() * .25;
double q3w = size.getWidth() * .75;
double x1 = 0;
double y1 = q2h;
double ctrlx1 = qw;
double ctrly1 = q2h + diffy1;
double ctrlx2 = q3w;
double ctrly2 = q2h + diffy2;
double x2 = size.getWidth();
double y2 = q2h;
double minctrlx1 = qw - rand(0, qw);
double minctrly1 = q2h - rand(0, qh);
double maxctrlx1 = qw + rand(0, qw);
double maxctrly1 = q2h + rand(0, qh);
double minctrlx2 = q3w - rand(0, qw);
double minctrly2 = q2h - rand(0, qh);
double maxctrlx2 = q3w + rand(0, qw);
double maxctrly2 = q2h + rand(0, qh);
double deltax1 = c.getDeltaX1();
double deltay1 = c.getDeltaY1();
double deltax2 = c.getDeltaX2();
double deltay2 = c.getDeltaY2();
curve2d.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
c.setCurve(curve2d,
minctrlx1, minctrly1,
maxctrlx1, maxctrly1,
minctrlx2, minctrly2,
maxctrlx2, maxctrly2,
deltax1, deltay1,
deltax2, deltay2,
c.getColor());
}
public BufferedImage getImage() {
return image;
}
public Dimension getSize() {
return new Dimension(size);
}
public List<Curve> getCurves() {
return curves;
}
public List<ActionListener> getRepaintListeners() {
return repaintListeners;
}
public void setSize(Dimension size) {
this.size = new Dimension(size);
}
public void addRepaintListener(ActionListener repaintListener) {
repaintListeners.add(repaintListener);
}
public void removeRepaintListener(ActionListener repaintListener) {
repaintListeners.remove(repaintListener);
}
public void addCurve(Curve c) {
curves.add(c);
}
public void removeCurve(Curve c) {
curves.remove(c);
}
public static class Curve {
private CubicCurve2D curve;
private double minctrlx1;
private double minctrly1;
private double maxctrlx1;
private double maxctrly1;
private double minctrlx2;
private double minctrly2;
private double maxctrlx2;
private double maxctrly2;
private double deltax1;
private double deltay1;
private double deltax2;
private double deltay2;
private Color color;
public Curve(CubicCurve2D curve2D,
double deltax1, double deltay1,
double deltax2, double deltay2,
Color color) {
this.curve = curve2D;
this.deltax1 = deltax1;
this.deltay1 = deltay1;
this.deltax2 = deltax2;
this.deltay2 = deltay2;
this.color = color;
}
public void update() {
double x1 = curve.getX1();
double y1 = curve.getY1();
double ctrlx1 = curve.getCtrlX1();
double ctrly1 = curve.getCtrlY1();
double ctrlx2 = curve.getCtrlX2();
double ctrly2 = curve.getCtrlY2();
double x2 = curve.getX2();
double y2 = curve.getY2();
if (ctrlx1 <= minctrlx1) {
deltax1 = Math.abs(deltax1);
}
if (ctrlx1 >= maxctrlx1) {
deltax1 = -Math.abs(deltax1);
}
if (ctrly1 <= minctrly1) {
deltay1 = Math.abs(deltay1);
}
if (ctrly1 >= maxctrly1) {
deltay1 = -Math.abs(deltay1);
}
if (ctrlx2 <= minctrlx2) {
deltax2 = Math.abs(deltax2);
}
if (ctrlx2 >= maxctrlx2) {
deltax2 = -Math.abs(deltax2);
}
if (ctrly2 <= minctrly2) {
deltay2 = Math.abs(deltay2);
}
if (ctrly2 >= maxctrly2) {
deltay2 = -Math.abs(deltay2);
}
ctrlx1 += deltax1;
ctrly1 += deltay1;
ctrlx2 += deltax2;
ctrly2 += deltay2;
curve.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
}
public void setCurve(CubicCurve2D curve2d,
double minCtrlX1, double minCtrlY1,
double maxCtrlX1, double maxCtrlY1,
double minCtrlX2, double minCtrlY2,
double maxCtrlX2, double maxCtrlY2,
double deltaX1, double deltaY1,
double deltaX2, double deltaY2,
Color color) {
this.curve = curve2d;
this.minctrlx1 = minCtrlX1;
this.minctrly1 = minCtrlY1;
this.maxctrlx1 = maxCtrlX1;
this.maxctrly1 = maxCtrlY1;
this.minctrlx2 = minCtrlX2;
this.minctrly2 = minCtrlY2;
this.maxctrlx2 = maxCtrlX2;
this.maxctrly2 = maxCtrlY2;
this.deltay1 = deltaX1;
this.deltay1 = deltaY1;
this.deltax2 = deltaX2;
this.deltay2 = deltaY2;
this.color = color;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public CubicCurve2D getCurve() {
return curve;
}
public void setCurve(CubicCurve2D curve) {
this.curve = curve;
}
public double getDeltaX1() {
return deltax1;
}
public void setDeltaX1(double deltax1) {
this.deltax1 = deltax1;
}
public double getDeltaX2() {
return deltax2;
}
public void setDeltaX2(double deltax2) {
this.deltax2 = deltax2;
}
public double getDeltaY1() {
return deltay1;
}
public void setDeltaY1(double deltay1) {
this.deltay1 = deltay1;
}
public double getDeltaY2() {
return deltay2;
}
public void setDeltaY2(double deltay2) {
this.deltay2 = deltay2;
}
public double getMaxCtrlX1() {
return maxctrlx1;
}
public void setMaxCtrlX1(double maxctrlx1) {
this.maxctrlx1 = maxctrlx1;
}
public double getMaxCtrlX2() {
return maxctrlx2;
}
public void setMaxCtrlX2(double maxctrlx2) {
this.maxctrlx2 = maxctrlx2;
}
public double getMaxCtrlY1() {
return maxctrly1;
}
public void setMaxCtrlY1(double maxctrly1) {
this.maxctrly1 = maxctrly1;
}
public double getMaxCtrlY2() {
return maxctrly2;
}
public void setMaxCtrlY2(double maxctrly2) {
this.maxctrly2 = maxctrly2;
}
public double getMinCtrlX1() {
return minctrlx1;
}
public void setMinCtrlX1(double minctrlx1) {
this.minctrlx1 = minctrlx1;
}
public double getMinCtrlX2() {
return minctrlx2;
}
public void setMinCtrlX2(double minctrlx2) {
this.minctrlx2 = minctrlx2;
}
public double getMinCtrlY1() {
return minctrly1;
}
public void setMinCtrlY1(double minctrly1) {
this.minctrly1 = minctrly1;
}
public double getMinCtrlY2() {
return minctrly2;
}
public void setMinCtrlY2(double minctrly2) {
this.minctrly2 = minctrly2;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("PspBackground");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Dimension d = new Dimension(250, 250);
final PspBackground background = new PspBackground(d);
Curve c1 = new Curve(new CubicCurve2D.Double(),
1, -1, 1, 1, Color.CYAN);
Curve c2 = new Curve(new CubicCurve2D.Double(),
1, -1, 1, 1, Color.CYAN.brighter());
background.setCurve(c1);
background.setCurve(c2);
background.addCurve(c1);
background.addCurve(c2);
final JPanel c = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
GradientPaint p = new GradientPaint(0, 0, Color.BLUE,
0, getHeight(), new Color(20, 170, 255));
g2.setPaint(p);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.drawImage(background.getImage(), 0, 0,
getWidth(), getHeight(), this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(d);
}
};
background.addRepaintListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
c.repaint();
}
});
f.add(c);
f.pack();
f.setVisible(true);
}
});
}
}