====== Showcase: "Fliegende Kugeln" ====== Im Folgenden ist die Implementierung "fliegender Kugeln" aufgeführt. Dabei wird eine Menge von Kugeln mit konstanter Geschwindigkeit bewegt. Kollidiert eine Kugel mit dem Fensterrand oder einer anderen Kugel, so prallt diese im Einfallswinkel der Kollision vom getroffenen Objekt ab. Die Lösung umfasst die zwei Klassen Bullet (Kugel) und BulletsMover. Zugegeben, die physikalische Modellierung der Kollision ist verbesserungswürdig ;-) ===== Klasse Bullet ===== import java.awt.Point; import java.util.ArrayList; import geofasc.swing.Circle; import geofasc.swing.tool.Calculator; import geofasc.swing.tool.Canvas; /** * Eine Bullet kann sich mit einer Geschwindigkeit von 5 Pixeln * in eine bestimmbare Richtung bewegen. Sie ist ein {@link Circle} und * wird auf einer {@link Canvas} visualisiert. * */ public class Bullet extends Circle { private static final int sVelocity = 5; // Konstante Geschwindigkeit aller Bullets in Pixeln private Canvas mCanvas; private ArrayList mNeighbours; // Liste benachbarter Bullets /** * Erzeugt eine neue Bullet bullet. * * @param x die x-Koordinate von bullet bez. der canvas * @param y die y-Koordinate von bullet bez. der canvas * @param diameter der Radius des Kreises zur Visualisierung von bullet * @param direction die initiale Richtung von bullet * @param canvas die Zeichenflaeche, die bullet visualisiert */ public Bullet(int x, int y, int diameter, double direction, Canvas canvas) { super(x, y, diameter); setFigureDirection(direction); mCanvas = canvas; mCanvas.add(this); mNeighbours = new ArrayList(); } /** * Bewegt diese bullet um 5 Pixel abhängig * von ihrer Bewegungsrichtung. */ public void move() { int x = getFigureLocationX(); int y = getFigureLocationY(); double dir = getFigureDirection(); if (y <= 0 || (y + getFigureHeight()) >= mCanvas.getHeight()) setFigureDirection(360 - dir); if (x <= 0 || (x + getFigureWidth()) >= mCanvas.getWidth()) setFigureDirection(180 - dir); for (Bullet b : mNeighbours) { if (hits(b)) { setFigureDirection(dir - 180); } } moveFigureLocationBy(sVelocity); } /** * Fuegt die Nachbarbullet b der Liste von Nachbarbullets dieser * bullet hinzu. * * @param b die Nachbarbullet */ public void addNeighbour(Bullet b) { if (b != null && !mNeighbours.contains(b)) mNeighbours.add(b); } /** * Gibt den Mittelpunkt des dieser bullet visualisierenden * Kreises wieder. */ public Point getCenter() { return new Point(getFigureLocationX() + getRadius(), getFigureLocationY() + getRadius()); } /** * Prueft fuer diese bullet, ob sie mit der Bullet b * kollidiert. * * @param b die Nachbarbullet * @return true oder false */ public boolean hits(Bullet b) { if (b == null) return false; else { Point m1 = getCenter(); Point m2 = b.getCenter(); Calculator c = new Calculator(); return (c.sqrt(c.square(m1.x - m2.x) + c.square(m1.y - m2.y)) <= (getRadius() + b .getRadius())); } } /** * Entfernt die Nachbarbullet b aus der Liste von Nachbarbullets dieser * bullet. * * @param b die Nachbarbullet */ public void removeNeighbour(Bullet b) { mNeighbours.remove(b); } } ===== Klasse BulletsMover ===== import geofasc.swing.tool.Calculator; import geofasc.swing.tool.Canvas; import geofasc.swing.tool.Frame; import javax.swing.SwingUtilities; /** * Ein BulletsMover stellt ein Hauptprogramm dar, * in dem mehrere {@link Bullet}s erzeugt, bewegt und dargestellt * werden. * */ public class BulletsMover { private Bullet[] mBullets; private Thread mMovingThread; // Thread fuer die nebenlaeufige Bewegung aller Bullets private Frame mFrame; /** * Erzeugt einen neuen BulletsMover. */ public BulletsMover() { mBullets = new Bullet[20]; mFrame = new Frame("Bullets"); mMovingThread = null; init(); mFrame.setCenterLocation(); mFrame.setVisible(true); } /** * Fuehrt diverse initiale Operationen aus. */ private void init() { Canvas canvas = mFrame.getCanvas(); double direction = 13; int x, y, diameter; Calculator calc = new Calculator(); for (int i = 0; i < mBullets.length; i++, direction += 11) { x = calc.randomInt(10, 620); y = calc.randomInt(20, 460); diameter = calc.randomInt(5, 20); mBullets[i] = new Bullet(x, y, diameter, direction, canvas); } for (int i = 0; i < mBullets.length; i++) { for (int j = 0; j < mBullets.length; j++) { if (i != j) mBullets[i].addNeighbour(mBullets[j]); } } } /** * Erzeugt einen Thread, in dem alle Bullets nebenlaeufig bewegt werden. */ public void move() { if (mMovingThread == null) { mMovingThread = new Thread() { @Override public void run() { try { while (true) { if (isInterrupted()) break; for (Bullet bullet : mBullets) { bullet.move(); } sleep(50); } }// try catch (Exception e) { } } }; mMovingThread.start(); } } /** * Stoppt die nebenlaeufige Bewegung der Bullets. */ public void stop() { if (mMovingThread != null) { mMovingThread.interrupt(); mMovingThread = null; } } /** * Hauptmethode zum Ausfuehren des Programms. */ public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { BulletsMover bm = new BulletsMover(); bm.move(); } }); } }