6 Commits

Author SHA1 Message Date
c9a7ac9551 Partikel Beispiel 2022-06-19 22:45:53 +02:00
c6615cc817 Sprache zu Englisch geändert 2022-06-19 22:37:08 +02:00
4d981b62a4 Merge branch 'main' into partikel 2022-06-19 22:30:40 +02:00
05aae6e6cc Merge branch 'main' into partikel 2021-12-23 11:17:55 +01:00
5e42509f75 Partikel Test Programm 2021-12-23 11:13:59 +01:00
e2bdf1e998 Partikelsystem 2021-12-23 09:26:27 +01:00
254 changed files with 7220 additions and 12157 deletions

16
.gitignore vendored
View File

@@ -32,19 +32,3 @@ hs_err_pid*
.DS_Store
._*
Thumbs.db
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache

View File

@@ -6,46 +6,11 @@ und diese Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]
### Added
- System für EventListener erstellt
- `AudioListener` und `AnimationListener` als erste Anwendungsfälle.
- Pakete für Animationen und Maschinelles-Lernen hinzugefügt
### Changed
- `update(double)` und `draw()` werden nun in einem eigenen Thread aufgerufen.
## Version 0.0.22
### Added
- Interface `Audio` extrahiert, mit Basisfunktionen von `Sound` und `Music`.
- Klasse `Mixer` steuert mehrere Audio-Objekte gleichzeitig.
- Klasse `tasks.RateLimitedTask`, `tasks.FramerateLimitedTask`, `tasks.FrameSynchronizedTask` und `tasks.DelayedTask`.
### Changed
- Neue Package-Struktur:
- `schule.ngb.zm.media` für Audio-Klassen (und ggf. zukünftig Video).
- `schule.ngb.zm.tasks` für alles Rund um Parallelität.
- `Zeichenthread` und `TaskRunner` setzen die Namen der Threads für besseres Debugging.
### Removed
- Beispielprojekte in [eigenes Repository](https://github.com/jneug/zeichenmaschine-examples) verschoben.
## Version 0.0.21
### Added
- Parameter `stop_after_draw` im Konstruktor der `Zeichenmaschine` erlaubt es beim Erstellen festzulegen, ob nach dem ersten Frame die Zeichenmaschine gestoppt wird.
- `Picture.tint(Color)` färbt ein Bild ein.
- `Picture.flip(Options.Direction)` spiegelt ein Bild entlang einer Achse (`LEFT`/`RIGHT` für horizontal, `UP`/`DOWN` für vertikal).
- Abstrakte Klasse `Zeichenobjekt` als einheitliche Oberklasse für Objekte in Projekten. Die Klasse erbt von `Constants` und implementiert `Drawabale` und `Updatable` mit leeren Methoden.
- Klasse `java.util.Validator` übernimmt intern Parametervalidierung.
- Klasse `Log` implementiert eine einfache Logging-API über `java.util.logging`.
- Klasse `TaskRunner` führt parallele Prozesse aus.
- `Zeichenmaschine#scheduleTask(Runnable, int)` führt eine Aufgabe nach einer Wartezeit im Gameloop aus.
- Neue Klasse `util.ResourceStreamProvider` sucht Resourcen und öffnet `InputStream`s.
- Abstrakte Klasse `Zeichenobjekt` als einheitliche Oberklasse für Objekte in Projekten. Die Klasse erbt von `Constants` und implementiert `Drawabale` und `Updatable` mit leeren Methoden.
### Changed
- Objektvariablen der `Zeichenmaschine`, die von Unterklassen genutzt werden sollen, sind nun statisch in `Constants`. Dadurch können auch andere Klasse, die von `Constants` erben ohne Umwege auf diese Werte zugreifen (z.B. `width`/`height` der Zeichenleinwand).
- `ImageLoader` und `FontLoader` wurden überarbeitet.
- Nutzung von `Log`
- Nutzung von `ResourceStreamProvider`
- Verarbeitung von Swing `InputEvent`s in einer eigenen interne EventQueue synchron zur Framerate.
- Objektvariablen der `Zeichenmaschine`, die von Unterklassen genutzt werden sollen, sind nun statisch in `Constants`. Dadurch können auch andere Klasse, die von `Constants` erben ohne Umwege auf diese Werte zugreifen (z.B. `width`/`height` der Zeichenleinwand).

View File

@@ -1,46 +0,0 @@
plugins {
id 'idea'
id 'java-library'
}
/*properties {
zmVersion {
major = 0;
minor = 0;
rev = 21;
}
}*/
group 'schule.ngb'
version '0.0.22-SNAPSHOT'
//version '{$zmVersion.major}.{$zmVersion.minor}.{$zmVersion.rev}-SNAPSHOT'
compileJava {
options.release = 11
}
repositories {
mavenCentral()
}
dependencies {
runtimeOnly 'com.googlecode.soundlibs:jlayer:1.0.1.4'
runtimeOnly 'com.googlecode.soundlibs:tritonus-share:0.3.7.4'
runtimeOnly 'com.googlecode.soundlibs:mp3spi:1.9.5.4'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
test {
useJUnitPlatform()
}
tasks.register('jarMP3SPI', Jar) {
archiveClassifier = 'all'
duplicatesStrategy = 'exclude'
archivesBaseName = 'zeichenmaschine-mp3spi'
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}

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

@@ -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();
}
}

