179 Commits

Author SHA1 Message Date
e2e6f8c291 Bug: Synchronized Methoden verschoben 2022-07-26 18:15:23 +02:00
916a581768 Refactorings 2022-07-26 18:14:59 +02:00
5bb2f75193 Bug: getShapes in ShapeGroup war immer leer 2022-07-26 18:14:50 +02:00
f0e4cd6c80 Refactoring des Beendens der ZM 2022-07-26 18:14:23 +02:00
a228b21c84 Verantwortlichkeiten für Layout und Aufgaben klarer getrennt 2022-07-26 08:59:30 +02:00
68c88ec9ca Merge branch 'main' into zeichenfenster
# Conflicts:
#	src/main/java/schule/ngb/zm/media/Sound.java
2022-07-25 19:07:51 +02:00
0d1dd771dd Logger eingefügt 2022-07-25 19:06:01 +02:00
e995bfc4fe Bug: Spielemaschine blockt nicht mehr nebenläufige Threads 2022-07-25 19:05:54 +02:00
97ff03990a Shape caching entfernt
In Tests konnten keine Geschwindigkeitsvorteile festgestellt werden.
2022-07-25 19:05:28 +02:00
bd2364a8df Laden von Schriftarten mit eigenem Namen möglich 2022-07-25 19:05:04 +02:00
617b915874 Refactorings zur Nebenläufigkeit 2022-07-25 17:45:39 +02:00
7772793e8d Kommentar 2022-07-25 17:44:31 +02:00
bd8c0e37a7 Audio-Methoden synchronisiert 2022-07-25 17:44:22 +02:00
ecbe2b4f6b interpolate zu animate umbenannt
Animation erbt zur Vereinfachung nun auch von Constants und dort gibt es schon eine interpolate Methode.
2022-07-25 17:42:06 +02:00
20fe700756 Rechtschreibung und standard Log-Format 2022-07-25 17:41:18 +02:00
0100a3f574 Methode um mehrere Animationen im ShapesLayer zu starten 2022-07-25 17:41:01 +02:00
aceb79c44f Animate Methode zu play umbenannt 2022-07-25 17:40:42 +02:00
a4e29ccdba Loader KLassen in io Paket verschoben 2022-07-25 17:38:53 +02:00
55014c8eec Klasse Zeichenfenster ausgelagert 2022-07-25 17:35:46 +02:00
4f958cd57c ImageLoaders in io Paket verschoben 2022-07-21 22:01:54 +02:00
04506f6e9c JFrame in eine eigene Klasse ausgelagert 2022-07-21 22:01:38 +02:00
5a27e18634 Javadoc und kleine Refactorings 2022-07-21 21:02:50 +02:00
8b23c658e8 Animator Interface entfernt 2022-07-21 21:02:30 +02:00
1ca13c977a Javadoc 2022-07-21 21:02:10 +02:00
78c93666d0 Javadoc 2022-07-21 21:01:46 +02:00
917eb805c6 Bug: Threadsafety 2022-07-21 21:01:33 +02:00
fddd8d621b flush() nach jeder Log-Nachricht
Der Logger sendet nun nach jedem Log die Nachricht zum OutputStream.
2022-07-21 21:00:55 +02:00
4bf0068051 Icons werden nun in allen Größen geladen
Alle vorhandenen Icons werden geladen und mit Jframe.setIconImages() dem Fenster hinzugefügt. Unter macOS wird nur die Größe 512 geladen und als Dock-Icon gesetzt.
2022-07-21 20:59:28 +02:00
371a962432 Syncronisation des Zeichenthreads mit update/draw über eigenen Zustand
delay() setzt den Zustand auf DELAYED und der Zeichenthread läuft weiter, wenn der update/draw Thread in diesen Zustand wechselt (also delay() aufgerufen wurde). Es wird nicht mehr Thread.getState() geprüft, dies zu unzuverlässi gwar.
2022-07-21 10:54:08 +02:00
99848e47f8 colt abhängigkeit nur für’s kompilieren 2022-07-21 10:52:47 +02:00
f75aaf4b7e Predict-Methode für eine Eingabe 2022-07-21 10:52:19 +02:00
e5c6fa634a Anpassung der Package-Struktur 2022-07-20 17:15:29 +02:00
ccc83414c7 Merge branch 'optional-ml' 2022-07-20 17:09:24 +02:00
16477463d4 java doc und refactorings 2022-07-20 17:09:09 +02:00
d3997561fc Streams durch Schleifen ersetzt
Der Overhead durch die parallelen Streams war zu hoch. Jedenfalls bei den relativ kleinen Matrizen im Test. Bei größeren Matrizen könnte die Parallelität einen Vorteil bringen. Ggf. sollte dies getesett werden und abhängig von der Größe die bestte Methode gewählt werden.
2022-07-19 22:53:46 +02:00
b6b4ffe6a5 Weitere Tests eingefügt und verbessert 2022-07-19 22:52:23 +02:00
bf261b5e9b Colt als optionale Abhängigkeit
DAs Anlernen des NN geht um den Faktor 20 schneller, wenn Colt benutzt wird.
2022-07-19 20:05:37 +02:00
b79f26f51e Matric interface umbenannt 2022-07-19 09:14:00 +02:00
538a8215e6 Userinput wird nach Stopp der ZM weiterverarbeitet 2022-07-19 08:56:00 +02:00
cbda5c3077 Bug: Linearer Farbverlauf wurde nicht korrekt berechnet 2022-07-19 08:55:06 +02:00
2caa528a5e Listeniterationen Threadsafe gemacht 2022-07-18 22:48:28 +02:00
bb50abb7bd Javadoc 2022-07-18 22:48:08 +02:00
38d5f22fb6 Bug: UpdateThreadExecutor blockt nun korrekt den Zeichenthread 2022-07-18 22:47:37 +02:00
d34c60505e Bug: mousePressed wurde nicht ausgelöst 2022-07-18 22:46:48 +02:00
4c8e5c8939 USing Colt library as optional dependency 2022-07-18 11:06:08 +02:00
9a9a714050 Javadoc 2022-07-17 16:38:42 +02:00
f0b064a3d5 Changelog 2022-07-17 15:57:34 +02:00
c922357ab7 Bug behoben: Flackern bei Farbverläufen 2022-07-17 15:57:24 +02:00
17c31a1a03 Bug behoben: delay() funktioniert nun auch nach Stopp der ZM 2022-07-17 15:57:02 +02:00
6551bb75c9 Farbverläufe für Formen und neue Konstantennamen 2022-07-17 15:45:05 +02:00
3931e610c6 Changelog und Versionsnummer 2022-07-17 09:28:11 +02:00
bf14bf14dd Fixewd javadoc 2022-07-17 09:27:56 +02:00
222bc0ff7d Merge branch 'concurrent-frames' 2022-07-17 08:55:13 +02:00
33fb503ab8 animateAndWait methoden 2022-07-17 08:54:47 +02:00
aad53d51d1 FadeAnimation erstellt 2022-07-17 08:54:34 +02:00
d87e455e9d Bug beim Laden von AudioStreams behoben 2022-07-17 08:54:17 +02:00
4fd4aa9a94 update/draw nun in eigenem Thread
update/draw wird nun einmal pro Frame als separater Thread ausgeführt. Falls dabei delay oder eine andere wartende Methode aufgerufen wird, läuft die ZM aber weiter, bis der update/draw Thread wieder aufwacht. Dadurch werden Animationen und andere parallele Prozesse nicht auch geblockt.
2022-07-17 08:53:43 +02:00
7031aa40cc Animationssystem erweitert 2022-07-16 17:01:39 +02:00
c295821d85 Timer und Counter Hilfsklassen 2022-07-16 13:32:03 +02:00
91805f7794 Refactorings FileLoader 2022-07-15 22:27:44 +02:00
22c0547caa Merge branch 'main' into tasks 2022-07-15 21:45:37 +02:00
d443d4d11d Merge branch 'main' into ml 2022-07-15 21:44:58 +02:00
4366726671 Merge branch 'main' into events 2022-07-15 21:40:55 +02:00
6040545274 Tests zum Laden und SPeichern 2022-07-15 19:42:48 +02:00
7b84570d18 Umbennung getResourceStream->getinputStream 2022-07-15 19:42:35 +02:00
b24eec5063 Laden und speichern von Netzen ermöglicht 2022-07-15 19:42:13 +02:00
d5abd4ef68 Biases im NeuronLayer eingeführt 2022-07-15 19:42:01 +02:00
9cd37fdce0 Merge branch 'main' into ml 2022-07-14 23:03:08 +02:00
7e023026ce Klasse FileLoader um Textdateien zu laden 2022-07-14 23:02:26 +02:00
005f8299ac Testklasse für Perlin Noise 2022-07-14 19:27:47 +02:00
763d9eff22 Bugfix beim setzen des StrokeType 2022-07-14 19:27:36 +02:00
b244a6e094 arrange und align Funktionen 2022-07-14 18:04:01 +02:00
4597fb411a DrawingLayer.pixel zeichnet nun direkt in den Puffer 2022-07-14 18:03:23 +02:00
9634d11842 Reihenfolge der Richtungs-Enum geändert 2022-07-14 18:02:48 +02:00
e6882fcbf7 WindowAdapter beendet die ZM nun direkt, und wartet nicht auf den Thread
Bisher hat ein Schließen des Fensters dazu geführt, dass `running = false` gestzt wurde und die Maschine den aktuellen Frame noch beenden konnte. Da ein Frame durch die Verwendung von `delay(int)` aber auch lange dauern kann, hatte man als Nutzer dann den Eindruck, dass der Klick nicht registriert wurde.
Nun beendet das Programm direkt, ruft aber trotzdem vorher `teardown()` und `cleanup()` auf.
2022-07-14 18:02:30 +02:00
c0831688ba Test für Noise-Klasse 2022-07-14 17:59:48 +02:00
1e4b865492 Color refactored 2022-07-14 17:59:32 +02:00
0098621ebe Klasse für Perlin Noise implementiert
Die Klasse erzeugt Zuffalswerte nach dem von Ken Perlin erfundenen „Improved Perlin Noise“ Algorithmus.
2022-07-14 17:59:17 +02:00
949f058b5d Fehlenden Klassenkommentar ergänzt 2022-07-12 23:33:38 +02:00
740bb37279 Klasse Constants kommentiert und refactored 2022-07-12 23:22:35 +02:00
f8550ceae5 Projekt an Gradle Struktur angepasst 2022-07-11 22:12:11 +02:00
99d0e702aa eventDispatch nur nach initialisierung aufrufen 2022-07-11 22:09:00 +02:00
5557030e0d Delayed initialization auch für Music Klasse 2022-07-11 14:41:58 +02:00
855d67c873 AnimationListener 2022-07-11 14:41:45 +02:00
bc791a9dc3 Merge branch 'anim' into events 2022-07-11 14:08:03 +02:00
f79cff18a6 Merge branch 'main' into tasks
# Conflicts:
#	src/main/java/schule/ngb/zm/tasks/DelayedTask.java
#	src/main/java/schule/ngb/zm/tasks/FrameSynchronizedTask.java
#	src/main/java/schule/ngb/zm/tasks/FramerateLimitedTask.java
#	src/main/java/schule/ngb/zm/tasks/RateLimitedTask.java
#	src/main/java/schule/ngb/zm/tasks/Task.java
2022-07-11 14:07:24 +02:00
921e2fb3ef An Gradle Struktur angepasst 2022-07-11 14:06:47 +02:00
944249ce82 Merge branch 'main' into anim
# Conflicts:
#	src/main/java/schule/ngb/zm/tasks/DelayedTask.java
#	src/main/java/schule/ngb/zm/tasks/FrameSynchronizedTask.java
#	src/main/java/schule/ngb/zm/tasks/FramerateLimitedTask.java
#	src/main/java/schule/ngb/zm/tasks/RateLimitedTask.java
#	src/main/java/schule/ngb/zm/tasks/Task.java
2022-07-11 14:05:46 +02:00
e1f01fe620 Auf Gradle Struktur angepasst 2022-07-11 14:03:21 +02:00
9f56b49fb7 Merge branch 'main' into events
# Conflicts:
#	src/main/java/schule/ngb/zm/media/AudioListener.java
#	src/main/java/schule/ngb/zm/media/Mixer.java
#	src/main/java/schule/ngb/zm/media/Music.java
#	src/schule/ngb/zm/media/Sound.java
2022-07-11 14:00:37 +02:00
ec8e5cea91 API angepasst und Javadoc verbessert 2022-07-11 13:53:15 +02:00
6a2adc9d4d Mehr Javadoc Korrekturen 2022-07-11 08:22:47 +02:00
9088e6eceb Merge branch 'main' into ml 2022-07-11 08:19:41 +02:00
2c322eb678 Javadocs angepasst und Fehler behoben 2022-07-11 08:18:52 +02:00
b60ffa9ef3 Projektstruktur an Gradle angepasst 2022-07-10 22:46:55 +02:00
0a72b97d56 Gradle initialisiert 2022-07-10 22:46:27 +02:00
4ea526b239 Erste Implementation eines einfachen neuronalen Netzes
Vorbild zur Implementation: https://github.com/wheresvic/neuralnet
2022-07-10 22:33:21 +02:00
54762cb3e6 enabelGlobalDebugging verbessert 2022-07-09 21:01:56 +02:00
2e5d5d7e83 Debug Nachricht beim shutdown 2022-07-09 21:01:39 +02:00
43c5b9f28e Fehler beim erstellen eines AudioStreams behoben 2022-07-09 21:01:01 +02:00
62f221e18e BlueJ Testprojekt entfernt 2022-07-09 21:00:11 +02:00
b3ff1a507e Tests auf Junit5 angepasst 2022-07-08 16:36:33 +02:00
600a49af64 invokeLater gibt nun auch eine Future zurück 2022-07-08 09:52:03 +02:00
b575c47ab3 Neue Easing funktionen 2022-07-08 08:52:31 +02:00
447accc567 Animationen nutzen FrameSynchronizedTasks 2022-07-08 08:01:53 +02:00
2de37e5501 Merge branch 'tasks' into anim 2022-07-08 08:01:35 +02:00
98a62f35cd initialize und finish methoden für Tasks 2022-07-08 08:01:24 +02:00
a52125aeb2 Merge branch 'tasks' into anim 2022-07-08 07:53:01 +02:00
476545f721 Changelog 2022-07-08 07:52:39 +02:00
a8bbce72a2 DelayedTask wartet selbstständig 2022-07-08 07:52:35 +02:00
ced0aa6842 Synchronisation über einen globalen Monitor 2022-07-08 07:44:49 +02:00
d48b167fb3 Renamed generator to dispatcher 2022-07-08 07:31:37 +02:00
e4818d4f3e Abstraktion für Listener API erstellt
EventGenerator soll als einheitlicher Unterbau zur Umstzung von Listener Patterns dienen. Damit sollen Listener wie AudioListener oder AnimationListener umgesetzt werden.
2022-07-07 21:45:08 +02:00
9ee7c606fe Implementierung verschiedener Task-Typen
Die Tasks erfüllen verschiedene Aufgaben und können vom TaskRunner parallel ausgeführt werden. Ob ein so komplexes Task-Management notwendig ist, bleibt offen.
2022-07-07 21:18:45 +02:00
303b667cbf Tests für Animationen 2022-07-07 15:45:25 +02:00
2f59d29d08 Animationen als eigener Prozess
Die Animations API verwendet Funktionale Aspekte der Java 8 API und erlaubt die Animation beliebiger Objekte, aber ist vor allem auf die `shape.*` Klassen ausgelegt.
2022-07-07 15:44:36 +02:00
fc7ee36367 Implementierung von Easing-Funktionen
Die Implementierungen wurden von https://easings.net übernommen.
2022-07-07 15:42:47 +02:00
3030445dcf Changelog 2022-07-07 09:21:39 +02:00
b6b8263e5e Reference auf TextBox entfernt 2022-07-07 09:20:36 +02:00
49ad98fd82 Namen der Threads gesetzt, für leichteres Debugging 2022-07-07 09:20:01 +02:00
1e552d6bc2 Changelog 2022-07-07 08:08:36 +02:00
4e147586e4 Audio Interface ud Mixer Klasse 2022-07-07 08:08:28 +02:00
5213dbb7e9 Formatierung 2022-07-06 22:18:00 +02:00
ed2c14a143 Dokumentation 2022-07-06 22:17:50 +02:00
f9f1cfed24 LineChart auf ChartValue interface umgestellt 2022-07-06 22:17:42 +02:00
e78ec53a53 Merge branch 'main' into charts 2022-07-06 21:29:58 +02:00
c5dd889406 Refactoring der Package-Struktur 2022-07-06 21:27:52 +02:00
a94194daf1 Beispielprojekte zur ZM entfernt
Die Projekte werden in einem eigenen Repository (zeichenmaschine-examples) neu veröffentlicht.
2022-07-06 21:23:44 +02:00
4ad24fc523 Changelog angepasst 2022-07-06 21:15:47 +02:00
e42b02763a width / height umbenannt, damit Constants nicht überschrieben werden
Dies ist ein generelles Problem. Wenn in Objekten die von Constants erben width und height als Objektvariablen genutzt werden sollen, ist die Größe der Zeichenleinwand nicht mehr direkt abrufbar.

