Viele weitere Beispielprojekt für verschiedene Anwendungen

This commit is contained in:
ngb 2022-06-19 22:26:01 +02:00
parent dc6b7ee351
commit a2d883305a
97 changed files with 2535 additions and 61 deletions

View File

@ -0,0 +1,53 @@
import schule.ngb.zm.Zeichenmaschine;
import schule.ngb.zm.util.ImageLoader;
public class Aquarium extends Zeichenmaschine {
public static final int N_FISHES = 25;
public static void main( String[] args ) {
new Aquarium();
}
private Fish[] fish;
public Aquarium() {
super(800, 600, "Aquarium");
}
@Override
public void setup() {
canvas.addLayer(1, new Background());
fish = new Fish[N_FISHES];
for( int i = 1; i <= 7; i++ ) {
ImageLoader.preloadImage("fish"+i, "tiles/fish"+i+"gs.png");
}
for( int i = 0; i < N_FISHES; i++ ) {
fish[i] = new Fish();
shapes.add(fish[i]);
}
}
@Override
public void update( double delta ) {
for( int i = 0; i < fish.length; i++ ) {
fish[i].update(delta);
}
}
@Override
public void draw() {
}
@Override
public void mouseClicked() {
for( int i = 0; i < fish.length; i++ ) {
fish[i].randomize();
}
}
}

View File

@ -0,0 +1,59 @@
import schule.ngb.zm.Layer;
import java.awt.Graphics2D;
import java.awt.Image;
public class Background extends Layer {
private static final int TILE_SIZE = 64;
private int tile_width;
private Image[] floor, plants;
private Image water;
public Background() {
super();
}
public Background( int width, int height ) {
super(width, height);
}
@Override
public void setSize( int width, int height ) {
super.setSize(width, height);
generateBackground();
}
public void generateBackground() {
tile_width = (int)(ceil(getWidth()/(double)TILE_SIZE));
floor = new Image[tile_width];
plants = new Image[tile_width];
for ( int i = 0; i < tile_width; i++ ) {
floor[i] = loadImage("tiles/floor"+random(1,8)+".png");
if( random(1,10) < 4 ) {
plants[i] = loadImage("tiles/plant"+random(1,14)+".png");
}
}
water = loadImage("tiles/water.png");
for ( int i = 0; i < getHeight(); i += TILE_SIZE ) {
for ( int j = 0; j < getWidth(); j += TILE_SIZE ) {
drawing.drawImage(water, j, i, null);
}
}
for ( int i = 0; i < tile_width; i++ ) {
if( plants[i] != null ) {
drawing.drawImage(plants[i], i*TILE_SIZE, getHeight() - (2*TILE_SIZE) + 10,TILE_SIZE,TILE_SIZE, null);
}
drawing.drawImage(floor[i], i*TILE_SIZE, getHeight() - TILE_SIZE,TILE_SIZE,TILE_SIZE, null);
}
}
}

View File

@ -0,0 +1,72 @@
import schule.ngb.zm.*;
import schule.ngb.zm.shapes.Picture;
import schule.ngb.zm.shapes.Shape;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
public class Fish extends Shape implements Updatable {
private int speed;
private Picture img;
public Fish() {
randomize();
}
public void randomize() {
int i = random(1, 7);
speed = random(-2, 2);
img = new Picture("fish" + i);
img.setAnchor(NORTHWEST);
img.scale(random(0.8, 1.0));
img.tint(randomNiceColor());
//img.scale(0.5);
if( speed < 0 ) {
img.flip(LEFT);
}
img.moveTo(random(10, width-img.getWidth()), random(30, height-120));
}
@Override
public boolean isActive() {
return true;
}
@Override
public void update( double delta ) {
img.move(speed, .5 * sin(tick / (speed * 10.0)));
if( img.getX() <= 0 || img.getX()+img.getWidth() >= 800 ) {
speed *= -1;
img.flip(LEFT);
}
}
@Override
public void draw( Graphics2D graphics, AffineTransform transform ) {
img.draw(graphics, transform);
}
@Override
public double getWidth() {
return img.getWidth();
}
@Override
public double getHeight() {
return img.getHeight();
}
@Override
public Shape copy() {
return img.copy();
}
@Override
public java.awt.Shape getShape() {
return img.getShape();
}
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1013 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

128
examples/zm_boids/Boid.java Normal file
View 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);
}
}

View 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);
}
}
}

View 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;
}
}

View 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);
}
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,101 @@
import schule.ngb.zm.GraphicsLayer;
import schule.ngb.zm.Options;
import schule.ngb.zm.Zeichenmaschine;
import schule.ngb.zm.shapes.Picture;
import schule.ngb.zm.shapes.Text;
import java.util.ArrayList;
public class Cookieclicker extends Zeichenmaschine {
public static void main( String[] args ) {
new Cookieclicker();
}
private int cookies = 0;
private int cookiesPerClick = 1;
private int grandmas = 0;
private int autoclicker = 12, autoclickerTimer = 0, autoClickerDelay = 600;
private Text tCookies, tShopGrandma, tShopAutoclicker;
private Picture pCookie;
private boolean cookieDown = false;
public Cookieclicker() {
super(1280, 900, "Cookieclicker");
}
@Override
public void setup() {
pCookie = new Picture(width / 2, height / 2, "assets/cookie.png");
pCookie.scale(.5);
shapes.add(pCookie);
tCookies = new Text(width - 60, 60, "" + cookies);
tCookies.setAnchor(NORTHEAST);
tCookies.setStrokeColor(255);
tCookies.setFontsize(36);
shapes.add(tCookies);
background.setColor(0);
}
@Override
public void update( double delta ) {
tCookies.setText("" + cookies);
autoclickerTimer -= (int)(delta * 1000.0);
if( autoclickerTimer <= 0 ) {
cookies += autoclicker;
autoclickerTimer += autoClickerDelay;
}
synchronized( particles ) {
ArrayList<NumberParticle> remove = new ArrayList<>();
for( NumberParticle p : particles ) {
if( p.isActive() ) {
p.update(delta);
} else {
remove.add(p);
}
}
for( NumberParticle p : remove ) {
particles.remove(p);
}
}
}
@Override
public void draw() {
}
ArrayList<NumberParticle> particles = new ArrayList<>();
@Override
public void mousePressed() {
if( pCookie.getBounds().contains(mouseX, mouseY) ) {
cookieDown = true;
cookies += cookiesPerClick;
pCookie.scale(.95);
synchronized( particles ) {
NumberParticle p = new NumberParticle(mouseX, mouseY, cookiesPerClick);
particles.add(p);
shapes.add(p);
}
}
}
@Override
public void mouseReleased() {
if( cookieDown ) {
pCookie.scale(1 / .95);
}
}
}