View File

@@ -0,0 +1,110 @@
import schule.ngb.zm.Vector;
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 {
/**
* Gravitationskonstante
* <p>
* Beeinflusst die Stärke der Anziehungskraft der {@link Attractor}en.
*/
public static final int G = 25;
/**
* Ob dieser <code>Attractor</code> auch von anderen Kräften beeinflusst wird.
*/
private boolean movable = true;
/**
* 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());
}
/**
* 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;
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.lengthSq();
force.setLength(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 transform ) {
double m = 2.0*mass;
AffineTransform at = graphics.getTransform();
graphics.transform(transform);
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, transform);
}
}

View File

@@ -0,0 +1,92 @@
import schule.ngb.zm.Vector;
import schule.ngb.zm.Zeichenmaschine;
import java.util.LinkedList;
/**
* Hauptklasse der Simulation.
*/
public class Gravity extends Zeichenmaschine {
/**
* 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() {
background.setColor(randomNiceColor());
for( Mover m : movers ) {
m.moveTo(random(10, width - 10), 30);
m.setVelocity(mouseX-m.getX(), mouseY-m.getY());
m.getVelocity().setLength(4.0);
}
}
public static void main( String[] args ) {
new Gravity();
}
}

View File

@@ -0,0 +1,186 @@
import schule.ngb.zm.Updatable;
import schule.ngb.zm.Vector;
import schule.ngb.zm.shapes.Arrow;
import schule.ngb.zm.shapes.Circle;
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 {
/**
* Größe der Objekte in der Simulation.
*/
public static final int SIZE = 10;
/**
* Ob die momentane Geschwindigkeit der Objekte als Pfeil dargestellt werden soll.
*/
public static final boolean SHOW_VELOCITY = true;
/**
* 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);
if( velocity.length() > 0.5 ) {
this.x += velocity.x;
this.y += velocity.y;
}
}
@Override
public void draw( Graphics2D graphics, AffineTransform transform ) {
if( SHOW_VELOCITY ) {
Vector v = velocity.copy().scale(10);
Arrow ar = new Arrow(v);
AffineTransform af = new AffineTransform(transform);
af.translate(radius, radius);
ar.draw(graphics, af);
}
super.draw(graphics, transform);
}
}

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,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

@@ -0,0 +1,257 @@
import schule.ngb.zm.Color;
import schule.ngb.zm.Zeichenmaschine;
/**
* Eine Bildergallerie von Bildern eines Informatikkurses des 10. Jahrgangs.
*/
public class Gallery extends Zeichenmaschine {
public static void main(String[] args) {
new Gallery();
}
public void setup() {
setSize(600, 600);
setTitle("ZM: Gallery");
}
/**
* Wählt ein zufälliges Bild aus und zeigt es an.
*/
public void draw() {
drawRandom();
}
/**
* Zeigt ein zufälliges Bild an.
*/
public void drawRandom() {
switch (random(0, 4)) {
case 0:
rainbow();
break;
case 1:
snowman();
break;
case 2:
deathstar();
break;
case 3:
prideflag();
break;
}
}
/**
* Bei Betätigen der Leertaste ein Zufallsbild anzeigen.
*/
public void keyPressed() {
if (keyCode == 32) {
drawRandom();
}
}
/**
* Startet eine fortlaufende Präsentation aller Bilder.
*
* @param pWartezeit Die Wartezeit zum nächsten Bildwechsel in Millisekunden.
*/
public void slideshow(int pWartezeit) {
int i = 0;
while (true) {
switch (i) {
case 0:
rainbow();
break;
case 1:
snowman();
break;
case 2:
deathstar();
break;
case 3:
prideflag();
break;
}
i = (i + 1) % 4;
delay(pWartezeit);
}
}
/**
* Regenbogen
* <p>
* von
*/
public void rainbow() {
// Blauer Hintergrund
drawing.clear(60, 155, 217);
// Einige Werte berechnen, um Bild an Bildgröße anzupassen
double size = (width + height) * 0.03333;
double r = width / 2.0;
// Kleiner werdende Kreise in den Farben des Bogens zeichnen
drawing.noStroke();
drawing.setFillColor(207, 71, 67);
drawing.circle(width / 2.0, height, r - 1 * size);
drawing.setFillColor(235, 134, 42);
drawing.circle(width / 2.0, height, r - 2 * size);
drawing.setFillColor(234, 181, 58);
drawing.circle(width / 2.0, height, r - 3 * size);
// Mitte mit "himmelfarbe" übermalen, um Ringe zu erzeugen
drawing.setFillColor(60, 155, 217);
drawing.circle(width / 2.0, height, r - 4 * size);
// Sonne zeichnen
drawing.setFillColor(232, 200, 52);
drawing.circle(width * 0.8333, size * 2.6666, size * 2);
// Bild auf Leinwand übertragen
redraw();
}
/**
* LGBTQ-Flagge
* <p>
* von
*/
public void prideflag() {
// Schwarzer Hintergrund
drawing.clear(0);
drawing.setStrokeColor(0);
// Farben der Streifen festlegen
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;
// Flaggenstab zeichnen
drawing.setFillColor(BROWN);
drawing.rect(borderX, borderY, size, height - 2 * borderY, NORTHWEST);
// Streifen zeichnen
for (int i = 0; i < colors.length; i++) {
drawing.setFillColor(colors[i]);
drawing.rect(borderX, borderY + i * size, width - 2 * borderX, size, NORTHWEST);
}
// Bild auf Leinwand übertragen
redraw();
}
/**
* Todesstern
* <p>
* von Niklas, Henry und Ben
*/
public void deathstar() {
// Sternenhimmel zeichnen
drawing.clear(0);
drawing.noStroke();
drawing.setFillColor(WHITE);
// Zufällig erzeugte Sterne
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, 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;
// Korpus zeichnen
drawing.setFillColor(128);
drawing.circle(width / 2.0, height / 2.0, radius);
// Graben am Äquator zeichnen
drawing.setStrokeColor(0);
drawing.setStrokeWeight(1.4);
drawing.arc(width / 2.0, height / 2.0, radius + radius, r2, 180, 360);
// Schüssel zeichnen
drawing.setFillColor(96);
drawing.circle(w2 + r2, h2 - r3, r4);
drawing.setFillColor(84);
drawing.circle(w2 + r2 + 2, h2 - r3 - 2, r10);
// Strahlen des Lasers zeichnen
int beams = 8; // Anzahl Strahlen
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);
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);
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);
}
// Hauptstrahl
drawing.setStrokeColor(GREEN);
drawing.setStrokeType(SOLID);
drawing.setStrokeWeight(4);
drawing.line(w2 + r2 + 2 + r5, h2 - r3 - 2 - r5, width, h2 - w2 + radius / 6.0);
drawing.setStrokeWeight(1);
drawing.setStrokeColor(255);
drawing.line(w2 + r2 + 2 + r5, h2 - r3 - 2 - r5, width, h2 - w2 + radius / 6.0);
// Bild auf Leinwand übertragen
redraw();
}
/**
* Schneemann
* <p>
* von
*/
public void snowman() {
// Hellblauer Hintergrund
drawing.clear(219, 253, 255);
drawing.noStroke();
drawing.setFillColor(255);
// Drei Schneekugeln
drawing.circle(width / 2.0, height - 100, 100);
drawing.circle(width / 2.0, height - 180 - 60, 60);
drawing.circle(width / 2.0, height - 180 - 110 - 40, 40);
// Zwei Augen
drawing.setFillColor(0);
drawing.circle(width / 2.0 - 15, height - 345, 4);
drawing.circle(width / 2.0 + 15, height - 345, 4);
// Nase
drawing.setFillColor(255, 147, 0);
drawing.triangle(width / 2.0, height - 335, width / 2.0 - 5, height - 330, width / 2.0 + 5, height - 330);
// Bild auf Leinwand übertragen
redraw();
}
}