Ggf. sollten die Variablen in Constants spezifischer benannt werden (z.B. `zmwidth` oder `canvaWidth`).
2022-07-06 21:15:23 +02:00
df335c8ff2 Weitere Methoden zum hinzufügen und entfernen von Shapes 2022-07-06 21:13:18 +02:00
28d996859a Versionsnummer angepasst 2022-07-06 21:12:57 +02:00
a400829594 updateGame als globale update Methode der Spielemaschine 2022-07-06 21:12:41 +02:00
b5faf202b8 Klassen Sound und Music zur Audiowiedergabe
Sound spielt kurze Clips (z.B. Soundeffekte) ab.
Music für längere Hintergrundmusik.

MP3s werden nur über die Einbindung der externen Abhängigkeiten jlayer, tritonus-share und mp3spi ermöglicht.
2022-07-06 20:46:49 +02:00
950098110f Eine TaskQueue in der Tasks geplant werden können
Es können Tasks (Runnables) für die geplante Ausführung (z.B. in 100 ms) übergeben werden. Die Tasks werden dann jeweils am Ende eines Frames abgearbeitet. Bei Bedarf auch parallel mit dem TaskRunner.

Das System sollte noch einmal Refactored werden. (Und ggf. auch auf seine Sinnhaftigkeit geprüft werden.)
2022-07-06 20:41:34 +02:00
ffe9bef5fd Synchronisierte EventQueue für InputEvents
Eingaben der Swing Componente werden nun in eine interen EventQueue einsortiert, die einmal pro Frame abgearbeitet wird. Das verhindert Probleme bei der Synchronisierung der ZM mit dem EDT von Swing.