View File

@ -0,0 +1,33 @@
import schule.ngb.zm.Updatable;
import schule.ngb.zm.shapes.Text;
public class NumberParticle extends Text implements Updatable {
double sinOffset, life = 0;
public NumberParticle( double x, double y, int number ) {
super(x,y,"+"+number);
sinOffset = random(0.0, PI);
life = 1.5;
setStrokeColor(255);
setFontsize(36);
}
@Override
public boolean isActive() {
return (life > 0);
}
@Override
public void update( double delta ) {
if( isActive() ) {
double deltaX = sin(sinOffset + life);
x += deltaX;
y -= 100*delta;
life -= delta;
setStrokeColor(strokeColor, (int) interpolate(0, 255, life / 1.5));
}
}
}

View File

@ -0,0 +1,111 @@
import schule.ngb.zm.Drawable;
import schule.ngb.zm.Updatable;
import schule.ngb.zm.shapes.Text;
import java.awt.Graphics2D;
import java.util.ArrayList;
public class NumberParticleEmitter implements Updatable, Drawable {
public class NumberParticle extends Text implements Updatable {
double velX = 0, velY = 0, accX = 0, accY = 0;
double life = 0;
public NumberParticle() {
super(0, 0, "0");
// life = particleLifespan;
}
@Override
public boolean isActive() {
return (life <= 0);
}
public void activate() {
x = emitterX;
y = emitterY;
life = particleLifespan;
}
@Override
public void update( double delta ) {
if( isActive() ) {
velX += accX;
velY += accY;
x += velX;
y += velY;
life -= delta;
setFillColor(fillColor, (int) interpolate(0, 255, life / particleLifespan));
}
}
}
private int particlesPerSecond, maxParticles;
private double particleLifespan;
private ArrayList<NumberParticle> particles;
private int activeParticles = 0;
private double lastEmit = 0.0;
private double emitterX, emitterY;
public NumberParticleEmitter( double x, double y, int particlesPerSecond, double particleLifespan ) {
emitterX = x;
emitterY = y;
this.particlesPerSecond = particlesPerSecond;
this.particleLifespan = particleLifespan;
maxParticles = (int) Math.ceil(particlesPerSecond * particleLifespan);
particles = new ArrayList<>(maxParticles);
for( int i = 0; i < maxParticles; i++ ) {
particles.add(new NumberParticle());
}
}
@Override
public boolean isVisible() {
return activeParticles > 0;
}
@Override
public void draw( Graphics2D graphics ) {
for( NumberParticle p : particles ) {
if( p.isActive() ) {
p.draw(graphics);
}
}
}
@Override
public boolean isActive() {
return isVisible();
}
public void emitParticle( int number ) {
particles.add(new NumberParticle());
}
@Override
public void update( double delta ) {
//lastEmit -= delta;
for( NumberParticle p : particles ) {
if( p.isActive() ) {
p.update(delta);
} /*else if( lastEmit <= 0 ) {
p.activate();
lastEmit += 1/(double)particlesPerSecond;
}*/
}
}
}

View File

@ -0,0 +1,36 @@
import schule.ngb.zm.GraphicsLayer;
import schule.ngb.zm.Zeichenmaschine;
public class ParticleTest extends Zeichenmaschine {
public static void main( String[] args ) {
new ParticleTest();
}
private NumberParticleEmitter emitter;
private GraphicsLayer graphics;
public ParticleTest() {
super(800,800, "Particles");
}
@Override
public void setup() {
graphics = new GraphicsLayer();
canvas.addLayer(graphics);
emitter = new NumberParticleEmitter(400, 400, 1, 10);
}
@Override
public void update( double delta ) {
emitter.update(delta);
}
@Override
public void draw() {
emitter.draw(graphics.getGraphics());
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View 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

View File

@ -0,0 +1,51 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.DrawingLayer;
import schule.ngb.zm.Vector;
import schule.ngb.zm.Zeichenobjekt;
public class Eye extends Zeichenobjekt {
private Vector position;
private double size;
private Color color;
public Eye() {
position = Vector.random(0, width, 0, height);
size = random(10.0, 25.0);
color = null;
}
public Eye( float x, float y ) {
position = new Vector(x, y);
size = random(10.0, 25.0);
color = null;
}
public Eye( float x, float y, Color color ) {
position = new Vector(x, y);
size = random(10.0, 25.0);
this.color = color;
}
@Override
public void draw( DrawingLayer drawing ) {
Vector dir = Vector.sub(new Vector(mouseX, mouseY), position);
double len = dir.length();
drawing.setStrokeColor(0);
if( color == null ) {
drawing.setFillColor(colorHsb(354, 100.0 - limit(len, 0.0, 100.0), 100));
} else {
drawing.setFillColor(color);
}
drawing.circle(position.x, position.y, size);
Vector pupil = Vector.add(position, dir.limit(size*.4));
drawing.setFillColor(0);
drawing.circle(pupil.x, pupil.y, size*.4);
}
}

View File

@ -0,0 +1,38 @@
import schule.ngb.zm.Zeichenmaschine;
public class Eyes extends Zeichenmaschine {
public static final int N_EYES = 30;
public static void main( String[] args ) {
new Eyes();
}
Eye[] eyes;
public Eyes() {
super(600, 600, "Eyes");
}
@Override
public void setup() {
eyes = new Eye[N_EYES];
for( int i = 0; i < eyes.length; i++ ) {
eyes[i] = new Eye();
}
}
@Override
public void update( double delta ) {
}
@Override
public void draw() {
drawing.clear(200);
for( int i = 0; i < eyes.length; i++ ) {
eyes[i].draw(drawing);
}
}
}

View 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

View File

@ -75,8 +75,8 @@ public class Attractor extends Mover {
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);
double v = G * mass / force.lengthSq();
force.setLength(v).limit(1.0, 4 * G);
pMover.applyForce(force);
}
}

View File