View File

@@ -0,0 +1,22 @@
# Zeichenmaschine: Gallery
Die Bildergallerie ist eine Sammlung statischer Bilder, die mit der
Zeichenmaschine programmiert wurden.
Die Bilder selbst wurden von einem Informatikkurs des Jahrgangs 10 in
Processing (https://processing.org) erstellt und für dieses Beispielprojekt
auf die Zeichenmaschine angespasst.
Die Autoren der Bilder sind:
- Schneemann:
- Todesstern
- Regenbogen:
- LGBTQ-Flagge:
## Verwendung
Beim Start wird eines der vorhandenen Bilder ausgewählt und angezeigt.
Mit der Methode "slideshow()" wird eine fortlaufende Präsentation der Bilder
gestartet. Die Wartezeit bis zum nächsten Bildwechsel kann als Parameter in
Millisekunden angegeben werden.

View File

@@ -0,0 +1,32 @@
#BlueJ package file
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
package.divider.vertical=0.8305369127516778
package.editor.height=488
package.editor.width=661
package.editor.x=0
package.editor.y=0
package.frame.height=660
package.frame.width=800
package.numDependencies=0
package.numTargets=1
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=Gallery
target1.showInterface=false
target1.type=ClassTarget
target1.width=120
target1.x=70
target1.y=10

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

@@ -0,0 +1,30 @@
import schule.ngb.zm.DrawableLayer;
import schule.ngb.zm.Zeichenmaschine;
import schule.ngb.zm.partikel.PartikelGenerator;
public class PartikelBeispiel extends Zeichenmaschine {
public static void main( String[] args ) {
new PartikelBeispiel();
}
public PartikelBeispiel() {
super(400, 400, "ZM: Partikel");
}
PartikelGenerator pgen;
public void setup() {
pgen = new PartikelGenerator(200, 200, 3, 20);
DrawableLayer drawables = new DrawableLayer();
addLayer(drawables);
drawables.add(pgen);
pgen.starten();
}
@Override
public void update( double delta ) {
pgen.update(delta);
}
}

View File

@@ -0,0 +1,14 @@
# Zeichenmaschine: Raindrops
Raindrops ist ein einfaches Spiel, bei dem Regentropfen vom Himmel fallen,
die von der Spieler:in mit einem Eimer aufgefangen werden müssen.
Das Spiel wird nach und nach schwerer (mehr Tropfen, höheres Tempo), bis die
Spieler:in zu viele Tropfen fallen gelassen hat.
Diese Variante des Spiels ist mit dem DrawingLayer implementiert.
Eine objektorientierte Version ist im Beispielprojekt zm_raindrops_oop zu finden.
## Quellen
- raindrop.png by @lagartoflojo (https://openclipart.org/detail/4063/water-drop)
- bucket.png

View File

@@ -0,0 +1,183 @@
import schule.ngb.zm.Zeichenmaschine;
public class Raindrops extends Zeichenmaschine {
/**
* Zähler für die gefangenen und fallen gelassenen Tropfen.
*/
int catched = 0, dropped = 0;
/**
* Startgeschwindigkeit, in der die Tropfen fallen.
*
* Die Tropfen fallen pro Frame (also ungefähr 60-mal pro Sekunde).
*/
double drop_speed = 1.0;
/**
* Objektvariablen für die Positionen der fünf Tropfen.
*/
double x1 = random(10, 390), y1 = 10;
double x2 = random(10, 390), y2 = -60;
double x3 = random(10, 390), y3 = -100;
double x4 = random(10, 390), y4 = -170;
double x5 = random(10, 390), y5 = -230;
/**
* Wird zu Beginn aufgerufen, um das Spiel zu initialisieren.
*/
public void setup() {
setSize(400, 600);
setTitle("ZM: Raindrops");
hideCursor();
drawing.setFontSize(64);
}
/**
* Aktualisiert die Position der Tropfen und prüft, ob die Tropfen mit dem
* Eimer oder dem Boden kollidieren. Ist dies der Fall, wird der Tropfen
* wieder "nach oben" befördert und der entsprechende Zähler wird um eins
* erhöht. Anschließend wird geprüft, ob die Geschwindigkeit erhöht werden
* muss, oder ob das Spiel verloren wurde.
*/
public void update( double delta ) {
// Tropfen bewegen
y1 += drop_speed;
y2 += drop_speed;
y3 += drop_speed;
y4 += drop_speed;
y5 += drop_speed;
// Kollision mit Eimer prüfen (Tropfen 1)
if( x1 > mouseX-20 && x1 < mouseX+20 && y1 > 520 && y1 < 560 ) {
x1 = random(10, 390);
y1 = -10;
catched += 1;
// Nächster Level?
if( catched > 0 && catched%10 == 0 ) {
drop_speed += 2;
}
} else if( y1 > 560 ) {
x1 = random(10, 390);
y1 = -10;
dropped += 1;
}
// Kollision mit Eimer prüfen (Tropfen 2)
if( x2 > mouseX-20 && x2 < mouseX+20 && y2 > 520 && y2 < 560 ) {
x2 = random(10, 390);
y2 = -10;
catched += 1;
// Nächster Level?
if( catched > 0 && catched%10 == 0 ) {
drop_speed += 2;
}
} else if( y2 > 560 ) {
x2 = random(10, 390);
y2 = -10;
dropped += 1;
}
// Kollision mit Eimer prüfen (Tropfen 3)
if( x3 > mouseX-20 && x3 < mouseX+20 && y3 > 520 && y3 < 560 ) {
x3 = random(10, 390);
y3 = -10;
catched += 1;
// Nächster Level?
if( catched > 0 && catched%10 == 0 ) {
drop_speed += 2;
}
} else if( y3 > 560 ) {
x3 = random(10, 390);
y3 = -10;
dropped += 1;
}
// Kollision mit Eimer prüfen (Tropfen 4)
if( x4 > mouseX-20 && x4 < mouseX+20 && y4 > 520 && y4 < 560 ) {
x4 = random(10, 390);
y4 = -10;
catched += 1;
// Nächster Level?
if( catched > 0 && catched%10 == 0 ) {
drop_speed += 2;
}
} else if( y4 > 560 ) {
x4 = random(10, 390);
y4 = -10;
dropped += 1;
}
// Kollision mit Eimer prüfen (Tropfen 5)
if( x5 > mouseX-20 && x5 < mouseX+20 && y5 > 520 && y5< 560 ) {
x5 = random(10, 390);
y5 = -10;
catched += 1;
// Nächster Level?
if( catched > 0 && catched%10 == 0 ) {
drop_speed += 2;
}
} else if( y5 > 560 ) {
x5 = random(10, 390);
y5 = -10;
dropped += 1;
}
// Game over?
if( dropped >= 13 ) {
stop(); // Stoppt das Spiel und ruft teardown() auf
}
}
/**
* Zeichnet die Spielszene (hintergrund, Eimer, Tropfen, Zähler)
*/
public void draw() {
// Hintergrund blaugrau
drawing.clear(129, 174, 206);
// Boden zeichnen
drawing.setFillColor(0, 144, 81);
drawing.noStroke();
drawing.rect(0, height - 40, width, 40, NORTHWEST);
// Eimer zeichnen
drawing.image("bucket.png", mouseX, 540, 0.25);
// Tropfen zeichnen
drawing.image("raindrop.png", x1, y1, 0.1);
drawing.image("raindrop.png", x2, y2, 0.1);
drawing.image("raindrop.png", x3, y3, 0.1);
drawing.image("raindrop.png", x4, y4, 0.1);
drawing.image("raindrop.png", x5, y5, 0.1);
// Punktezähler
drawing.setFillColor(0);
drawing.text(""+catched, 10, 10, NORTHWEST);
drawing.text(""+dropped, 390, 10, NORTHEAST);
}
/**
* Wird nach dem Aufruf von {@code stop()} aufgerufen.
*/
public void teardown() {
// Alles löschen
drawing.clear(129, 174, 206);
// Text anzeigen (Punkte und Zeit)
drawing.setFillColor(33);
drawing.setFontSize(64);
drawing.text("Game Over!", 200, 300);
drawing.setFontSize(32);
drawing.text("Punkte: " + catched, 200, 364);
drawing.text("Zeit: " + (runtime/1000.0), 200, 396);
redraw();
}
public static void main( String[] args ) {
new Raindrops();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -0,0 +1,32 @@
#BlueJ package file
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
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=0
package.numTargets=1
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=Raindrops
target1.showInterface=false
target1.type=ClassTarget
target1.width=120
target1.x=70
target1.y=10

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -0,0 +1,13 @@
import schule.ngb.zm.shapes.Picture;
public class Bucket extends Picture {
public Bucket( int x, int y ) {
super(x, y, "bucket.png");
}
public boolean contains( Drop pDrop ) {
return getBounds().contains(pDrop.getX(), pDrop.getY());
}
}

View File

@@ -0,0 +1,45 @@
import schule.ngb.zm.Updatable;
import schule.ngb.zm.shapes.Picture;
public class Drop extends Picture implements Updatable {
public static final double SPEED_PIXELPERSECOND = 100.0;
public static final double SPEED_INCREASE = 1.2;
public static final int START_Y = 40;
private double speed = SPEED_PIXELPERSECOND;
private boolean active = false;
public Drop() {
super(0, 0, "raindrop.png");
hide();
}
public void increaseSpeed() {
this.speed *= SPEED_INCREASE;
}
public void activate() {
this.active = true;
}
public void reset() {
moveTo(random(Raindrops.GAME_BORDER, Raindrops.GAME_WIDTH - Raindrops.GAME_BORDER), START_Y);
show();
}
@Override
public boolean isActive() {
return active;
}
@Override
public void update( double delta ) {
y += speed * delta;
}
}

Some files were not shown because too many files have changed in this diff Show More