Im Moment werden die Originalen InputEvent gespeichert und verarbeitet. In Zukunft könnte eine eigene Event-Klasse sinnvoll sein, die die Events für die Nutzer vereinfacht (siehe Processing).
2022-07-06 20:39:34 +02:00
81624e3a7a Setter für FPS verhindert das setzen auf weniger als 0 frames 2022-07-06 20:36:27 +02:00
1a26afb1ae Fehlende Imports in der Zeichenmaschine gefixt 2022-07-06 20:33:57 +02:00
264552c8b7 Neue Klasse TaskRunner
TaskRunner ist eine statische Klasse, die einen ThreadPool verwaltet und es anderen KLassen ermöglicht, Parallele Prozesse auszuführen. Die ZM ist grundsätzlich erstmal nicht auf Parallelität ausgelegt, da alle im „GameLoop“ (Zeichenmaschine$Zeichenthread) pro Frame synchron läuft. Einige Aufgaben erfordern aber eigene Therad (z.B. das Abspielen von Musikdateien oder zukünftige Animationen).

Der TaskRunner ist eine erste Verison einer Klasse, die zukünftig in der ZM an Bedeutung gewinnen könnte, wenn Parallelität wichtiger wird (z.B. in der Spielemaschine).
2022-07-06 20:33:10 +02:00
bb330c81b8 Reafactoring des ImageLoader
ImageLoader nutz nun den ResourceStreamProvider und die Logging API
2022-07-06 20:29:50 +02:00
aadec6d973 Refactoring des FontLoader
Das Öffnen von Resourcen Streams wurde in eine eigene Hilfsklasse ausgelagert. FontLoader nutzt nun die neue Logging API.
2022-07-06 20:29:21 +02:00
fb2580eb2c Logging API erstellt, um einheitliches Logging zu vereinfachen 2022-07-06 20:18:25 +02:00
49063c9581 Klasse Validator eingefügt 2022-07-06 20:16:37 +02:00
62dc4190a1 Spelling 2022-07-01 13:05:52 +02:00
a31ec502d4 Möglichkeit beliebige Tasks zu timen
Die ZM kann nun beliebige Runnables mit einem Zeitdelay versehen ausführen. Mitteles `scheduleTask(Runnable, int)` wird das angegebene Runnable nach der angegebene Anzahl Millisekunden ausgeführt.
Tasks werden immer am Ende eines Frames ausgeführt.
2022-07-01 13:05:23 +02:00
0f0b03d8fe Verwendung eigener Schriftarten 2022-07-01 13:00:53 +02:00
57c396c2e4 Verwendung der neuen FontLoader KLasse 2022-07-01 13:00:39 +02:00
bd71bb6619 Hilfsklasse um Schrifarten aus Dateien zu laden 2022-07-01 13:00:09 +02:00
fb88f8a17f Spielemaschine auf neue Standardebenen angepasst 2022-06-30 21:29:38 +02:00
c989e69f9f Behandlung von inputs nun in eigener EventQueue
Tastatur- und Mauseingaben werden nun nicht mehr direkt verarbeitet, sondern in eine interne EventQueue geschoben, die nach dem Aufruf von `draw()` abgearbeitet wird. Die `InputEvent`s werden momentan direkt an die üblichen Listener Methoden weitergegeben. Ggf. ist in Zukunft hier auch ein vereinfachtes Eventsystem (siehe Processing) sinnvoll.
Ist die ZM pausiert, werden Events ohne verzögerung direkt ausgelöst.
2022-06-30 21:29:01 +02:00
3e94f42ed3 Zeichenleinwand wird nur noch mit ColorLayer initialisiert 2022-06-30 21:25:05 +02:00
1b5f46c771 Boids Beispiel angepasst und Bug bei Null-Entfernung behoben 2022-06-30 21:24:10 +02:00
445bc29480 Vector wirft nun eine Exception, wenn durch 0 geteilt wird 2022-06-30 21:22:12 +02:00
62e9f5d0f2 Allgemeiner GraphicsLayer hinzugefügt
Vor allem für Testst hilfreich
2022-06-29 22:35:57 +02:00
4f1bd25ad7 Hehomon Beispiel implementiert
Noch Bugs bei Verwendung des Vollbildmodus vorhanden
2022-06-29 22:35:24 +02:00
ff56e689f8 Test für Formen 2022-06-29 22:34:48 +02:00
a01878286b Klassenmethode zur Berechnung beliebiger Ankerpunkte 2022-06-29 22:34:31 +02:00
010a37fc0e Breite / Höhe von Gruppen darf nicht manuell geändert werden 2022-06-29 22:30:39 +02:00
1a55e11841 Texte haben eine separate fontColor
stroke und fill werden nun auf null gesetzt und als Rahmen bzw Hintergrund gezeichnet, wenn sie gesetzt werden.
2022-06-29 22:30:19 +02:00
67610963f2 Spielemaschine als UNterbau für Spiele mit der ZM 2022-06-29 22:29:42 +02:00
57afc4683f Dokumentaiton verbessert 2022-06-29 22:29:23 +02:00
cb303d2c32 Tastencodes als Konstanten ergänzt 2022-06-29 22:29:12 +02:00
7c0d8458ed Rechtschreibung 2022-06-29 22:28:50 +02:00
9344fc284b Interne Verwendung von Settern
Zur Verbesserung der Überschreibbarkeit.
2022-06-29 22:28:40 +02:00
3bdf0daf79 Änderung der Größe in eigener Methode
Die Größe der Zeichenfläche wird nun in einer eigenen, internen Methode geändert, die von setSize und setFullscreen benutzt wird. Dadurch wird die abhängigkeit der beiden Methoden voneinander aufgehoben.
2022-06-29 22:27:44 +02:00
e411b5025e Dokumentation verbessert 2022-06-29 22:26:18 +02:00
e5c2c0e569 Kleine Änderung 2022-06-21 21:33:39 +02:00
3cbdffaa08 Entfernen von Ebenen von der Leinwand ermöglicht 2022-06-21 21:33:19 +02:00
7293f62a19 Standardverschiebung für Shape#nextTo() 2022-06-21 21:32:56 +02:00
2b20cc0f8e Kleiner Bugfix 2022-06-21 21:32:27 +02:00
83039f0717 Dokumentation 2022-06-21 21:32:20 +02:00
f27fc206af Test für Verschiebungen 2022-06-21 21:32:14 +02:00
7cf8f81d07 Richtungen werden nun als Vektoren ausgedrückt 2022-06-21 21:31:57 +02:00
e2c10ff940 Merge branch 'main' into games 2022-06-20 18:31:44 +02:00
6be5104836 Überschreibare Methode zur Reaktion auf verlassen / aktivieren des Vollbildmodus 2022-06-20 18:31:25 +02:00
b3319e09aa Removed SOund and Fonts 2022-06-20 18:21:37 +02:00
3c46ae4faa Hehomon Beispiel 2022-06-20 18:15:10 +02:00
11cb9f7bff Überflüssige Beispiel entfernt 2022-06-20 17:51:57 +02:00
99fda3c37c Erste Diagrammtypen implementiert 2022-06-19 22:28:09 +02:00
259 changed files with 15284 additions and 7625 deletions

