mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-10-12 01:45:18 +02:00
Viele weitere Beispielprojekt für verschiedene Anwendungen
This commit is contained in:
128
examples/zm_boids/Boid.java
Normal file
128
examples/zm_boids/Boid.java
Normal file
@@ -0,0 +1,128 @@
|
||||
import schule.ngb.zm.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Boid extends Creature {
|
||||
|
||||
public static final double COHESION_FACTOR = .5;
|
||||
|
||||
public static final double SEPARATION_FACTOR = .5;
|
||||
|
||||
public static final double ALIGNMENT_FACTOR = .5;
|
||||
|
||||
public static final double FLIGHT_FACTOR = .5;
|
||||
|
||||
public static final double VELOCITY_LIMIT = 3.0;
|
||||
|
||||
public static final double FORCE_LIMIT = .1;
|
||||
|
||||
public static final int FLOCK_RADIUS = 100;
|
||||
|
||||
public static final boolean SHOW_RADIUS = false;
|
||||
|
||||
public static final int BOID_WIDTH = 8;
|
||||
|
||||
public static final int BOID_HEIGHT = 16;
|
||||
|
||||
private boolean highlight = false;
|
||||
|
||||
public Boid() {
|
||||
// Generate random Boid
|
||||
super(
|
||||
Vector.random(BOID_WIDTH, width-BOID_WIDTH, BOID_HEIGHT, height-BOID_HEIGHT),
|
||||
Vector.random(-1, 1).scale(random(VELOCITY_LIMIT))
|
||||
);
|
||||
senseRange = FLOCK_RADIUS;
|
||||
}
|
||||
|
||||
public Boid( Vector pos, Vector vel ) {
|
||||
super(pos, vel);
|
||||
senseRange = FLOCK_RADIUS;
|
||||
}
|
||||
|
||||
public void toggleHighlight() {
|
||||
highlight = !highlight;
|
||||
}
|
||||
|
||||
public void draw( DrawingLayer drawing ) {
|
||||
drawing.setFillColor(251, 241, 195);
|
||||
drawing.setStrokeColor(239, 191, 77);
|
||||
drawing.setStrokeWeight(2);
|
||||
|
||||
drawing.pushMatrix();
|
||||
drawing.translate(position.x, position.y);
|
||||
drawing.rotate(90 + velocity.angle());
|
||||
drawing.triangle(BOID_WIDTH / -2.0, BOID_HEIGHT / 2.0, 0, BOID_HEIGHT / -2.0, BOID_WIDTH / 2.0, BOID_HEIGHT / 2.0);
|
||||
|
||||
if( SHOW_RADIUS || highlight ) {
|
||||
drawing.setFillColor(251, 241, 195, 33);
|
||||
drawing.noStroke();
|
||||
drawing.circle(0, 0, FLOCK_RADIUS);
|
||||
}
|
||||
drawing.popMatrix();
|
||||
}
|
||||
|
||||
|
||||
public void update( List<Creature> creatures ) {
|
||||
Vector cohesion = new Vector();
|
||||
Vector separation = new Vector();
|
||||
Vector alignment = new Vector();
|
||||
Vector flight = new Vector();
|
||||
int boids = 0, predators = 0;
|
||||
|
||||
for( Creature c: creatures ) {
|
||||
if( isInRange(c) ) {
|
||||
if( Predator.class.isInstance(c) ) {
|
||||
double distSq = position.distanceSq(c.getPosition());
|
||||
flight.add(Vector.sub(position, c.getPosition()).div(distSq));
|
||||
|
||||
predators += 1;
|
||||
} else {
|
||||
cohesion.add(c.getPosition());
|
||||
alignment.add(c.getVelocity());
|
||||
|
||||
double distSq = position.distanceSq(c.getPosition());
|
||||
separation.add(Vector.sub(position, c.getPosition()).div(distSq));
|
||||
|
||||
boids += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( boids > 0 ) {
|
||||
// Cohesion
|
||||
cohesion.div(boids).sub(position);
|
||||
cohesion.setLength(VELOCITY_LIMIT).sub(velocity);
|
||||
cohesion.limit(FORCE_LIMIT);
|
||||
cohesion.scale(COHESION_FACTOR);
|
||||
// Separation
|
||||
separation.div(boids);
|
||||
separation.setLength(VELOCITY_LIMIT).sub(velocity);
|
||||
separation.limit(FORCE_LIMIT);
|
||||
separation.scale(SEPARATION_FACTOR);
|
||||
// Alignment
|
||||
alignment.div(boids);
|
||||
alignment.setLength(VELOCITY_LIMIT).sub(velocity);
|
||||
alignment.limit(FORCE_LIMIT);
|
||||
alignment.scale(ALIGNMENT_FACTOR);
|
||||
}
|
||||
if( predators > 0 ) {
|
||||
flight.div(predators);
|
||||
flight.setLength(VELOCITY_LIMIT).sub(velocity);
|
||||
flight.limit(FORCE_LIMIT*4.0);
|
||||
flight.scale(FLIGHT_FACTOR);
|
||||
}
|
||||
|
||||
acceleration
|
||||
.scale(0.0)
|
||||
.add(separation)
|
||||
.add(cohesion)
|
||||
.add(alignment)
|
||||
.add(flight);
|
||||
|
||||
position.add(velocity);
|
||||
limitPosition();
|
||||
velocity.add(acceleration).limit(VELOCITY_LIMIT);
|
||||
}
|
||||
|
||||
}
|
||||
78
examples/zm_boids/Boids.java
Normal file
78
examples/zm_boids/Boids.java
Normal file
@@ -0,0 +1,78 @@
|
||||
import schule.ngb.zm.*;
|
||||
import schule.ngb.zm.util.ImageLoader;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Boids extends Zeichenmaschine {
|
||||
|
||||
public static void main( String[] args ) {
|
||||
new Boids();
|
||||
}
|
||||
|
||||
public static final boolean BORDER_WRAP = true;
|
||||
|
||||
public static final int N_BOIDS = 200;
|
||||
|
||||
public static final int N_PREDATORS = 0;
|
||||
|
||||
private List<Creature> creatures;
|
||||
|
||||
public Boids() {
|
||||
super(1280, 720, "ZM: Boids");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setFullscreen(true);
|
||||
setCursor(ImageLoader.loadImage("pointer.png"), 0, 0);
|
||||
|
||||
creatures = new ArrayList<Creature>();
|
||||
|
||||
synchronized( creatures ) {
|
||||
for( int i = 0; i < N_BOIDS; i++ ) {
|
||||
creatures.add(new Boid());
|
||||
}
|
||||
for( int i = 0; i < N_PREDATORS; i++ ) {
|
||||
creatures.add(new Predator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( double delta ) {
|
||||
synchronized( creatures ) {
|
||||
for( Creature c : creatures ) {
|
||||
c.update(creatures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
drawing.clear(0, 125, 182);
|
||||
synchronized( creatures ) {
|
||||
for( Creature c : creatures ) {
|
||||
c.draw(drawing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked() {
|
||||
synchronized( creatures ) {
|
||||
creatures.add(new Predator(
|
||||
Vector.mouse(), Vector.ZERO
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed() {
|
||||
if( keyCode == KeyEvent.VK_G ) {
|
||||
setSize(800, 800);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
77
examples/zm_boids/Creature.java
Normal file
77
examples/zm_boids/Creature.java
Normal file
@@ -0,0 +1,77 @@
|
||||
import schule.ngb.zm.Constants;
|
||||
import schule.ngb.zm.DrawingLayer;
|
||||
import schule.ngb.zm.Vector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Creature extends Constants {
|
||||
|
||||
protected Vector position, velocity, acceleration;
|
||||
|
||||
protected int senseRange = 100;
|
||||
|
||||
public Creature( Vector pos, Vector vel ) {
|
||||
position = pos.copy();
|
||||
velocity = vel.copy();
|
||||
acceleration = new Vector();
|
||||
}
|
||||
|
||||
public Vector getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Vector getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
|
||||
public abstract void draw( DrawingLayer drawing );
|
||||
|
||||
public abstract void update( List<Creature> creatures );
|
||||
|
||||
protected void limitPosition() {
|
||||
if( position.x < 0 ) {
|
||||
if( Boids.BORDER_WRAP ) {
|
||||
position.x = width;
|
||||
} else {
|
||||
position.x = 0;
|
||||
//velocity.mult(-1);
|
||||
acceleration.add(Vector.scale(velocity, -2));
|
||||
}
|
||||
} else if( position.x > width ) {
|
||||
if( Boids.BORDER_WRAP ) {
|
||||
position.x = 0;
|
||||
} else {
|
||||
position.x = width;
|
||||
//velocity.mult(-1);
|
||||
acceleration.add(Vector.scale(velocity, -2));
|
||||
}
|
||||
}
|
||||
if( position.y < 0 ) {
|
||||
if( Boids.BORDER_WRAP ) {
|
||||
position.y = height;
|
||||
} else {
|
||||
position.y = 0;
|
||||
//velocity.mult(-1);
|
||||
acceleration.add(Vector.scale(velocity, -2));
|
||||
}
|
||||
} else if( position.y > height ) {
|
||||
if( Boids.BORDER_WRAP ) {
|
||||
position.y = 0.0;
|
||||
} else {
|
||||
position.y = height;
|
||||
//velocity.mult(-1);
|
||||
acceleration.add(Vector.scale(velocity, -2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isInRange( Creature otherCreature ) {
|
||||
if( otherCreature == this || otherCreature == null ) {
|
||||
return false;
|
||||
}
|
||||
if( abs(position.x-otherCreature.getPosition().x) > senseRange ) {
|
||||
return false;
|
||||
}
|
||||
return position.distanceSq(otherCreature.getPosition()) < senseRange*senseRange;
|
||||
}
|
||||
}
|
||||
97
examples/zm_boids/Predator.java
Normal file
97
examples/zm_boids/Predator.java
Normal file
@@ -0,0 +1,97 @@
|
||||
import schule.ngb.zm.DrawingLayer;
|
||||
import schule.ngb.zm.Vector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Predator extends Creature {
|
||||
|
||||
public static final int SENSE_RADIUS = 180;
|
||||
|
||||
public static final double AVOIDANCE_FACTOR = .65;
|
||||
|
||||
public static final double HUNTING_FACTOR = .65;
|
||||
|
||||
public static final double VELOCITY_LIMIT = 5.0;
|
||||
|
||||
public static final double FORCE_LIMIT = .1;
|
||||
|
||||
public static final int PREDATOR_WIDTH = 12;
|
||||
|
||||
public static final int PREDATOR_HEIGHT = 26;
|
||||
|
||||
public static final boolean SHOW_RADIUS = true;
|
||||
|
||||
public Predator() {
|
||||
// Generate random Predator
|
||||
super(
|
||||
Vector.random(PREDATOR_WIDTH, width - PREDATOR_WIDTH, PREDATOR_HEIGHT, height - PREDATOR_HEIGHT),
|
||||
Vector.random(-1, 1).scale(random(VELOCITY_LIMIT))
|
||||
);
|
||||
senseRange = SENSE_RADIUS;
|
||||
}
|
||||
|
||||
public Predator( Vector pos, Vector vel ) {
|
||||
super(pos, vel);
|
||||
senseRange = SENSE_RADIUS;
|
||||
}
|
||||
|
||||
public void draw( DrawingLayer drawing ) {
|
||||
drawing.setFillColor(152, 61, 83);
|
||||
drawing.setStrokeColor(225, 33, 32);
|
||||
drawing.setStrokeWeight(2);
|
||||
|
||||
drawing.pushMatrix();
|
||||
drawing.translate(position.x, position.y);
|
||||
drawing.rotate(90 + velocity.angle());
|
||||
drawing.triangle(PREDATOR_WIDTH / -2.0, PREDATOR_HEIGHT / 2.0, 0, PREDATOR_HEIGHT / -2.0, PREDATOR_WIDTH / 2.0, PREDATOR_HEIGHT / 2.0);
|
||||
|
||||
if( SHOW_RADIUS ) {
|
||||
drawing.setFillColor(152, 61, 83, 33);
|
||||
drawing.noStroke();
|
||||
drawing.circle(0, 0, SENSE_RADIUS);
|
||||
}
|
||||
drawing.popMatrix();
|
||||
}
|
||||
|
||||
public void update( List<Creature> creatures ) {
|
||||
Vector hunting = new Vector();
|
||||
Vector separation = new Vector();
|
||||
double boids = 0, predators = 0;
|
||||
|
||||
for( Creature c : creatures ) {
|
||||
if( isInRange(c) ) {
|
||||
if( Boid.class.isInstance(c) ) {
|
||||
hunting.add(c.getPosition());
|
||||
boids += 1;
|
||||
} else {
|
||||
double distSq = position.distanceSq(c.getPosition());
|
||||
separation.add(Vector.sub(position, c.getPosition()).div(distSq));
|
||||
|
||||
predators += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( boids > 0 ) {
|
||||
hunting.div(boids).sub(position);
|
||||
hunting.setLength(VELOCITY_LIMIT).sub(velocity);
|
||||
hunting.limit(FORCE_LIMIT);
|
||||
hunting.scale(HUNTING_FACTOR);
|
||||
}
|
||||
if( predators > 0 ) {
|
||||
separation.div(predators);
|
||||
separation.setLength(VELOCITY_LIMIT).sub(velocity);
|
||||
separation.limit(FORCE_LIMIT);
|
||||
separation.scale(AVOIDANCE_FACTOR);
|
||||
}
|
||||
|
||||
acceleration
|
||||
.scale(0.0)
|
||||
.add(hunting)
|
||||
.add(separation);
|
||||
|
||||
position.add(velocity);
|
||||
limitPosition();
|
||||
velocity.add(acceleration).limit(VELOCITY_LIMIT);
|
||||
}
|
||||
|
||||
}
|
||||
55
examples/zm_boids/package.bluej
Normal file
55
examples/zm_boids/package.bluej
Normal file
@@ -0,0 +1,55 @@
|
||||
#BlueJ package file
|
||||
dependency1.from=Attractor
|
||||
dependency1.to=Gravity
|
||||
dependency1.type=UsesDependency
|
||||
dependency2.from=Gravity
|
||||
dependency2.to=Mover
|
||||
dependency2.type=UsesDependency
|
||||
dependency3.from=Gravity
|
||||
dependency3.to=Attractor
|
||||
dependency3.type=UsesDependency
|
||||
editor.fx.0.height=728
|
||||
editor.fx.0.width=1037
|
||||
editor.fx.0.x=95
|
||||
editor.fx.0.y=53
|
||||
objectbench.height=94
|
||||
objectbench.width=776
|
||||
package.divider.horizontal=0.6
|
||||
package.divider.vertical=0.8305369127516778
|
||||
package.editor.height=488
|
||||
package.editor.width=661
|
||||
package.editor.x=374
|
||||
package.editor.y=158
|
||||
package.frame.height=660
|
||||
package.frame.width=800
|
||||
package.numDependencies=3
|
||||
package.numTargets=3
|
||||
package.showExtends=true
|
||||
package.showUses=true
|
||||
project.charset=UTF-8
|
||||
readme.height=60
|
||||
readme.name=@README
|
||||
readme.width=48
|
||||
readme.x=10
|
||||
readme.y=10
|
||||
target1.height=70
|
||||
target1.name=Mover
|
||||
target1.showInterface=false
|
||||
target1.type=ClassTarget
|
||||
target1.width=120
|
||||
target1.x=380
|
||||
target1.y=220
|
||||
target2.height=70
|
||||
target2.name=Attractor
|
||||
target2.showInterface=false
|
||||
target2.type=ClassTarget
|
||||
target2.width=120
|
||||
target2.x=380
|
||||
target2.y=350
|
||||
target3.height=70
|
||||
target3.name=Gravity
|
||||
target3.showInterface=false
|
||||
target3.type=ClassTarget
|
||||
target3.width=120
|
||||
target3.x=120
|
||||
target3.y=120
|
||||
BIN
examples/zm_boids/pointer.png
Normal file
BIN
examples/zm_boids/pointer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Reference in New Issue
Block a user