@ -77,10 +77,11 @@ public class Gravity extends Zeichenmaschine {
* Welt zurück.
*/
public void mouseClicked() {
background.setColor(randomNiceColor());
for( Mover m : movers ) {
m.moveTo(random(10, width - 10), 30);
m.setVelocity(mouseX-m.getX(), mouseY-m.getY());
m.getVelocity().setLen(4.0);
m.getVelocity().setLength(4.0);
}
}

View File

@ -23,7 +23,7 @@ public class Mover extends Circle implements Updatable {
/**
* Ob die momentane Geschwindigkeit der Objekte als Pfeil dargestellt werden soll.
*/
public static final boolean SHOW_VELOCITY = false;
public static final boolean SHOW_VELOCITY = true;
/**
@ -163,8 +163,10 @@ public class Mover extends Circle implements Updatable {
velocity.add(acceleration);
acceleration.scale(0.0);
this.x += velocity.x;
this.y += velocity.y;
if( velocity.length() > 0.5 ) {
this.x += velocity.x;
this.y += velocity.y;
}
}
@Override

View File

@ -0,0 +1,33 @@
/**
* Beschreiben Sie hier die Klasse Dreieck.
*
* @author (Ihr Name)
* @version (eine Versionsnummer oder ein Datum)
*/
public class Dreieck
{
// Instanzvariablen - ersetzen Sie das folgende Beispiel mit Ihren Variablen
private int x;
/**
* Konstruktor für Objekte der Klasse Dreieck
*/
public Dreieck()
{
// Instanzvariable initialisieren
x = 0;
}
/**
* Ein Beispiel einer Methode - ersetzen Sie diesen Kommentar mit Ihrem eigenen
*
* @param y ein Beispielparameter für eine Methode
* @return die Summe aus x und y
*/
public int beispielMethode(int y)
{
// tragen Sie hier den Code ein
return x + y;
}
}

View File

@ -0,0 +1,88 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Drawable;
import java.awt.Graphics2D;
public class Kreis implements Drawable {
private int x;
private int y;
private int radius;
private Color farbe;
private Color linienfarbe;
private boolean sichtbar;
public Kreis() {
x = 420;
y = 420;
radius = 80;
farbe = Color.BLUE;
linienfarbe = Color.BLACK;
sichtbar = true;
}
public void anzeigen() {
sichtbar = true;
}
public void verstecken() {
sichtbar = false;
}
public void setPosition( int pX, int pY ) {
x = pX;
y = pY;
}
public void links() {
x -= 10;
}
public void rechts() {
x += 10;
}
public void hoch() {
y -= 10;
}
public void runter() {
y += 10;
}
public void setRadius( int pRadius ) {
radius = pRadius;
}
public void setFarbe( String pFarbe ) {
farbe = Color.parseString(pFarbe);
}
public void setLinienfarbe( String pLinienfarbe ) {
linienfarbe = Color.parseString(pLinienfarbe);
}
@Override
public boolean isVisible() {
return sichtbar;
}
@Override
public void draw( Graphics2D graphics ) {
if( x-(radius/2.0) > 0 && x+(radius/2.0) < 800 && y-(radius/2.0) > 0 && y+(radius/2.0) < 800 ) {
graphics.setColor(farbe.getJavaColor());
graphics.fillOval(x, y, radius, radius);
graphics.setColor(linienfarbe.getJavaColor());
graphics.drawOval(x, y, radius, radius);
}
}
}

View File

@ -0,0 +1,29 @@
import schule.ngb.zm.Drawable;
import schule.ngb.zm.DrawableLayer;
import schule.ngb.zm.Zeichenmaschine;
public class Leinwand {
private final Zeichenmaschine zm;
private final DrawableLayer zeichenflaeche;
public Leinwand() {
zm = new Zeichenmaschine(800, 800, "ZM: Shapes", false);
zeichenflaeche = new DrawableLayer();
zm.addLayer(zeichenflaeche);
}
public void anzeigen( Drawable pForm ) {
zeichenflaeche.add(pForm);
}
public void beenden() {
zm.exit();
}
public void zeichnen() {
zm.redraw();
}
}

View File

@ -0,0 +1,95 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Drawable;
import java.awt.Graphics2D;
public class Rechteck implements Drawable {
private int x;
private int y;
private int breite;
private int hoehe;
private Color farbe;
private Color linienfarbe;
private boolean sichtbar;
public Rechteck() {
x = 320;
y = 240;
breite = 100;
hoehe = 60;
farbe = Color.RED;
linienfarbe = Color.BLACK;
sichtbar = true;
}
public void anzeigen() {
sichtbar = true;
}
public void verstecken() {
sichtbar = false;
}
public void setPosition( int pX, int pY ) {
x = pX;
y = pY;
}
public void links() {
x -= 10;
}
public void rechts() {
x += 10;
}
public void hoch() {
y -= 10;
}
public void runter() {
y += 10;
}
public void setBreite( int pBreite ) {
breite = pBreite;
}
public void setHoehe( int pHoehe ) {
hoehe = pHoehe;
}
public void setFarbe( String pFarbe ) {
farbe = Color.parseString(pFarbe);
}
public void setLinienfarbe( String pLinienfarbe ) {
linienfarbe = Color.parseString(pLinienfarbe);
}
@Override
public boolean isVisible() {
return sichtbar;
}
@Override
public void draw( Graphics2D graphics ) {
if( x-(breite/2.0) > 0 && x+(breite/2.0) < 800 && y-(hoehe/2.0) > 0 && y+(hoehe/2.0) < 800 ) {
graphics.setColor(farbe.getJavaColor());
graphics.fillRect(x, y, breite, hoehe);
graphics.setColor(linienfarbe.getJavaColor());
graphics.drawRect(x, y, breite, hoehe);
}
}
}

View File

@ -0,0 +1,53 @@
#BlueJ package file
editor.fx.0.height=728
editor.fx.0.width=800
editor.fx.0.x=488
editor.fx.0.y=107
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=36
package.editor.y=155
package.frame.height=660
package.frame.width=800
package.numDependencies=0
package.numTargets=4
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=30
target1.name=Rechteck
target1.showInterface=false
target1.type=ClassTarget
target1.width=70
target1.x=190
target1.y=50
target2.height=30
target2.name=Dreieck
target2.showInterface=false
target2.type=ClassTarget
target2.width=70
target2.x=190
target2.y=170
target3.height=30
target3.name=Kreis
target3.showInterface=false
target3.type=ClassTarget
target3.width=70
target3.x=190
target3.y=110
target4.height=60
target4.name=Leinwand
target4.showInterface=false
target4.type=ClassTarget
target4.width=120
target4.x=40
target4.y=100

View File

@ -1,14 +1,12 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Zeichenmaschine;
import java.awt.event.KeyEvent;
/**
* Eine Bildergallerie von Bildern eines Informatikkurses des 10. Jahrgangs.
*/
public class Gallery extends Zeichenmaschine {
public static void main( String[] args ) {
public static void main(String[] args) {
new Gallery();
}
@ -28,7 +26,7 @@ public class Gallery extends Zeichenmaschine {
* Zeigt ein zufälliges Bild an.
*/
public void drawRandom() {
switch( random(0, 4) ) {
switch (random(0, 4)) {
case 0:
rainbow();
break;
@ -45,10 +43,10 @@ public class Gallery extends Zeichenmaschine {
}
/**
* Bei Betätigen der Leertaste ein Zufallsbild anzeigen
* Bei Betätigen der Leertaste ein Zufallsbild anzeigen.
*/
public void keyPressed() {
if( keyCode == 32 ) {
if (keyCode == 32) {
drawRandom();
}
}
@ -58,10 +56,10 @@ public class Gallery extends Zeichenmaschine {
*
* @param pWartezeit Die Wartezeit zum nächsten Bildwechsel in Millisekunden.
*/
public void slideshow( int pWartezeit ) {
public void slideshow(int pWartezeit) {
int i = 0;
while( true ) {
switch( i ) {
while (true) {
switch (i) {
case 0:
rainbow();
break;
@ -91,7 +89,7 @@ public class Gallery extends Zeichenmaschine {
drawing.clear(60, 155, 217);
// Einige Werte berechnen, um Bild an Bildgröße anzupassen
double size = (width+height)*0.03333;
double size = (width + height) * 0.03333;
double r = width / 2.0;
// Kleiner werdende Kreise in den Farben des Bogens zeichnen
@ -108,7 +106,7 @@ public class Gallery extends Zeichenmaschine {
// Sonne zeichnen
drawing.setFillColor(232, 200, 52);
drawing.circle(width*0.8333, size*2.6666, size*2);
drawing.circle(width * 0.8333, size * 2.6666, size * 2);
// Bild auf Leinwand übertragen
redraw();
@ -125,22 +123,21 @@ public class Gallery extends Zeichenmaschine {
drawing.setStrokeColor(0);
// Farben der Streifen festlegen
Color[] colors = new Color[]{
RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE
Color[] colors = new Color[] {
RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE
};
// Breite der Streifen an Bildgröße anpassen
double size = height*0.06666;
double borderX = width/6.0, borderY = height/6.0;
double size = height * 0.06666;
double borderX = width / 6.0, borderY = height / 6.0;
// Flaggenstab zeichnen
drawing.setFillColor(BROWN);
drawing.rect(borderX, borderY, size, height - 2*borderY, NORTHWEST);
drawing.rect(borderX, borderY, size, height - 2 * borderY, NORTHWEST);
// Streifen zeichnen
for( int i = 0; i < colors.length; i++ ) {
for (int i = 0; i < colors.length; i++) {
drawing.setFillColor(colors[i]);
drawing.rect(borderX, borderY + i * size, width - 2*borderX, size, NORTHWEST);
drawing.rect(borderX, borderY + i * size, width - 2 * borderX, size, NORTHWEST);
}
// Bild auf Leinwand übertragen
@ -159,17 +156,17 @@ public class Gallery extends Zeichenmaschine {
drawing.setFillColor(WHITE);
// Zufällig erzeugte Sterne
for( int i = 0; i < (width+height)/4; i++ ) {
for (int i = 0; i < (width + height) / 4; i++) {
drawing.circle(random(0.0, width), random(0.0, height), random(1, 3));
}
// Einige Werte berechnen, die später verwendet werden, um
// die Zeichnung an die Bildschirmgröße anzupassen.
double radius = limit(width*0.6666, height*0.6666) / 2.0;
double radius = limit(width * 0.6666, 0.0, height * 0.6666) / 2.0;
double w2 = width / 2.0, h2 = height / 2.0;
double r2 = radius / 2.0,
r3 = radius / 3.0, r4 = radius / 4.0,
r5 = radius / 5.0, r10 = radius / 10.0;
r3 = radius / 3.0, r4 = radius / 4.0,
r5 = radius / 5.0, r10 = radius / 10.0;
// Korpus zeichnen
drawing.setFillColor(128);
@ -187,35 +184,32 @@ public class Gallery extends Zeichenmaschine {
// Strahlen des Lasers zeichnen
int beams = 8; // Anzahl Strahlen
for( int i = 0; i < beams; i++ ) {
for (int i = 0; i < beams; i++) {
drawing.setStrokeColor(GREEN);
drawing.setStrokeType(SOLID);
drawing.setStrokeWeight(1.6);
drawing.line(
w2 + r2 - r4 * cos(radians(360 / beams * i)),
h2 - r3 + r4 * sin(radians(360 / beams * i)),
w2 + r2 + 2 + r5,
h2 - r3 - 2 - r5
);
w2 + r2 - r4 * cos(radians(360 / beams * i)),
h2 - r3 + r4 * sin(radians(360 / beams * i)),
w2 + r2 + 2 + r5,
h2 - r3 - 2 - r5);
drawing.setStrokeType(DASHED);
drawing.setStrokeWeight(3.0);
drawing.line(
w2 + r2 - r4 * cos(radians(360 / beams * i)),
h2 - r3 + r4 * sin(radians(360 / beams * i)),
w2 + r2 + 2 + r5,
h2 - r3 - 2 - r5
);
w2 + r2 - r4 * cos(radians(360 / beams * i)),
h2 - r3 + r4 * sin(radians(360 / beams * i)),
w2 + r2 + 2 + r5,
h2 - r3 - 2 - r5);
drawing.setStrokeColor(WHITE);
drawing.setStrokeType(SOLID);
drawing.setStrokeWeight(1.0);
drawing.line(
w2 + r2 - r4 * cos(radians(360 / beams * i)),
h2 - r3 + r4 * sin(radians(360 / beams * i)),
w2 + r2 + 2 + r5,
h2 - r3 - 2 - r5
);
w2 + r2 - r4 * cos(radians(360 / beams * i)),
h2 - r3 + r4 * sin(radians(360 / beams * i)),
w2 + r2 + 2 + r5,
h2 - r3 - 2 - r5);
}
// Hauptstrahl

View File

@ -0,0 +1,77 @@
import schule.ngb.zm.Vector;
import schule.ngb.zm.Zeichenmaschine;
public class BouncingLine extends Zeichenmaschine {
public static void main( String[] args ) {
new BouncingLine();
}
private Vector start, end, dStart, dEnd;
private int r, g, b;
private boolean mouseFollow = false;
public BouncingLine() {
super(800, 800, "Bouncing Lines");
}
@Override
public void setup() {
start = Vector.random(0, width, 0, height);
end = Vector.random(0, width, 0, height);
dStart = Vector.random(-5, 5);
dEnd = Vector.random(-5, 5);
r = random(255);
g = random(255);
b = random(255);
}
@Override
public void update( double delta ) {
start.add(dStart);
end.add(dEnd);
if( start.x > width || start.x < 0 ) {
dStart.x *= -1;
}
if( end.x > width || end.x < 0 ) {
dEnd.x *= -1;
}
if( start.y > width || start.y < 0 ) {
dStart.y *= -1;
}
if( end.y > width || end.y < 0 ) {
dEnd.y *= -1;
}
r += limit(random(-5, 5), 0, 255);
g += limit(random(-5, 5), 0, 255);
b += limit(random(-5, 5), 0, 255);
}
@Override
public void draw() {
drawing.setStrokeColor(r, g, b);
drawing.line(start.x, start.y, end.x, end.y);
// bezier(0, 0, startX, startY, endX, endY, width, height);
}
@Override
public void mouseClicked() {
mouseFollow = !mouseFollow;
}
@Override
public void mouseMoved() {
if( mouseFollow ) {
dStart = new Vector(mouseX - start.x, mouseY - start.y);
dStart.setLength(5);
dEnd = new Vector(mouseX - end.x, mouseY - end.y);
dEnd.setLength(5);
}
}
}

View File

@ -0,0 +1,40 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Zeichenmaschine;
public class GenColors extends Zeichenmaschine {
public static void main( String[] args ) {
new GenColors();
}
public GenColors() {
super(800, 800, "Nice Colors");
}
@Override
public void setup() {
genPattern();
}
public void genPattern() {
drawing.noStroke();
int SIZE = 40;
for( int i = 0; i < width/SIZE; i++ ) {
for( int j = 0; j < height/SIZE; j++ ) {
Color c = randomNiceColor();
float[] hsl = Color.RGBtoHSL(c.getRGBA(), null);
System.out.printf("%f, %f, %f\n", hsl[0], hsl[1], hsl[2]);
drawing.setFillColor(c);
drawing.square(i*SIZE, j*SIZE, SIZE, NORTHWEST);
}
}
}
@Override
public void mouseClicked() {
genPattern();
redraw();
}
}

View File

@ -0,0 +1,122 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Constants;
import schule.ngb.zm.Options;
import schule.ngb.zm.Zeichenmaschine;
public class GenHitomezashi extends Zeichenmaschine {
public static final int TILE_SIZE = 20;
public static final int COLUMNS = 30;
public static final int ROWS = 30;
public static final double P = 0.5;
public static final Color[] colors = new Color[]{
randomNiceColor(),
randomNiceColor(),
color(241, 124, 55),
color(62, 156, 191)
};
private int[] stitchesX, stitchesY;
public static void main( String[] args ) {
new GenHitomezashi();
}
public GenHitomezashi() {
super(TILE_SIZE*COLUMNS, TILE_SIZE*ROWS, "Hitomezashi Pattern");
}
@Override
public void setup() {
drawing.setStrokeColor(0);
drawing.setFillColor(0);
generatePattern();
pause();
}
public void generatePattern() {
stitchesX = new int[COLUMNS];
for ( int i = 0; i < COLUMNS; i++ ) {
stitchesX[i] = random(0, 1) < P ? 1 : 0;
}
stitchesY = new int[COLUMNS];
for ( int j = 0; j < ROWS; j++ ) {
stitchesY[j] = random(0, 1) < P ? 1 : 0;
}
}
public boolean hasStitch( int i, int j, Options.Direction dir ) {
switch( dir ) {
case UP:
return (j > 0 && (stitchesY[j-1]+i)%2 == 1);
case DOWN:
return (j >= 0 && (stitchesY[j]+i)%2 == 1);
case LEFT:
return (i > 0 && (stitchesX[i-1]+j)%2 == 1);
case RIGHT:
return (i >= 0 && (stitchesX[i]+j)%2 == 1);
default:
return false;
}
}
@Override
public void update( double delta ) {
}
@Override
public void draw() {
drawing.clear(200);
int clr = random(1), clr2 = clr;
drawing.noStroke();
for ( int i = 0; i < COLUMNS; i++ ) {
if ( hasStitch(i, 0, LEFT) ) {
clr = (clr2+1)%2;
clr2 = clr;
} else {
clr = clr2;
}
for ( int j = 0; j < ROWS; j++ ) {
drawing.setFillColor(colors[clr]);
drawing.rect(i*TILE_SIZE, j*TILE_SIZE, TILE_SIZE, TILE_SIZE, NORTHWEST);
if ( hasStitch(i, j, DOWN) ) {
clr = (clr+1)%2;
}
}
}
drawing.setStrokeColor(0);
drawing.setStrokeWeight(2);
for ( int i = 0; i < COLUMNS; i++ ) {
for ( int j = 0; j < ROWS; j++ ) {
boolean stitchX = (stitchesX[i]+j)%2 == 1;
if ( i < COLUMNS-1 && stitchX ) {
drawing.line((i+1)*TILE_SIZE, j*TILE_SIZE, (i+1)*TILE_SIZE, (j+1)*TILE_SIZE);
}
boolean stitchY = (stitchesY[j]+i)%2 == 1;
if ( j < ROWS-1 && stitchY ) {
drawing.line(i*TILE_SIZE, (j+1)*TILE_SIZE, (i+1)*TILE_SIZE, (j+1)*TILE_SIZE);
}
}
}
}
@Override
public void mousePressed() {
generatePattern();
redraw();
}
}

View File

@ -0,0 +1,62 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Zeichenmaschine;
public class GenLines extends Zeichenmaschine {
public static final int BORDER = 16;
public static final int SIZE = 400;
public static Color[] colors = new Color[]{
color(62, 156, 191),
color(167, 236, 242),
color(242, 196, 61),
color(241, 124, 55),
color(242, 109, 80)
};
public static void main( String[] args ) {
new GenLines();
}
private int i = 0;
public GenLines() {
super(SIZE, SIZE, "Lines");
}
@Override
public void setup() {
setFramesPerSecond(10);
drawing.clear(33);
}
@Override
public void update( double delta ) {
}
@Override
public void draw() {
int a = random(BORDER, SIZE-BORDER);
//drawing.setStrokeColor(random(50, 200));
drawing.setStrokeColor(colors[random(colors.length-1)]);
drawing.setStrokeWeight(random(4,12));
int d;
if( a > SIZE*0.5 ) {
d = random(1, (SIZE - a) - BORDER);
} else {
d = random(1, a - BORDER);
}
drawing.line(a - d, a + d, a + d, a - d);
i += 1;
if( i == SIZE ) {
stop();
}
}
}

View File

@ -0,0 +1,60 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Zeichenmaschine;
public class GenSpiral extends Zeichenmaschine {
public static final int SIZE = 800;
public static final double D_SCALE = .33;
public static final double A_SCALE = 6.0;
public static Color[] colors = new Color[]{
color(62, 156, 191, 44),
color(167, 236, 242, 44),
color(242, 196, 61, 44),
color(241, 124, 55, 44),
color(242, 109, 80, 44)
};
public static void main( String[] args ) {
new GenSpiral();
}
private int i = 0;
public GenSpiral() {
super(SIZE, SIZE, "Lines");
}
@Override
public void setup() {
setFramesPerSecond(60);
drawing.clear(33);
drawing.translate(SIZE/2, SIZE/2);
}
@Override
public void update( double delta ) {
}
@Override
public void draw() {
double d = (tick * D_SCALE); // + random(0,3);
double a = radians(tick * tick / A_SCALE);
// a = radians(tick * A_SCALE / D_SCALE);
// a = radians(d * A_SCALE);
int x = (int)(d * cos(a));
int y = (int)(d * sin(a));
drawing.setFillColor(colors[random(colors.length - 1)]);
drawing.noStroke();
drawing.circle(x, y, 10);
if( d > SIZE+SIZE ) {
stop();
}
}
}

View File

@ -0,0 +1,43 @@
import schule.ngb.zm.DrawingLayer;
import schule.ngb.zm.Zeichenmaschine;
public class GenWalk extends Zeichenmaschine {
public static final int N_WALKERS = 8;
private Walker[] walkers;
public static void main( String[] args ) {
new GenWalk();
}
public GenWalk() {
super(800, 800, "Randomwalk");
}
@Override
public void setup() {
this.walkers = new Walker[N_WALKERS];
for( int i = 0; i < walkers.length; i++ ) {
this.walkers[i] = new Walker(width/2, height/2, drawing);
}
drawing.clear(0);
}
@Override
public void update( double delta ) {
for( Walker walker: walkers ) {
walker.update();
}
}
@Override
public void draw() {
drawing.clear(0, 5);
for( Walker walker: walkers ) {
walker.draw();
}
}
}

View File

@ -0,0 +1,12 @@
# Zeichenmaschine: GenLines
GenLines ist ein kreatives Projekt, bei dem ein Feld von Punkten durch geschickt
gewählte mathematische Formeln animiert wird.
Die Idee stammt von der Seite http://tixy.land
Dort finden sich auch weitere Beispiele für interessante Animationen.
## Verwendung

View File

@ -0,0 +1,50 @@
import schule.ngb.zm.*;
// TODO: Build Interface (like Drawable) that uses DrawingLayer instead of Graphics2D ?
public class Walker extends Constants {
public static final int SIZE = 8;
public static final int STEP = 6;
private static final Color[] colors = new Color[]{
Color.parseHexcode("#b13254"),
Color.parseHexcode("#ff5349"),
Color.parseHexcode("#ff7249"),
Color.parseHexcode("#ff9248")
};
private int x;
private int y;
private Color color;
private DrawingLayer drawing;
public Walker(DrawingLayer drawing) {
this(0, 0, drawing);
}
public Walker( int x, int y, DrawingLayer drawing) {
this.x = x;
this.y = y;
this.color = choice(colors);
this.drawing = drawing;
}
public void update() {
x += random(-STEP, STEP);
y += random(-STEP, STEP);
x = limit(x, 10, drawing.getWidth() - 10);
y = limit(y, 10, drawing.getHeight() - 10);
}
public void draw() {
drawing.setFillColor(color);
drawing.noStroke();
drawing.square(x, y, SIZE, MIDDLE);
}
}

View File

@ -0,0 +1,58 @@
#BlueJ package file
dependency1.from=GenLines
dependency1.to=MyTIXY
dependency1.type=UsesDependency
dependency2.from=GenLines
dependency2.to=Dot
dependency2.type=UsesDependency
dependency3.from=MyTIXY
dependency3.to=Dot
dependency3.type=UsesDependency
dependency4.from=Dot
dependency4.to=GenLines
dependency4.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=4
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=GenLines
target1.showInterface=false
target1.type=ClassTarget
target1.width=120
target1.x=120
target1.y=60
target2.height=70
target2.name=MyTIXY
target2.showInterface=false
target2.type=ClassTarget
target2.width=120
target2.x=200
target2.y=210
target3.height=70
target3.name=Dot
target3.showInterface=false
target3.type=ClassTarget
target3.width=120
target3.x=420
target3.y=140

View File

@ -1,8 +1,8 @@
#BlueJ package file
editor.fx.0.height=728
editor.fx.0.width=1037
editor.fx.0.x=95
editor.fx.0.y=53
editor.fx.0.height=0
editor.fx.0.width=0
editor.fx.0.x=0
editor.fx.0.y=0
objectbench.height=94
objectbench.width=776
package.divider.horizontal=0.6

View File

@ -1,15 +1,15 @@
#BlueJ package file
dependency1.from=TIXY
dependency1.from=GenLines
dependency1.to=MyTIXY
dependency1.type=UsesDependency
dependency2.from=TIXY
dependency2.from=GenLines
dependency2.to=Dot
dependency2.type=UsesDependency
dependency3.from=MyTIXY
dependency3.to=Dot
dependency3.type=UsesDependency
dependency4.from=Dot
dependency4.to=TIXY
dependency4.to=GenLines
dependency4.type=UsesDependency
editor.fx.0.height=728
editor.fx.0.width=1037
@ -36,7 +36,7 @@ readme.width=48
readme.x=10
readme.y=10
target1.height=70
target1.name=TIXY
target1.name=GenLines
target1.showInterface=false
target1.type=ClassTarget
target1.width=120

View File

@ -40,7 +40,7 @@ public class Dot implements Drawable {
color = DOT_WHITE;
}
value = Constants.limit(value, 1.0);
value = Constants.limit(value, 0.0, 1.0);
size = (int) (SIZE * value);
}
@ -51,7 +51,7 @@ public class Dot implements Drawable {
@Override
public void draw( Graphics2D graphics ) {
graphics.setColor(color.getColor());
graphics.setColor(color.getJavaColor());
graphics.fillOval(GAP + x * (SIZE + GAP) + RADIUS - (size / 2), GAP + y * (SIZE + GAP) + RADIUS - (size / 2), size, size);
}

View File

@ -1,6 +1,6 @@
# Zeichenmaschine: TIXY
# Zeichenmaschine: GenLines
TIXY ist ein kreatives Projekt, bei dem ein Feld von Punkten durch geschickt
GenLines ist ein kreatives Projekt, bei dem ein Feld von Punkten durch geschickt
gewählte mathematische Formeln animiert wird.
Die Idee stammt von der Seite http://tixy.land

View File

@ -60,4 +60,9 @@ public class TIXY extends Zeichenmaschine {
}
}
@Override
public void mousePressed() {
stop();
}
}

View File

@ -1,15 +1,15 @@
#BlueJ package file
dependency1.from=TIXY
dependency1.from=GenLines
dependency1.to=MyTIXY
dependency1.type=UsesDependency
dependency2.from=TIXY
dependency2.from=GenLines
dependency2.to=Dot
dependency2.type=UsesDependency
dependency3.from=MyTIXY
dependency3.to=Dot
dependency3.type=UsesDependency
dependency4.from=Dot
dependency4.to=TIXY
dependency4.to=GenLines
dependency4.type=UsesDependency
editor.fx.0.height=728
editor.fx.0.width=1037
@ -36,7 +36,7 @@ readme.width=48
readme.x=10
readme.y=10
target1.height=70
target1.name=TIXY
target1.name=GenLines
target1.showInterface=false
target1.type=ClassTarget
target1.width=120

View File

@ -0,0 +1,148 @@
import java.sql.*;
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Klasse DatabaseConnector
* </p>
* <p>
* Ein Objekt der Klasse DatabaseConnector ermoeglicht die Abfrage und Manipulation
* einer SQLite-Datenbank.
* Beim Erzeugen des Objekts wird eine Datenbankverbindung aufgebaut, so dass
* anschließend SQL-Anweisungen an diese Datenbank gerichtet werden koennen.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version 2016-01-24
*/
public class DatabaseConnector{
private Connection connection;
private QueryResult currentQueryResult = null;
private String message = null;
/**
* Ein Objekt vom Typ DatabaseConnector wird erstellt, und eine Verbindung zur Datenbank
* wird aufgebaut. Mit den Parametern pIP und pPort werden die IP-Adresse und die
* Port-Nummer uebergeben, unter denen die Datenbank mit Namen pDatabase zu erreichen ist.
* Mit den Parametern pUsername und pPassword werden Benutzername und Passwort fuer die
* Datenbank uebergeben.
*/
public DatabaseConnector(String pIP, int pPort, String pDatabase, String pUsername, String pPassword){
//Eine Impementierung dieser Schnittstelle fuer SQLite ignoriert pID und pPort, da die Datenbank immer lokal ist.
//Auch pUsername und pPassword werden nicht verwendet, da SQLite sie nicht unterstuetzt.
try {
//Laden der Treiberklasse
Class.forName("org.sqlite.JDBC");
//Verbindung herstellen
connection = DriverManager.getConnection("jdbc:sqlite:"+pDatabase);
} catch (Exception e) {
message = e.getMessage();
}
}
/**
* Der Auftrag schickt den im Parameter pSQLStatement enthaltenen SQL-Befehl an die
* Datenbank ab.
* Handelt es sich bei pSQLStatement um einen SQL-Befehl, der eine Ergebnismenge
* liefert, so kann dieses Ergebnis anschließend mit der Methode getCurrentQueryResult
* abgerufen werden.
*/
public void executeStatement(String pSQLStatement){
//Altes Ergebnis loeschen
currentQueryResult = null;
message = null;
try {
//Neues Statement erstellen
Statement statement = connection.createStatement();
//SQL Anweisung an die DB schicken.
if (statement.execute(pSQLStatement)) { //Fall 1: Es gibt ein Ergebnis
//Resultset auslesen
ResultSet resultset = statement.getResultSet();
//Spaltenanzahl ermitteln
int columnCount = resultset.getMetaData().getColumnCount();
//Spaltennamen und Spaltentypen in Felder uebertragen
String[] resultColumnNames = new String[columnCount];
String[] resultColumnTypes = new String[columnCount];
for (int i = 0; i < columnCount; i++){
resultColumnNames[i] = resultset.getMetaData().getColumnLabel(i+1);
resultColumnTypes[i] = resultset.getMetaData().getColumnTypeName(i+1);
}
//Queue fuer die Zeilen der Ergebnistabelle erstellen
Queue<String[]> rows = new Queue<String[]>();
//Daten in Queue uebertragen und Zeilen zaehlen
int rowCount = 0;
while (resultset.next()){
String[] resultrow = new String[columnCount];
for (int s = 0; s < columnCount; s++){
resultrow[s] = resultset.getString(s+1);
}
rows.enqueue(resultrow);
rowCount = rowCount + 1;
}
//Ergebnisfeld erstellen und Zeilen aus Queue uebertragen
String[][] resultData = new String[rowCount][columnCount];
int j = 0;
while (!rows.isEmpty()){
resultData[j] = rows.front();
rows.dequeue();
j = j + 1;
}
//Statement schließen und Ergebnisobjekt erstellen
statement.close();
currentQueryResult = new QueryResult(resultData, resultColumnNames, resultColumnTypes);
} else { //Fall 2: Es gibt kein Ergebnis.
//Statement ohne Ergebnisobjekt schliessen
statement.close();
}
} catch (Exception e) {
//Fehlermeldung speichern
message = e.getMessage();
}
}
/**
* Die Anfrage liefert das Ergebnis des letzten mit der Methode executeStatement an
* die Datenbank geschickten SQL-Befehls als Ob-jekt vom Typ QueryResult zurueck.
* Wurde bisher kein SQL-Befehl abgeschickt oder ergab der letzte Aufruf von
* executeStatement keine Ergebnismenge (z.B. bei einem INSERT-Befehl oder einem
* Syntaxfehler), so wird null geliefert.
*/
public QueryResult getCurrentQueryResult(){
return currentQueryResult;
}
/**
* Die Anfrage liefert null oder eine Fehlermeldung, die sich jeweils auf die letzte zuvor ausgefuehrte
* Datenbankoperation bezieht.
*/
public String getErrorMessage(){
return message;
}
/**
* Die Datenbankverbindung wird geschlossen.
*/
public void close(){
try{
connection.close();
} catch (Exception e) {
message = e.getMessage();
}
}
}

View File

@ -0,0 +1,76 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Klasse QueryResult
* </p>
* <p>
* Ein Objekt der Klasse QueryResult stellt die Ergebnistabelle einer Datenbankanfrage mit Hilfe
* der Klasse DatabaseConnector dar. Objekte dieser Klasse werden nur von der Klasse DatabaseConnector erstellt.
* Die Klasse verfuegt ueber keinen oeffentlichen Konstruktor.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version 2015-01-31
*/
public class QueryResult{
private String[][] data;
private String[] columnNames;
private String[] columnTypes;
/**
* Paketinterner Konstruktor.
*/
QueryResult(String[][] pData, String[] pColumnNames, String[] pColumnTypes){
data = pData;
columnNames = pColumnNames;
columnTypes = pColumnTypes;
}
/**
* Die Anfrage liefert die Eintraege der Ergebnistabelle als zweidimensionales Feld
* vom Typ String. Der erste Index des Feldes stellt die Zeile und der zweite die
* Spalte dar (d.h. Object[zeile][spalte]).
*/
public String[][] getData(){
return data;
}
/**
* Die Anfrage liefert die Bezeichner der Spalten der Ergebnistabelle als Feld vom
* Typ String zurueck.
*/
public String[] getColumnNames(){
return columnNames;
}
/**
* Die Anfrage liefert die Typenbezeichnung der Spalten der Ergebnistabelle als Feld
* vom Typ String zurueck. Die Bezeichnungen entsprechen den Angaben in der MySQL-Datenbank.
*/
public String[] getColumnTypes(){
return columnTypes;
}
/**
* Die Anfrage liefert die Anzahl der Zeilen der Ergebnistabelle als Integer.
*/
public int getRowCount(){
if (data != null )
return data.length;
else
return 0;
}
/**
* Die Anfrage liefert die Anzahl der Spalten der Ergebnistabelle als Integer.
*/
public int getColumnCount(){
if (data != null && data.length > 0 && data[0] != null)
return data[0].length;
else
return 0;
}
}

142
examples/zm_wahlkamp/Queue.java Executable file
View File

@ -0,0 +1,142 @@
/**
* <p>
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
* </p>
* <p>
* Generische Klasse Queue<ContentType>
* </p>
* <p>
* Objekte der generischen Klasse Queue (Warteschlange) verwalten beliebige
* Objekte vom Typ ContentType nach dem First-In-First-Out-Prinzip, d.h., das
* zuerst abgelegte Objekt wird als erstes wieder entnommen. Alle Methoden haben
* eine konstante Laufzeit, unabhaengig von der Anzahl der verwalteten Objekte.
* </p>
*
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version Generisch_02 2014-02-21
*/
public class Queue<ContentType> {
/* --------- Anfang der privaten inneren Klasse -------------- */
private class QueueNode {
private ContentType content = null;
private QueueNode nextNode = null;
/**
* Ein neues Objekt vom Typ QueueNode<ContentType> wird erschaffen.
* Der Inhalt wird per Parameter gesetzt. Der Verweis ist leer.
*
* @param pContent das Inhaltselement des Knotens vom Typ ContentType
*/
public QueueNode(ContentType pContent) {
content = pContent;
nextNode = null;
}
/**
* Der Verweis wird auf das Objekt, das als Parameter uebergeben wird,
* gesetzt.
*
* @param pNext der Nachfolger des Knotens
*/
public void setNext(QueueNode pNext) {
nextNode = pNext;
}
/**
* Liefert das naechste Element des aktuellen Knotens.
*
* @return das Objekt vom Typ QueueNode, auf das der aktuelle Verweis zeigt
*/
public QueueNode getNext() {
return nextNode;
}
/**
* Liefert das Inhaltsobjekt des Knotens vom Typ ContentType.
*
* @return das Inhaltsobjekt des Knotens
*/
public ContentType getContent() {
return content;
}
}
/* ----------- Ende der privaten inneren Klasse -------------- */
private QueueNode head;
private QueueNode tail;
/**
* Eine leere Schlange wird erzeugt.
* Objekte, die in dieser Schlange verwaltet werden, muessen vom Typ
* ContentType sein.
*/
public Queue() {
head = null;
tail = null;
}
/**
* Die Anfrage liefert den Wert true, wenn die Schlange keine Objekte enthaelt,
* sonst liefert sie den Wert false.
*
* @return true, falls die Schlange leer ist, sonst false
*/
public boolean isEmpty() {
return head == null;
}
/**
* Das Objekt pContentType wird an die Schlange angehaengt.
* Falls pContentType gleich null ist, bleibt die Schlange unveraendert.
*
* @param pContent
* das anzuhaengende Objekt vom Typ ContentType
*/
public void enqueue(ContentType pContent) {
if (pContent != null) {
QueueNode newNode = new QueueNode(pContent);
if (this.isEmpty()) {
head = newNode;
tail = newNode;
} else {
tail.setNext(newNode);
tail = newNode;
}
}
}
/**
* Das erste Objekt wird aus der Schlange entfernt.
* Falls die Schlange leer ist, wird sie nicht veraendert.
*/
public void dequeue() {
if (!this.isEmpty()) {
head = head.getNext();
if (this.isEmpty()) {
head = null;
tail = null;
}
}
}
/**
* Die Anfrage liefert das erste Objekt der Schlange.
* Die Schlange bleibt unveraendert.
* Falls die Schlange leer ist, wird null zurueckgegeben.
*
* @return das erste Objekt der Schlange vom Typ ContentType oder null,
* falls die Schlange leer ist
*/
public ContentType front() {
if (this.isEmpty()) {
return null;
} else {
return head.getContent();
}
}
}

View File

@ -0,0 +1,75 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Zeichenmaschine;
import schule.ngb.zm.charts.*;
public class Wahlkampf extends Zeichenmaschine {
public static void main( String[] args ) {
new Wahlkampf();
}
public Wahlkampf() {
super(800, 800, "Landtagswahl 2022 in Bielefeld");
}
public void draw() {
background.setColor(240);
DatabaseConnector dbc = new DatabaseConnector("", 0, "wahlergebnisse.db", "", "");
QueryResult res;
String[] parteien = new String[]{"CDU", "SPD", "FDP", "AfD", "GRÜNE", "DIELINKE", "PIRATEN"};
Color[] farben = new Color[]{BLACK, RED, YELLOW, BLUE, GREEN, MAGENTA, ORANGE};
// Erststimmen im Bezirk
StringBuilder sb = new StringBuilder("SELECT ");
for( int i = 0; i < parteien.length; i++ ) {
sb.append("SUM(");
sb.append('"');
sb.append('D');
sb.append(i+1);
sb.append('-');
sb.append(parteien[i]);
sb.append("Erstimmen");
sb.append('"');
sb.append(')');
if( i < parteien.length-1 ) {
sb.append(',');
}
}
sb.append(" FROM \"2022_Landtagswahl\"");
dbc.executeStatement(sb.toString());
res = dbc.getCurrentQueryResult();
if( res != null ) {
String[] data = res.getData()[0];
double[] values = new double[parteien.length];
for( int i = 0; i < data.length; i++ ) {
values[i] = Double.parseDouble(data[i]);
}
RingChart chart1 = new RingChart(200, 200, 100, parteien.length);
RingChart chart2 = new RingChart(600, 200, 100, parteien.length);
RingChart chart3 = new RingChart(200, 600, 100, parteien.length);
RingChart chart4 = new RingChart(600, 600, 100, parteien.length);
double s = sum(values);
for( int i = 0; i < values.length; i++ ) {
double value = values[i];
chart1.setValue(i, value, s, parteien[i], farben[i]);
chart2.setValue(i, value, s, parteien[i], farben[i]);
chart3.setValue(i, value, s, parteien[i], farben[i]);
chart4.setValue(i, value, s, parteien[i], farben[i]);
}
chart4.setStrokeColor(200);
shapes.add(chart1, chart2, chart3, chart4);
} else {
System.err.println(dbc.getErrorMessage());
}
pause();
}
}

View 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

Binary file not shown.