mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 14:43:33 +02:00
Beispiel zu Anziehungskräften vervollständigt
This commit is contained in:
94
examples/zm_forces/Atoms.java
Normal file
94
examples/zm_forces/Atoms.java
Normal file
@@ -0,0 +1,94 @@
|
||||
import schule.ngb.zm.Zeichenmaschine;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class Atoms extends Zeichenmaschine {
|
||||
|
||||
/**
|
||||
* Liste der beweglichen Objekte in der Welt.
|
||||
*/
|
||||
private LinkedList<Mover> movers = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Liste der Gravitationsquellen in der Welt.
|
||||
*/
|
||||
private LinkedList<Attractor> attractors = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Erstellt die {@link Mover}- und {@link Attractor}-Objekte.
|
||||
*/
|
||||
public void setup() {
|
||||
addAttractor( width / 2, height / 2, 20 );
|
||||
attractors.getFirst().setMovable(false);
|
||||
attractors.getFirst().setActive(false);
|
||||
attractors.getFirst().hide();
|
||||
|
||||
addAttractor( width*.4, height*.4, 8 );
|
||||
addAttractor( width*.6, height*.6, 8 );
|
||||
|
||||
for( int i = 0; i < 10; i++ ) {
|
||||
Mover m = new Mover(random(10, width - 10), random(10, height - 10));
|
||||
movers.add(m);
|
||||
shapes.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
private void addAttractor( double pX, double pY, int pMass ) {
|
||||
Attractor a = new Attractor((int)pX, (int)pY, pMass);
|
||||
attractors.add(a);
|
||||
movers.add(a);
|
||||
shapes.add(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert die Beschleunigung der {@link Mover}-Objekte durch Anwenden
|
||||
* der einwirkenden Kräfte und aktualisiert dann die Position entsprechend
|
||||
* der Beschleunigung.
|
||||
* <p>
|
||||
* Die Position des ersten {@link Attractor} wird auf die Mausposition
|
||||
* gesetzt.
|
||||
*
|
||||
* @param delta
|
||||
*/
|
||||
public void update( double delta ) {
|
||||
// Erste Gravitationsquelle auf Mausposition setzen.
|
||||
Attractor mouseFollow = attractors.get(0);
|
||||
if( mouseFollow.isActive() ) {
|
||||
mouseFollow.moveTo(mouseX, mouseY);
|
||||
}
|
||||
|
||||
// Kräfte anwenden
|
||||
for( Attractor a : attractors ) {
|
||||
if( a.isActive() ) {
|
||||
for( Mover m : movers ) {
|
||||
if( m.isActive() ) {
|
||||
a.attract(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Position aktualisieren
|
||||
for( Mover m : movers ) {
|
||||
if( m.isActive() ) {
|
||||
m.update(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die Position und Beschleunigung aller {@link Mover}-Objekte in der
|
||||
* Welt zurück.
|
||||
*/
|
||||
public void mouseClicked() {
|
||||
for( Mover m : movers ) {
|
||||
m.moveTo(random(10, width - 10), random(10, height - 10));
|
||||
m.setVelocity(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main( String[] args ) {
|
||||
new Atoms();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +1,110 @@
|
||||
import schule.ngb.zm.Vector;
|
||||
|
||||
import schule.ngb.zm.*;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
/**
|
||||
* Gravitationsquelle in der Simulation.
|
||||
* <p>
|
||||
* Eine Gravitationsquelle zieht mit einer Anziehungskraft proportional zu
|
||||
* seiner Masse alle {@link Mover}-Objekte an. Dabei kommt die Newtonsche
|
||||
* Gravitationsformel zur Anwendung.
|
||||
* <p>
|
||||
* Ein <code>Attractor</code> ist auch ein {@link Mover} und wird von anderen
|
||||
* Gravitationsquellen beeinflusst. Dieses Verhalten kann durch Setzen von
|
||||
* <code>setMovable(false)</code> abgeschaltet werden.
|
||||
*/
|
||||
public class Attractor extends Mover {
|
||||
|
||||
private int mass = 0;
|
||||
/**
|
||||
* Gravitationskonstante
|
||||
* <p>
|
||||
* Beeinflusst die Stärke der Anziehungskraft der {@link Attractor}en.
|
||||
*/
|
||||
public static final int G = 25;
|
||||
|
||||
public Attractor( int x, int pY, int pMass ) {
|
||||
this(x, pY, pMass, new Vector());
|
||||
}
|
||||
/**
|
||||
* Ob dieser <code>Attractor</code> auch von anderen Kräften beeinflusst wird.
|
||||
*/
|
||||
private boolean movable = true;
|
||||
|
||||
public Attractor( int x, int pY, int pMass, Vector pVelocity ) {
|
||||
super(x, pY, pVelocity);
|
||||
mass = pMass;
|
||||
/**
|
||||
* Erstellt einen <code>Attractor</code> an der angegebenen Position mit der angegebenen
|
||||
* Masse.
|
||||
*
|
||||
* @param pX x-Koordinate des Objektes.
|
||||
* @param pY y-Koordinate des Objektes.
|
||||
* @param pMass Masse des Objektes.
|
||||
*/
|
||||
public Attractor( int pX, int pY, int pMass ) {
|
||||
this(pX, pY, pMass, new Vector());
|
||||
}
|
||||
|
||||
setFillColor(YELLOW);
|
||||
}
|
||||
/**
|
||||
* Erstellt einen <code>Attractor</code> an der angegebenen Position
|
||||
*
|
||||
* @param pX x-Koordinate des Objektes.
|
||||
* @param pY y-Koordinate des Objektes.
|
||||
* @param pMass Masse des Objektes.
|
||||
* @param pVelocity Initialgeschwindigkeit des Objektes.
|
||||
*/
|
||||
public Attractor( int pX, int pY, int pMass, Vector pVelocity ) {
|
||||
super(pX, pY, pVelocity);
|
||||
mass = pMass;
|
||||
|
||||
public void attract( Mover pMover ) {
|
||||
if( pMover != this ) {
|
||||
Vector force = new Vector(this.x, this.y);
|
||||
force.sub(pMover.getX(), pMover.getY()).scale(mass*Gravity.G).limit(0, 50*Gravity.G);
|
||||
pMover.applyForce(force);
|
||||
}
|
||||
}
|
||||
setFillColor(randomColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stellt ein, ob dieser <code>Attractor</code> auch von anderen Kräften
|
||||
* beeinflusst wird, oder ob er starr an einer Position bleibt.
|
||||
*
|
||||
* @param pMovable <code>true</code> oder <code>false</code>.
|
||||
*/
|
||||
public void setMovable( boolean pMovable ) {
|
||||
this.movable = pMovable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wendet die Anziehungskraft des <code>Attractor</code> auf einen
|
||||
* <code>Mover</code> an.
|
||||
*
|
||||
* @param pMover Das Objekt, das angezogen wird.
|
||||
*/
|
||||
public void attract( Mover pMover ) {
|
||||
if( pMover != this && isActive() ) {
|
||||
Vector force = new Vector(this.x, this.y);
|
||||
force.sub(pMover.getX(), pMover.getY());
|
||||
double v = G * mass / force.lenSq();
|
||||
force.setLen(v).limit(1.0, 4 * G);
|
||||
pMover.applyForce(force);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert die momentante Geschwindigkeit und Position des Objektes und
|
||||
* setzt die Beschleunigung zurück.
|
||||
*
|
||||
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
|
||||
*/
|
||||
@Override
|
||||
public void update( double delta ) {
|
||||
if( movable ) {
|
||||
super.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||
double m = 2.0*mass;
|
||||
|
||||
AffineTransform at = graphics.getTransform();
|
||||
graphics.transform(pVerzerrung);
|
||||
graphics.setColor(new java.awt.Color(255,193,64,66));
|
||||
graphics.fillOval((int)(-.5*m), (int)(-.5*m), (int)(2*getRadius()+m), (int)(2*getRadius()+m));
|
||||
graphics.setTransform(at);
|
||||
|
||||
super.draw(graphics, pVerzerrung);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,50 +1,91 @@
|
||||
import schule.ngb.zm.Vector;
|
||||
import schule.ngb.zm.Zeichenmaschine;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import schule.ngb.zm.*;
|
||||
|
||||
/**
|
||||
* Hauptklasse der Simulation.
|
||||
*/
|
||||
public class Gravity extends Zeichenmaschine {
|
||||
|
||||
|
||||
public static final int G = 1;
|
||||
|
||||
|
||||
private LinkedList<Mover> movers = new LinkedList<>();
|
||||
|
||||
private LinkedList<Attractor> attractors = new LinkedList<>();
|
||||
|
||||
public void setup(){
|
||||
for( int i = 0; i < 10; i++ ) {
|
||||
Mover m = new Mover(random(10, width-10), random(10, height-10));
|
||||
movers.add(m);
|
||||
shapes.add(m);
|
||||
}
|
||||
|
||||
attractors.add(new Attractor(width/2, height/2, 10));
|
||||
shapes.add(attractors.get(0));
|
||||
}
|
||||
|
||||
public void update( double delta ) {
|
||||
Attractor mouseFollow = attractors.get(0);
|
||||
mouseFollow.moveTo(mouseX, mouseY);
|
||||
|
||||
for( Attractor a: attractors ) {
|
||||
for( Mover m: movers ) {
|
||||
a.attract(m);
|
||||
}
|
||||
}
|
||||
|
||||
for( Mover m: movers ) {
|
||||
m.update(delta);
|
||||
}
|
||||
shapes.clear();
|
||||
}
|
||||
|
||||
public void mouseClicked() {
|
||||
for( Mover m: movers ) {
|
||||
m.moveTo(random(10, width-10), random(10, height-10));
|
||||
m.setVelocity(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Liste der beweglichen Objekte in der Welt.
|
||||
*/
|
||||
private LinkedList<Mover> movers = new LinkedList<>();
|
||||
|
||||
private final Vector gravity = new Vector(0, 6.734);
|
||||
|
||||
/**
|
||||
* Erstellt die {@link Mover}-Objekte.
|
||||
*/
|
||||
public void setup() {
|
||||
for( int i = 0; i < 4; i++ ) {
|
||||
//Mover m = new Mover(random(10, width - 10), 30);
|
||||
Mover m = new Mover(10 + (i*30), 30, 5*(i+1));
|
||||
movers.add(m);
|
||||
shapes.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert die Beschleunigung der {@link Mover}-Objekte durch Anwenden
|
||||
* der einwirkenden Kräfte und aktualisiert dann die Position entsprechend
|
||||
* der Beschleunigung.
|
||||
* <p>
|
||||
* Die Position des ersten {@link Attractor} wird auf die Mausposition
|
||||
* gesetzt.
|
||||
*
|
||||
* @param delta
|
||||
*/
|
||||
public void update( double delta ) {
|
||||
// Kräfte anwenden
|
||||
for( Mover m : movers ) {
|
||||
if( m.isActive() ) {
|
||||
m.applyForce(gravity);
|
||||
}
|
||||
}
|
||||
|
||||
// Position aktualisieren
|
||||
for( Mover m : movers ) {
|
||||
if( m.isActive() ) {
|
||||
m.update(delta);
|
||||
|
||||
// Abprallen Boden
|
||||
if( m.getY() >= height ) {
|
||||
m.setY(height-1);
|
||||
|
||||
m.getVelocity().y *= -1;
|
||||
double s = 9.0 / m.getMass();
|
||||
m.getVelocity().scale(limit(s, 0.0, 1.0));
|
||||
}
|
||||
// Abprallen rechter Rand
|
||||
if( m.getX() >= width ) {
|
||||
m.setX(width-1);
|
||||
m.getVelocity().x *= -1;
|
||||
}
|
||||
// Abprallen linker Rand
|
||||
if( m.getX() <= 0) {
|
||||
m.setX(1);
|
||||
m.getVelocity().x *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die Position und Beschleunigung aller {@link Mover}-Objekte in der
|
||||
* Welt zurück.
|
||||
*/
|
||||
public void mouseClicked() {
|
||||
for( Mover m : movers ) {
|
||||
m.moveTo(random(10, width - 10), 30);
|
||||
m.setVelocity(mouseX-m.getX(), mouseY-m.getY());
|
||||
m.getVelocity().setLen(4.0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main( String[] args ) {
|
||||
new Gravity();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,42 +1,184 @@
|
||||
import schule.ngb.zm.Updatable;
|
||||
import schule.ngb.zm.Vector;
|
||||
import schule.ngb.zm.shapes.Arrow;
|
||||
import schule.ngb.zm.shapes.Circle;
|
||||
|
||||
import schule.ngb.zm.*;
|
||||
import schule.ngb.zm.shapes.*;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
/**
|
||||
* Ein bewegliches Objekt in der Simulation.
|
||||
*
|
||||
* <code>Mover</code> werden durch Kräfte beeinflusst. Diese Kräfte können von
|
||||
* unterschiedlichen Quellen ausgehen. Die {@link Attractor}en wirken zum
|
||||
* Beispiel mit ihrer Anziehungskraft auf die <code>Mover</code> ein.
|
||||
*/
|
||||
public class Mover extends Circle implements Updatable {
|
||||
|
||||
private Vector velocity;
|
||||
private Vector acceleration = new Vector();
|
||||
/**
|
||||
* Größe der Objekte in der Simulation.
|
||||
*/
|
||||
public static final int SIZE = 10;
|
||||
|
||||
public Mover( int x, int pY ) {
|
||||
this(x, pY, new Vector());
|
||||
}
|
||||
|
||||
public Mover( int x, int pY, Vector pVelocity ) {
|
||||
super(x, pY, 10);
|
||||
this.velocity = pVelocity.copy();
|
||||
}
|
||||
|
||||
public void setVelocity(double dx, double dy) {
|
||||
velocity.set(dx, dy);
|
||||
}
|
||||
|
||||
public void applyForce( Vector force ) {
|
||||
acceleration.add(force);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void update( double delta ) {
|
||||
acceleration.scale(delta);
|
||||
velocity.add(acceleration);
|
||||
acceleration.scale(0.0);
|
||||
|
||||
this.x += velocity.x;
|
||||
this.y += velocity.y;
|
||||
/**
|
||||
* Ob die momentane Geschwindigkeit der Objekte als Pfeil dargestellt werden soll.
|
||||
*/
|
||||
public static final boolean SHOW_VELOCITY = false;
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Masse des Objektes.
|
||||
*/
|
||||
protected double mass = 10.0;
|
||||
|
||||
/**
|
||||
* Ob dieses Objekt an der Simulation beteiligt ist.
|
||||
*/
|
||||
protected boolean active = true;
|
||||
|
||||
/**
|
||||
* Momentane Geschwindigkeit des Objektes.
|
||||
*/
|
||||
private Vector velocity;
|
||||
|
||||
/**
|
||||
* Momentane Beschleunigung des Objektes.
|
||||
*/
|
||||
private Vector acceleration = new Vector();
|
||||
|
||||
/**
|
||||
* Erstellt einen Mover an der angegebenen Position mit der momentanen
|
||||
* Geschwindigkeit <code>(0, 0)</code>.
|
||||
*
|
||||
* @param pX x-Position des Objektes.
|
||||
* @param pY y-Position des Objektes.
|
||||
*/
|
||||
public Mover( int pX, int pY ) {
|
||||
this(pX, pY, new Vector());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Erstellt einen <code>Attractor</code> an der angegebenen Position mit der angegebenen
|
||||
* Masse.
|
||||
*
|
||||
* @param pX x-Koordinate des Objektes.
|
||||
* @param pY y-Koordinate des Objektes.
|
||||
* @param pMass Masse des Objektes.
|
||||
*/
|
||||
public Mover( int pX, int pY, int pMass ) {
|
||||
this(pX, pY, pMass, new Vector());
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen Mover an der angegebenen Position mit der angegebenen
|
||||
* Initialgeschwindigkeit.
|
||||
*
|
||||
* @param pX x-Position des Objektes.
|
||||
* @param pY y-Position des Objektes.
|
||||
* @param pVelocity Momentane Geschwindigkeit des Objektes.
|
||||
*/
|
||||
public Mover( int pX, int pY, Vector pVelocity ) {
|
||||
super(pX, pY, SIZE);
|
||||
velocity = pVelocity.copy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen <code>Attractor</code> an der angegebenen Position
|
||||
*
|
||||
* @param pX x-Koordinate des Objektes.
|
||||
* @param pY y-Koordinate des Objektes.
|
||||
* @param pMass Masse des Objektes.
|
||||
* @param pVelocity Initialgeschwindigkeit des Objektes.
|
||||
*/
|
||||
public Mover( int pX, int pY, int pMass, Vector pVelocity ) {
|
||||
super(pX, pY, SIZE);
|
||||
mass = pMass;
|
||||
velocity = pVelocity.copy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Masse des Objektes zurück.
|
||||
*
|
||||
* @return Die Masse des Objektes.
|
||||
*/
|
||||
public double getMass() {
|
||||
return mass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die momentane Geschwindigkeit zurück.
|
||||
* @return Die momentane Geschwindigkeit als Vektor.
|
||||
*/
|
||||
public Vector getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die momentane Geschwindigkeit des Objektes.
|
||||
*
|
||||
* @param pDx Momentane Geschwindigkeit in x-Richtung.
|
||||
* @param pDy Momentane Geschwindigkeit in y-Richtung.
|
||||
*/
|
||||
public void setVelocity( double pDx, double pDy ) {
|
||||
velocity.set(pDx, pDy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Addiert eine Kraft zur momentanen Beschleunigung des Objektes. Die
|
||||
* Beschleunigung wird einmal pro Update auf die Geschwindigkeit angewandt
|
||||
* und dann wieder auf <code>(0, 0)</code> gesetzt.
|
||||
*
|
||||
* @param force Ein Vektor, der die Kraft darstellt.
|
||||
*/
|
||||
public void applyForce( Vector force ) {
|
||||
acceleration.add(force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ob dieses Objekt aktiv ist und Updates erhalten soll.
|
||||
*
|
||||
* @return Ob das Objekt simuliert wird.
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktiviert / Deaktiviert das Objekt.
|
||||
* @param pActive
|
||||
*/
|
||||
public void setActive( boolean pActive ) {
|
||||
this.active = pActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert die momentante Geschwindigkeit und Position des Objektes und
|
||||
* setzt die Beschleunigung zurück.
|
||||
*
|
||||
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
|
||||
*/
|
||||
public void update( double delta ) {
|
||||
acceleration.scale(delta);
|
||||
velocity.add(acceleration);
|
||||
acceleration.scale(0.0);
|
||||
|
||||
this.x += velocity.x;
|
||||
this.y += velocity.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||
if( SHOW_VELOCITY ) {
|
||||
Vector v = velocity.copy().scale(10);
|
||||
Arrow ar = new Arrow(v);
|
||||
|
||||
AffineTransform af = new AffineTransform(pVerzerrung);
|
||||
af.translate(radius, radius);
|
||||
ar.draw(graphics, af);
|
||||
}
|
||||
|
||||
super.draw(graphics, pVerzerrung);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user