
Animacja „Rój owadów” podążających za kursorem myszy
Pomysł tej animacji nie był moim pomysłem. Inspiracją był rój owadów przedstawiony w książce: Bhangal S., 2000. Flash 5. ActionScript. Podstawy, Helion, rozdz. 10. Animacja w ActionScript różni się tak bardzo od animacji w języku Java, że aplikacja została (oczywiście) napisana od nowa.
Uwagi do wykonania
Ciało owada Body implementuje Shape.
Klasa Insect wykorzystuje klasę Body do stworzenia całego owada i określenia parametrów jego ruchu. Każdy owad jest obiektem implementującym Runnable. Jednym słowem żyje na swój własny sposób, w swoim własnym wątku.
Klasa Swarm tworzy rój owadów i środowisko życia dla nich.
Klasa Util zawiera parę potrzebnych metod.
Klasa Main uruchamia aplikację.
Klasy
Klasa Body
package swarm;
import java.awt.*;
import java.awt.geom.*;
public class Body implements Shape {
private final GeneralPath path;
public Body(float x, float y, float w, float h) {
path = new GeneralPath();
path.moveTo(x, y);
path.lineTo(x + w / 2f, y + 2f * h / 3f);
path.lineTo(x + w, y);
path.moveTo(x + w / 4f, y + h);
path.lineTo(x + w / 2f, y + 2f * h / 3f);
path.lineTo(x + 3f / 4f * w, y + h);
}
@Override
public boolean contains(Point2D p) {
return path.contains(p);
}
@Override
public boolean contains(Rectangle2D r) {
return path.contains(r);
}
@Override
public boolean contains(double x, double y) {
return path.contains(x, y);
}
@Override
public boolean contains(double x, double y, double w, double h) {
return path.contains(x, y, w, h);
}
@Override
public Rectangle getBounds() {
return path.getBounds();
}
@Override
public Rectangle2D getBounds2D() {
return path.getBounds2D();
}
@Override
public PathIterator getPathIterator(AffineTransform at) {
return path.getPathIterator(at);
}
@Override
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return path.getPathIterator(at, flatness);
}
@Override
public boolean intersects(Rectangle2D r) {
return path.intersects(r);
}
@Override
public boolean intersects(double x, double y, double w, double h) {
return path.intersects(x, y, w, h);
}
}
Klasa Insect
package swarm;
import java.awt.*;
import javax.swing.*;
public class Insect extends JComponent implements Runnable {
private static final long serialVersionUID = -1022417174863360222L;
private static final double a = 20.0;
private static final double b = 50;
private static final double c = 2 * b;
private static final double d = 4 * b;
private static final double e = 8 * b;
private static final double f = 12 * b;
private static final double p1 = 0.8;
private static final double p2 = 0.9;
private Body body;
private double x;
private double y;
private double dx = 0;
private double dy = 0;
private double tX = 0;
private double tY = 0;
private double oTX = 0;
private double oTY = 0;
private double rX = (Math.random() * d) - c;
private double rY = (Math.random() * d) - c;
private Color color;
public Insect() {
this(Color.BLACK);
}
public Insect(Color color) {
this.color = color;
body = new Body(1, 1, 4, 3);
x = Util.randomInRange(d, f);
y = Util.randomInRange(d, f);
setBounds(0, 0, 6, 5);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(color);
g2.draw(body);
}
@Override
public void run() {
while (true) {
move(Insect.this.getParent());
this.setLocation((int) x, (int) y);
Insect.this.getParent().repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void move(Container panel) {
Point cursor = Insect.this.getParent().getMousePosition();
if (cursor != null) {
tX = cursor.getX();
tY = cursor.getY();
if ((tX == oTX) && (Math.random() > p2)) {
rX = (Math.random() * c) - b;
rY = (Math.random() * c) - b;
} else if ((tX != oTX) && (Math.random() > p1)) {
rX = (Math.random() * e) - c;
rY = (Math.random() * e) - c;
}
dx = tX - x + rX;
dy = tY - y + rY;
x = Math.round(x + dx / a);
y = Math.round(y + dy / a);
oTX = tX;
oTY = tY;
} else {
tX = oTX;
tY = oTY;
if ((tX == oTX) && (Math.random() > p2)) {
rX = (Math.random() * c) - b;
rY = (Math.random() * c) - b;
} else if ((tX != oTX) && (Math.random() > p1)) {
rX = (Math.random() * e) - d;
rY = (Math.random() * e) - d;
}
dx = tX - x + rX;
dy = tY - y + rY;
x = Math.round(x + dx / a);
y = Math.round(y + dy / a);
oTX = tX;
oTY = tY;
}
}
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
public double getThisX() {
return x;
}
public void setThisX(double thisX) {
this.x = thisX;
}
public double getThisY() {
return y;
}
public void setThisY(double thisY) {
this.y = thisY;
}
public double getDx() {
return dx;
}
public void setDx(double dx) {
this.dx = dx;
}
public double getDy() {
return dy;
}
public void setDy(double dy) {
this.dy = dy;
}
public double getTargetX() {
return tX;
}
public void setTargetX(double targetX) {
this.tX = targetX;
}
public double getTargetY() {
return tY;
}
public void setTargetY(double targetY) {
this.tY = targetY;
}
public double getOldTargetX() {
return oTX;
}
public void setOldTargetX(double oldTargetX) {
this.oTX = oldTargetX;
}
public double getOldTargetY() {
return oTY;
}
public void setOldTargetY(double oldTargetY) {
this.oTY = oldTargetY;
}
public double getRandX() {
return rX;
}
public void setRandX(double randX) {
this.rX = randX;
}
public double getRandY() {
return rY;
}
public void setRandY(double randY) {
this.rY = randY;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
Klasa Swarm
package swarm;
import java.awt.*;
import javax.swing.*;
public class Swarm extends JPanel {
private static final long serialVersionUID = 6253469964190884324L;
private int number;
public Swarm(int number) {
this.number = number;
setPreferredSize(new Dimension(Util.FRAME_SIZE, Util.FRAME_SIZE));
setLayout(null);
setBounds(0, 0, Util.FRAME_SIZE, Util.FRAME_SIZE);
for (int i = 0; i < number; i++) {
Insect insect = new Insect(Color.BLACK);
add(insect);
Thread t = new Thread(insect);
t.start();
}
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Klasa Util
package swarm;
public class Util {
private Util() {
}
public static final int FRAME_SIZE = 800;
public static int randomInRange(int min, int max) {
int random = -1;
if (min > max) {
System.out.println("pierwsza liczba musi byc mniejsza od drugiej");
} else {
random = (int) (Math.floor(Math.random() * (max - min + 1)) + min);
}
return random;
}
public static double randomInRange(double min, double max) {
double rR = -1;
if (min > max) {
System.out.println("pierwsza liczba musi byc mniejsza od drugiej");
} else {
rR = Math.floor(Math.random() * (max - min + 1)) + min;
}
return rR;
}
}
Klasa Main
package swarm;
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
private static final long serialVersionUID = -4401137932946724934L;
public Main() {
Swarm swarm = new Swarm(25);
setLayout(null);
setPreferredSize(new Dimension(Util.FRAME_SIZE, Util.FRAME_SIZE));
setBounds((Toolkit.getDefaultToolkit().getScreenSize().width / 2)
- (Util.FRAME_SIZE / 2), (Toolkit.getDefaultToolkit()
.getScreenSize().height / 2)
- (Util.FRAME_SIZE / 2), Util.FRAME_SIZE, Util.FRAME_SIZE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Swarm");
setResizable(false);
add(swarm);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Main());
}
}
Wynik