16
.gitignore vendored
View File

@@ -32,3 +32,19 @@ 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,11 +6,49 @@ und diese Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]
### Added
- System für EventListener.
- `AudioListener` und `AnimationListener` als erste Anwendungsfälle.
- Pakete für Animationen und Maschinelles-Lernen.
- Farbverläufe als Füllung.
### Changed
- `update(double)` und `draw()` werden nun in einem eigenen Thread aufgerufen.
- Die Standardwerte in `Constants` wurden mit dem Prefix `DEFAULT_` benannt (vorher `STD_`).
- Die Standardwerte sind nun nicht mehr `final` und können vom Nutzer manuell gesetzt werden.
## 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.util.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.
- 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.
### 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).
- 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.

51
build.gradle Normal file
View File

@@ -0,0 +1,51 @@
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'
compileOnlyApi 'colt:colt:1.2.0'
//api 'colt:colt:1.2.0'
//api 'net.sourceforge.parallelcolt:parallelcolt:0.10.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params: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

@@ -1,53 +0,0 @@
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

@@ -1,59 +0,0 @@
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

@@ -1,72 +0,0 @@
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

@@ -1,55 +0,0 @@
#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.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1013 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 711 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 B

View File

@@ -1,128 +0,0 @@
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

@@ -1,78 +0,0 @@
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

@@ -1,77 +0,0 @@
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

@@ -1,97 +0,0 @@
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

@@ -1,55 +0,0 @@
#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.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,101 +0,0 @@
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

@@ -1,33 +0,0 @@
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

@@ -1,111 +0,0 @@
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

@@ -1,36 +0,0 @@
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.

Before

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -1,55 +0,0 @@
#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

@@ -1,51 +0,0 @@
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

@@ -1,38 +0,0 @@
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

@@ -1,55 +0,0 @@
#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

@@ -1,94 +0,0 @@
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

@@ -1,110 +0,0 @@
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

@@ -1,92 +0,0 @@
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

@@ -1,186 +0,0 @@
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

@@ -1,55 +0,0 @@
#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

@@ -1,33 +0,0 @@
/**
* 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

@@ -1,88 +0,0 @@
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

@@ -1,29 +0,0 @@
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

@@ -1,95 +0,0 @@
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

@@ -1,53 +0,0 @@
#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,257 +0,0 @@
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

@@ -1,22 +0,0 @@
# 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

@@ -1,32 +0,0 @@
#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

@@ -1,77 +0,0 @@
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

@@ -1,40 +0,0 @@
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

@@ -1,122 +0,0 @@
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

@@ -1,62 +0,0 @@
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

@@ -1,60 +0,0 @@
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

@@ -1,43 +0,0 @@
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

@@ -1,12 +0,0 @@
# 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

@@ -1,50 +0,0 @@
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

@@ -1,58 +0,0 @@
#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,14 +0,0 @@
# 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

@@ -1,183 +0,0 @@
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.

Before

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -1,32 +0,0 @@
#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.

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -1,13 +0,0 @@
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

@@ -1,45 +0,0 @@
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;
}
}

View File

@@ -1,14 +0,0 @@
# 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 Objektorientiert mit dem ShapesLayer implementiert.
Eine nicht OOP Version ist im Beispielprojekt zm_raindrops zu finden.
## Quellen
- raindrop.png by @lagartoflojo (https://openclipart.org/detail/4063/water-drop)
- bucket.png

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