mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 06:33:34 +02:00
Basisklassen
This commit is contained in:
23
src/schule/ngb/zm/Aktualisierbar.java
Normal file
23
src/schule/ngb/zm/Aktualisierbar.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
/**
|
||||
* Aktualisierbare Objekte können in regelmäßigen Intervallen (meist einmal
|
||||
* pro Frame) ihren Zustand aktualisieren. Diese Änderung kann abhängig vom
|
||||
* Zeitintervall (in Sekunden) zum letzten Aufruf passieren.
|
||||
*/
|
||||
public interface Aktualisierbar {
|
||||
|
||||
/**
|
||||
* Gibt an, ob das Objekt gerade auf Aktualisierungen reagiert.
|
||||
* @return <code>true</code>, wenn das Objekt aktiv ist.
|
||||
*/
|
||||
public boolean istAktiv();
|
||||
|
||||
/**
|
||||
* Änderung des Zustandes des Objekts abhängig vom Zeitintervall
|
||||
* <var>delta</var> in Sekunden.
|
||||
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
|
||||
*/
|
||||
public void aktualisieren( double delta );
|
||||
|
||||
}
|
||||
106
src/schule/ngb/zm/Ebene.java
Normal file
106
src/schule/ngb/zm/Ebene.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public abstract class Ebene extends Konstanten implements Zeichenbar, Aktualisierbar {
|
||||
|
||||
protected BufferedImage puffer;
|
||||
|
||||
protected Graphics2D zeichnung;
|
||||
|
||||
protected boolean sichtbar = true;
|
||||
|
||||
protected boolean aktiv = true;
|
||||
|
||||
|
||||
public Ebene() {
|
||||
this(STD_BREITE, STD_HOEHE);
|
||||
}
|
||||
|
||||
public Ebene( int pBreite, int pHoehe ) {
|
||||
zeichnungErstellen(pBreite, pHoehe);
|
||||
}
|
||||
|
||||
public int getBreite() {
|
||||
return puffer.getWidth();
|
||||
}
|
||||
|
||||
public int getHoehe() {
|
||||
return puffer.getHeight();
|
||||
}
|
||||
|
||||
public void setGroesse( int pBreite, int pHoehe ) {
|
||||
if( puffer != null ) {
|
||||
zeichnenWiederherstellen(pBreite, pHoehe);
|
||||
} else {
|
||||
zeichnungErstellen(pBreite, pHoehe);
|
||||
}
|
||||
}
|
||||
|
||||
private void zeichnungErstellen( int pBreite, int pHoehe ) {
|
||||
puffer = new BufferedImage(pBreite, pHoehe, BufferedImage.TYPE_INT_ARGB);
|
||||
zeichnung = puffer.createGraphics();
|
||||
|
||||
// add antialiasing
|
||||
RenderingHints hints = new RenderingHints(
|
||||
RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON
|
||||
);
|
||||
hints.put(
|
||||
RenderingHints.KEY_RENDERING,
|
||||
RenderingHints.VALUE_RENDER_QUALITY
|
||||
);
|
||||
zeichnung.addRenderingHints(hints);
|
||||
}
|
||||
|
||||
private void zeichnenWiederherstellen( int pBreite, int pHoehe ) {
|
||||
BufferedImage oldCanvas = puffer;
|
||||
zeichnungErstellen(pBreite, pHoehe);
|
||||
zeichnung.drawImage(oldCanvas, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leert die Ebene und löscht alles bisher gezeichnete.
|
||||
*/
|
||||
public abstract void leeren();
|
||||
|
||||
/**
|
||||
* Zeichnet den Puffer auf die Grafik-Instanz.
|
||||
*
|
||||
* @param pGraphics
|
||||
*/
|
||||
@Override
|
||||
public void zeichnen( Graphics2D pGraphics ) {
|
||||
if( sichtbar ) {
|
||||
pGraphics.drawImage(puffer, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean istSichtbar() {
|
||||
return sichtbar;
|
||||
}
|
||||
|
||||
public void verstecken() {
|
||||
sichtbar = false;
|
||||
}
|
||||
|
||||
public void zeigen() {
|
||||
sichtbar = true;
|
||||
}
|
||||
|
||||
public void umschalten() {
|
||||
sichtbar = !sichtbar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void aktualisieren( double delta ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean istAktiv() {
|
||||
return aktiv;
|
||||
}
|
||||
|
||||
}
|
||||
95
src/schule/ngb/zm/Farbe.java
Normal file
95
src/schule/ngb/zm/Farbe.java
Normal file
@@ -0,0 +1,95 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class Farbe extends Color {
|
||||
|
||||
public static final Farbe SCHWARZ = new Farbe(Color.BLACK);
|
||||
public static final Farbe WEISS = new Farbe(Color.WHITE);
|
||||
public static final Farbe GRAU = new Farbe(Color.GRAY);
|
||||
public static final Farbe DUNKELGRAU = new Farbe(Color.DARK_GRAY);
|
||||
public static final Farbe HELLGRAU = new Farbe(Color.LIGHT_GRAY);
|
||||
|
||||
public static final Farbe ROT = new Farbe(Color.RED);
|
||||
public static final Farbe GRUEN = new Farbe(Color.GREEN);
|
||||
public static final Farbe BLAU = new Farbe(Color.BLUE);
|
||||
public static final Farbe GELB = new Farbe(Color.YELLOW);
|
||||
public static final Farbe ORANGE = new Farbe(Color.ORANGE);
|
||||
public static final Farbe CYAN = new Farbe(Color.CYAN);
|
||||
public static final Farbe MAGENTA = new Farbe(Color.MAGENTA);
|
||||
public static final Farbe PINK = new Farbe(Color.PINK);
|
||||
|
||||
public static final Farbe HGGRUEN = new Farbe(0, 165, 81);
|
||||
public static final Farbe HGROT = new Farbe(151, 54, 60);
|
||||
|
||||
|
||||
public Farbe( int pGrau ) {
|
||||
super(pGrau, pGrau, pGrau, 255);
|
||||
}
|
||||
|
||||
public Farbe( int pGrau, int pAlpha ) {
|
||||
super(pGrau, pGrau, pGrau, pAlpha);
|
||||
}
|
||||
|
||||
|
||||
public Farbe( int pRot, int pGruen, int pBlau ) {
|
||||
super(pRot, pGruen, pBlau);
|
||||
}
|
||||
|
||||
public Farbe( int pRot, int pGruen, int pBlau, int pAlpha ) {
|
||||
super(pRot, pGruen, pBlau, pAlpha);
|
||||
}
|
||||
|
||||
public Farbe( Color pColor ) {
|
||||
super(pColor.getRed(), pColor.getGreen(), pColor.getBlue(), pColor.getAlpha());
|
||||
}
|
||||
|
||||
public Farbe( Color pColor, int pAlpha ) {
|
||||
super(pColor.getRed(), pColor.getGreen(), pColor.getBlue(), pAlpha);
|
||||
}
|
||||
|
||||
public static Farbe vonRGB( int pRGB ) {
|
||||
return new Farbe(
|
||||
(pRGB >> 16) & 255,
|
||||
(pRGB >> 8) & 255,
|
||||
pRGB & 255,
|
||||
(pRGB >> 24) & 255);
|
||||
}
|
||||
|
||||
public static Farbe vonHexcode( String pHexcode ) {
|
||||
if( pHexcode.startsWith("#") ) {
|
||||
pHexcode = pHexcode.substring(1);
|
||||
}
|
||||
|
||||
int red = Integer.valueOf(pHexcode.substring(0, 2), 16);
|
||||
int green = Integer.valueOf(pHexcode.substring(2, 4), 16);
|
||||
int blue = Integer.valueOf(pHexcode.substring(4, 6), 16);
|
||||
|
||||
int alpha = 255;
|
||||
if( pHexcode.length() == 8 ) {
|
||||
alpha = Integer.valueOf(pHexcode.substring(6, 8), 16);
|
||||
}
|
||||
|
||||
return new Farbe(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
public static Farbe morphen( Color pFarbe1, Color pFarbe2, double pFactor ) {
|
||||
if( pFactor < 0.0 || pFarbe2 == null ) {
|
||||
return new Farbe(pFarbe1);
|
||||
}
|
||||
if( pFactor > 1.0 || pFarbe1 == null )
|
||||
return new Farbe(pFarbe2);
|
||||
double pFactorInv = 1 - pFactor;
|
||||
return new Farbe(
|
||||
(int) (pFactorInv * pFarbe1.getRed() + pFactor * pFarbe2.getRed()),
|
||||
(int) (pFactorInv * pFarbe1.getGreen() + pFactor * pFarbe2.getGreen()),
|
||||
(int) (pFactorInv * pFarbe1.getBlue() + pFactor * pFarbe2.getBlue()),
|
||||
(int) (pFactorInv * pFarbe1.getAlpha() + pFactor * pFarbe2.getAlpha())
|
||||
);
|
||||
}
|
||||
|
||||
public Farbe kopie() {
|
||||
return new Farbe(this);
|
||||
}
|
||||
|
||||
}
|
||||
145
src/schule/ngb/zm/Konstanten.java
Normal file
145
src/schule/ngb/zm/Konstanten.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.formen.Konturform;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Arc2D;
|
||||
|
||||
public class Konstanten {
|
||||
|
||||
public static final String APP_NAME = "Zeichenmaschine";
|
||||
|
||||
public static final int STD_BREITE = 400;
|
||||
public static final int STD_HOEHE = 400;
|
||||
public static final int STD_FPS = 60;
|
||||
|
||||
public static Color STD_HINTERGRUND = new Color(200, 200, 200);
|
||||
|
||||
|
||||
public static final int DURCHGEZOGEN = Konturform.DURCHGEZOGEN;
|
||||
public static final int GESTRICHELT = Konturform.GESTRICHELT;
|
||||
public static final int GEPUNKTET = Konturform.GEPUNKTET;
|
||||
|
||||
public static final int OFFEN = Arc2D.OPEN;
|
||||
public static final int GESCHLOSSEN = Arc2D.CHORD;
|
||||
public static final int KREISTEIL = Arc2D.PIE;
|
||||
|
||||
|
||||
public static final byte ZENTRUM = 0;
|
||||
public static final byte NORDEN = 1 << 0;
|
||||
public static final byte OSTEN = 1 << 2;
|
||||
public static final byte SUEDEN = 1 << 3;
|
||||
public static final byte WESTEN = 1 << 4;
|
||||
|
||||
public static final byte NORDOSTEN = NORDEN | OSTEN;
|
||||
public static final byte SUEDOSTEN = SUEDEN | OSTEN;
|
||||
public static final byte NORDWESTEN = NORDEN | WESTEN;
|
||||
public static final byte SUEDWESTEN = SUEDEN | WESTEN;
|
||||
|
||||
public static final byte MITTE = ZENTRUM;
|
||||
public static final byte OBEN = NORDEN;
|
||||
public static final byte RECHTS = OSTEN;
|
||||
public static final byte UNTEN = SUEDEN;
|
||||
public static final byte LINKS = WESTEN;
|
||||
|
||||
|
||||
public static final Farbe SCHWARZ = Farbe.SCHWARZ;
|
||||
public static final Farbe WEISS = Farbe.WEISS;
|
||||
public static final Farbe ROT = Farbe.ROT;
|
||||
public static final Farbe BLAU = Farbe.BLAU;
|
||||
public static final Farbe GRUEN = Farbe.GRUEN;
|
||||
public static final Farbe GELB = Farbe.GELB;
|
||||
|
||||
public Farbe farbe( int pGrau ) {
|
||||
return farbe(pGrau, pGrau, pGrau, 255);
|
||||
}
|
||||
|
||||
public Farbe farbe( int pGrau, int pAlpha ) {
|
||||
return farbe(pGrau, pGrau, pGrau, pAlpha);
|
||||
}
|
||||
|
||||
public Farbe farbe(int red, int green, int blue) {
|
||||
return farbe(red, green, blue, 255);
|
||||
}
|
||||
|
||||
public Farbe farbe(int red, int green, int blue, int alpha) {
|
||||
if (red < 0 || red >= 256)
|
||||
throw new IllegalArgumentException("red must be between 0 and 255");
|
||||
if (green < 0 || green >= 256)
|
||||
throw new IllegalArgumentException("green must be between 0 and 255");
|
||||
if (blue < 0 || blue >= 256)
|
||||
throw new IllegalArgumentException("blue must be between 0 and 255");
|
||||
if (alpha < 0 || alpha >= 256)
|
||||
throw new IllegalArgumentException("alpha must be between 0 and 255");
|
||||
|
||||
return new Farbe(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public double abs( double x ) {
|
||||
return Math.abs(x);
|
||||
}
|
||||
|
||||
public double vorzeichen( double x ) {
|
||||
return Math.signum(x);
|
||||
}
|
||||
|
||||
public double runden( double x ) {
|
||||
return Math.round(x);
|
||||
}
|
||||
|
||||
public double abrunden( double x ) {
|
||||
return Math.floor(x);
|
||||
}
|
||||
|
||||
public double aufrunden( double x ) {
|
||||
return Math.ceil(x);
|
||||
}
|
||||
|
||||
public double sin( double x ) {
|
||||
return Math.sin(x);
|
||||
}
|
||||
|
||||
public double cos( double x ) {
|
||||
return Math.cos(x);
|
||||
}
|
||||
|
||||
public double tan( double x ) {
|
||||
return Math.tan(x);
|
||||
}
|
||||
|
||||
public double arcsin( double x ) {
|
||||
return Math.asin(x);
|
||||
}
|
||||
|
||||
public double arccos( double x ) {
|
||||
return Math.acos(x);
|
||||
}
|
||||
|
||||
public double arctan( double x ) {
|
||||
return Math.atan(x);
|
||||
}
|
||||
|
||||
public double beschraenken( double x, double max ) {
|
||||
if( x > max ) {
|
||||
return max;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public double beschraenken( double x, double min, double max ) {
|
||||
if( x > max ) {
|
||||
return max;
|
||||
}
|
||||
if( x < min ) {
|
||||
return min;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public double morphen( double pVon, double pNach, double pFaktor ) {
|
||||
return pVon - pFaktor*(pVon+pNach);
|
||||
}
|
||||
|
||||
}
|
||||
118
src/schule/ngb/zm/Leinwand.java
Normal file
118
src/schule/ngb/zm/Leinwand.java
Normal file
@@ -0,0 +1,118 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.formen.Formenebene;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Eine Leinwand ist die Hauptkomponente einer Zeichenmaschine. Sie besteht aus
|
||||
* mehreren Ebenen, auf denen auf verschiedene Arten gezeichnet werden kann. Die
|
||||
* Ebenen lassen sich beliebig übereinander anordenen, ausblenden oder wieder
|
||||
* löschen.
|
||||
*
|
||||
* Jede Ebene besitzt eine Zeichenfläche, auf der ihre Zeichnung liegt. Diese
|
||||
* zeichenflächen werden pro Frame einmal von "unten" nach "oben" auf diese
|
||||
* Leinwand gezeichnet.
|
||||
*/
|
||||
public class Leinwand extends JComponent {
|
||||
|
||||
|
||||
private LinkedList<Ebene> ebenen;
|
||||
|
||||
public Leinwand( int pBreite, int pHoehe ) {
|
||||
Dimension dim = new Dimension(pBreite, pHoehe);
|
||||
super.setSize(pBreite, pHoehe);
|
||||
this.setPreferredSize(dim);
|
||||
this.setMinimumSize(dim);
|
||||
|
||||
ebenen = new LinkedList<>();
|
||||
ebenen.add(new Zeichenebene());
|
||||
ebenen.add(new Formenebene());
|
||||
setBackground(Konstanten.STD_HINTERGRUND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSize( int pBreite, int pHoehe ) {
|
||||
Dimension dim = new Dimension(pBreite, pHoehe);
|
||||
super.setSize(pBreite, pHoehe);
|
||||
this.setPreferredSize(dim);
|
||||
this.setMinimumSize(dim);
|
||||
|
||||
for( Ebene ebene : ebenen ) {
|
||||
ebene.setGroesse(getWidth(), getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
public void hinzu( Ebene pEbene ) {
|
||||
if( pEbene != null ) {
|
||||
pEbene.setGroesse(getWidth(), getHeight());
|
||||
ebenen.add(pEbene);
|
||||
}
|
||||
}
|
||||
|
||||
public void hinzu( int pIndex, Ebene pEbene ) {
|
||||
if( pEbene != null ) {
|
||||
pEbene.setGroesse(getWidth(), getHeight());
|
||||
ebenen.add(pIndex, pEbene);
|
||||
}
|
||||
}
|
||||
|
||||
public java.util.List<Ebene> getEbenen() {
|
||||
return ebenen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt die {@link Ebene} am Index <var>i</var> (beginnend bei <code>0</code>).
|
||||
*
|
||||
* @param i Index der Ebene (beginnend bei <code>0</code>).
|
||||
* @return Die Ebene am Index <var>i</var> oder <code>null</code>.
|
||||
* @throws IndexOutOfBoundsException Falls der Index nicht existiert.
|
||||
*/
|
||||
public Ebene getEbene( int i ) {
|
||||
if( ebenen.size() > i ) {
|
||||
return ebenen.get(i);
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException("Keine Ebene mit dem Index " + i + " vorhanden (maximum: " + (ebenen.size() - 1) + ").");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt die erste Ebene des angegebenen Typs aus der Liste der Ebenen.
|
||||
* Existiert keine solche Ebene, wird <code>null</code> zurückgegeben.
|
||||
*
|
||||
* @param pClazz Typ der Ebene.
|
||||
* @param <L>
|
||||
* @return Erste Ebene vom angegeben Typ.
|
||||
*/
|
||||
public <L extends Ebene> L getEbene( Class<L> pClazz ) {
|
||||
for( Ebene ebene : ebenen ) {
|
||||
if( ebene.getClass().equals(pClazz) ) {
|
||||
return pClazz.cast(ebene);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <L extends Ebene> java.util.List<L> getEbenen( Class<L> pClazz ) {
|
||||
ArrayList<L> result = new ArrayList<>(ebenen.size());
|
||||
for( Ebene ebene : ebenen ) {
|
||||
if( ebene.getClass().equals(pClazz) ) {
|
||||
result.add(pClazz.cast(ebene));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g ) {
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
|
||||
for( Ebene ebene : ebenen ) {
|
||||
ebene.zeichnen(g2d);
|
||||
}
|
||||
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
||||
251
src/schule/ngb/zm/Vektor.java
Normal file
251
src/schule/ngb/zm/Vektor.java
Normal file
@@ -0,0 +1,251 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class Vektor extends Point2D.Double {
|
||||
|
||||
public Vektor() {
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
}
|
||||
|
||||
public Vektor(double pX, double pY) {
|
||||
x = pX;
|
||||
y = pY;
|
||||
}
|
||||
|
||||
public Vektor(Point2D.Double pPunkt) {
|
||||
x = pPunkt.getX();
|
||||
x = pPunkt.getY();
|
||||
}
|
||||
|
||||
public Vektor(Vektor pVektor) {
|
||||
x = pVektor.x;
|
||||
y = pVektor.y;
|
||||
}
|
||||
|
||||
public static Vektor zufall() {
|
||||
return new Vektor(Math.random()*100, Math.random()*100);
|
||||
}
|
||||
|
||||
public static Vektor zufall( double min, double max ) {
|
||||
return new Vektor(Math.random()*(max-min)+min, Math.random()*(max-min)+min);
|
||||
}
|
||||
|
||||
public Vektor kopie() {
|
||||
return new Vektor(x, y);
|
||||
}
|
||||
|
||||
public Vektor set(double pX, double pY) {
|
||||
x = pX;
|
||||
y = pY;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vektor set(Vektor pVektor) {
|
||||
x = pVektor.x;
|
||||
y = pVektor.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vektor set(Point2D.Double pPunkt) {
|
||||
x = pPunkt.getX();
|
||||
x = pPunkt.getY();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setX(double pX) {
|
||||
x = pX;
|
||||
}
|
||||
|
||||
public void setY(double pY) {
|
||||
y = pY;
|
||||
}
|
||||
|
||||
public Point2D.Double getPunkt() {
|
||||
return new Point2D.Double(x, y);
|
||||
}
|
||||
|
||||
public double laenge() {
|
||||
return Math.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public double laengeQuad() {
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
public Vektor setLaenge(double pLaenge) {
|
||||
normalisieren();
|
||||
return skalieren(pLaenge);
|
||||
}
|
||||
|
||||
public static Vektor setLaenge(Vektor pVektor, double pLaenge) {
|
||||
Vektor vec = pVektor.kopie();
|
||||
vec.setLaenge(pLaenge);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public Vektor normalisieren() {
|
||||
double len = laenge();
|
||||
if (len != 0 && len != 1) {
|
||||
x /= len;
|
||||
y /= len;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vektor normalisieren(Vektor pVektor) {
|
||||
Vektor vec = pVektor.kopie();
|
||||
vec.normalisieren();
|
||||
return vec;
|
||||
}
|
||||
|
||||
public Vektor addieren(Vektor pVektor) {
|
||||
x += pVektor.x;
|
||||
y += pVektor.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vektor addieren(double pX, double pY) {
|
||||
x += pX;
|
||||
y += pY;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vektor addieren(Vektor pVektor1, Vektor pVektor2) {
|
||||
Vektor vec = pVektor1.kopie();
|
||||
vec.addieren(pVektor2);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public void subtrahieren(Vektor pVektor) {
|
||||
x -= pVektor.x;
|
||||
y -= pVektor.y;
|
||||
}
|
||||
|
||||
public void subtrahieren(double pX, double pY) {
|
||||
x -= pX;
|
||||
y -= pY;
|
||||
}
|
||||
|
||||
public static Vektor subtrahieren(Vektor pVektor1, Vektor pVektor2) {
|
||||
Vektor vec = pVektor1.kopie();
|
||||
vec.subtrahieren(pVektor2);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public Vektor skalieren(double pSkalar) {
|
||||
x *= pSkalar;
|
||||
y *= pSkalar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vektor skalieren(Vektor pVektor, double pSkalar) {
|
||||
Vektor vec = pVektor.kopie();
|
||||
vec.skalieren(pSkalar);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public Vektor dividieren(double pSkalar) {
|
||||
x /= pSkalar;
|
||||
y /= pSkalar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vektor dividieren(Vektor pVektor, double pSkalar) {
|
||||
Vektor vec = pVektor.kopie();
|
||||
vec.dividieren(pSkalar);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public double abstand(Vektor pVektor) {
|
||||
double dx = x - pVektor.x;
|
||||
double dy = y - pVektor.y;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
public static double abstand(Vektor pVektor1, Vektor pVektor2) {
|
||||
return pVektor1.abstand(pVektor2);
|
||||
}
|
||||
|
||||
public double dot(Vektor pVektor) {
|
||||
return x * pVektor.x + y * pVektor.y;
|
||||
}
|
||||
|
||||
public double dot(double pX, double pY) {
|
||||
return x * pX + y * pY;
|
||||
}
|
||||
|
||||
public static double dot(Vektor pVektor1, Vektor pVektor2) {
|
||||
return pVektor1.dot(pVektor2);
|
||||
}
|
||||
|
||||
// See: http://allenchou.net/2013/07/cross-product-of-2d-vectors/
|
||||
public double cross(Vektor pVektor) {
|
||||
return x * pVektor.y - pVektor.x * y;
|
||||
}
|
||||
|
||||
public static double cross(Vektor pVektor1, Vektor pVektor2) {
|
||||
return pVektor1.cross(pVektor2);
|
||||
}
|
||||
|
||||
public void limitieren(double pMax) {
|
||||
if (laengeQuad() > pMax * pMax) {
|
||||
normalisieren();
|
||||
skalieren(pMax);
|
||||
}
|
||||
}
|
||||
|
||||
public void beschraenken(double pMin, double pMax) {
|
||||
if (pMin > pMax) {
|
||||
throw new IllegalArgumentException("HVector.constrain(): pMin muss kleiner sein als pMax.");
|
||||
}
|
||||
if (laengeQuad() < pMin * pMin) {
|
||||
normalisieren();
|
||||
skalieren(pMin);
|
||||
}
|
||||
if (laengeQuad() > pMax * pMax) {
|
||||
normalisieren();
|
||||
skalieren(pMax);
|
||||
}
|
||||
}
|
||||
|
||||
public double richtung() {
|
||||
double angle = Math.atan2(y, x);
|
||||
return angle;
|
||||
}
|
||||
|
||||
public double winkel() {
|
||||
return richtung();
|
||||
}
|
||||
|
||||
public Vektor drehen(double pWinkel) {
|
||||
double temp = x;
|
||||
x = x * Math.cos(pWinkel) - y * Math.sin(pWinkel);
|
||||
y = temp * Math.sin(pWinkel) + y * Math.cos(pWinkel);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vektor drehen(Vektor pVektor, double pWinkel) {
|
||||
Vektor vec = pVektor.kopie();
|
||||
vec.drehen(pWinkel);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public void linterp(Vektor pVektor, float t) {
|
||||
x = x + (pVektor.x - x) * t;
|
||||
y = y + (pVektor.y - y) * t;
|
||||
}
|
||||
|
||||
public static Vektor linterp(Vektor pVektor1, Vektor pVektor2, float t) {
|
||||
Vektor vec = pVektor1.kopie();
|
||||
vec.linterp(pVektor2, t);
|
||||
return vec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "schule.ngb.zm.Vektor{x = " + x + ", y = " + y + "}";
|
||||
}
|
||||
|
||||
}
|
||||
31
src/schule/ngb/zm/Zeichenbar.java
Normal file
31
src/schule/ngb/zm/Zeichenbar.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Zeichenbare Objekte können auf eine Zeichenfläche gezeichnet werden.
|
||||
* In der Regel werden sie einmal pro Frame gezeichnet.
|
||||
*/
|
||||
public interface Zeichenbar {
|
||||
|
||||
/**
|
||||
* Gibt an, ob das Objekt derzeit sichtbar ist (also gezeichnet werden
|
||||
* muss).
|
||||
*
|
||||
* @return <code>true</code>, wenn das Objekt sichtbar ist.
|
||||
*/
|
||||
public boolean istSichtbar();
|
||||
|
||||
/**
|
||||
* Wird aufgerufen, um das Objekt auf die Zeichenfläche <var>graphics</var>
|
||||
* zu zeichnen.
|
||||
* <p>
|
||||
* Das Objekt muss dafür Sorge tragen, dass der Zustand der Zeichenfläche
|
||||
* (Transformationsmatrix, Farbe, ...) erhalten bleibt. Das Objekt sollte
|
||||
* also etwaige Änderungen am Ende des Aufrufs wieder rückgängig machen.
|
||||
*
|
||||
* @param graphics Die Zeichenfläche.
|
||||
*/
|
||||
public void zeichnen( Graphics2D graphics );
|
||||
|
||||
}
|
||||
417
src/schule/ngb/zm/Zeichenebene.java
Normal file
417
src/schule/ngb/zm/Zeichenebene.java
Normal file
@@ -0,0 +1,417 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.util.Stack;
|
||||
|
||||
public class Zeichenebene extends Ebene {
|
||||
|
||||
private int default_anchor = ZENTRUM;
|
||||
|
||||
protected Color strokeColor;
|
||||
|
||||
protected Color fillColor;
|
||||
|
||||
protected double strokeWeight;
|
||||
|
||||
protected int konturArt = DURCHGEZOGEN;
|
||||
|
||||
public Color getColor() {
|
||||
return fillColor;
|
||||
}
|
||||
|
||||
public void noFill() {
|
||||
fillColor = null;
|
||||
}
|
||||
|
||||
public void setColor(int gray) {
|
||||
setColor(gray, gray, gray, 255);
|
||||
}
|
||||
|
||||
public void setColor(int gray, int alpha) {
|
||||
setColor(gray, gray, gray, alpha);
|
||||
}
|
||||
|
||||
public void setColor(int red, int green, int blue) {
|
||||
setColor(red, green, blue, 255);
|
||||
}
|
||||
|
||||
public void setColor(int red, int green, int blue, int alpha ) {
|
||||
if (red < 0 || red >= 256) throw new IllegalArgumentException("red must be between 0 and 255");
|
||||
if (green < 0 || green >= 256) throw new IllegalArgumentException("green must be between 0 and 255");
|
||||
if (blue < 0 || blue >= 256) throw new IllegalArgumentException("blue must be between 0 and 255");
|
||||
if (alpha < 0 || alpha >= 256) throw new IllegalArgumentException("alpha must be between 0 and 255");
|
||||
|
||||
setColor(new Color(red, green, blue, alpha));
|
||||
}
|
||||
|
||||
public void setColor(Color pColor) {
|
||||
fillColor = pColor;
|
||||
zeichnung.setColor(pColor);
|
||||
}
|
||||
|
||||
public Color getStrokeColor() {
|
||||
return strokeColor;
|
||||
}
|
||||
|
||||
public void noStroke() {
|
||||
strokeColor = null;
|
||||
}
|
||||
|
||||
public void setStrokeColor(int gray) {
|
||||
setStrokeColor(gray, gray, gray, 255);
|
||||
}
|
||||
|
||||
public void setStrokeColor(int gray, int alpha) {
|
||||
setStrokeColor(gray, gray, gray, alpha);
|
||||
}
|
||||
|
||||
public void setStrokeColor(int red, int green, int blue) {
|
||||
if (red < 0 || red >= 256) throw new IllegalArgumentException("red must be between 0 and 255");
|
||||
if (green < 0 || green >= 256) throw new IllegalArgumentException("green must be between 0 and 255");
|
||||
if (blue < 0 || blue >= 256) throw new IllegalArgumentException("blue must be between 0 and 255");
|
||||
setStrokeColor(red, green, blue, 255);
|
||||
}
|
||||
|
||||
public void setStrokeColor(int red, int green, int blue, int alpha ) {
|
||||
if (red < 0 || red >= 256) throw new IllegalArgumentException("red must be between 0 and 255");
|
||||
if (green < 0 || green >= 256) throw new IllegalArgumentException("green must be between 0 and 255");
|
||||
if (blue < 0 || blue >= 256) throw new IllegalArgumentException("blue must be between 0 and 255");
|
||||
if (alpha < 0 || alpha >= 256) throw new IllegalArgumentException("alpha must be between 0 and 255");
|
||||
|
||||
setStrokeColor(new Color(red, green, blue, alpha));
|
||||
}
|
||||
|
||||
public void setStrokeColor(Color pColor) {
|
||||
strokeColor = pColor;
|
||||
zeichnung.setColor(pColor);
|
||||
}
|
||||
|
||||
public void setStrokeWeight( double pWeight ) {
|
||||
strokeWeight = pWeight;
|
||||
zeichnung.setStroke(createStroke());
|
||||
}
|
||||
|
||||
protected Stroke createStroke() {
|
||||
switch(konturArt) {
|
||||
case GEPUNKTET:
|
||||
return new BasicStroke(
|
||||
(float) strokeWeight,
|
||||
BasicStroke.CAP_ROUND,
|
||||
BasicStroke.JOIN_ROUND,
|
||||
10.0f, new float[]{1.0f, 5.0f}, 0.0f);
|
||||
case GESTRICHELT:
|
||||
return new BasicStroke(
|
||||
(float) strokeWeight,
|
||||
BasicStroke.CAP_ROUND,
|
||||
BasicStroke.JOIN_ROUND,
|
||||
10.0f, new float[]{5.0f}, 0.0f);
|
||||
default:
|
||||
return new BasicStroke(
|
||||
(float) strokeWeight,
|
||||
BasicStroke.CAP_ROUND,
|
||||
BasicStroke.JOIN_ROUND);
|
||||
}
|
||||
}
|
||||
|
||||
public int getKonturArt() {
|
||||
return konturArt;
|
||||
}
|
||||
|
||||
public void setKonturArt(int konturArt) {
|
||||
this.konturArt = konturArt;
|
||||
}
|
||||
|
||||
private Stack<AffineTransform> transformStack = new Stack<>();
|
||||
|
||||
public Zeichenebene() {
|
||||
super();
|
||||
transformStack.push(new AffineTransform());
|
||||
|
||||
strokeColor = Color.BLACK;
|
||||
fillColor = Color.WHITE;
|
||||
strokeWeight = 1.0;
|
||||
}
|
||||
|
||||
public Zeichenebene( int pWidth, int pHeight) {
|
||||
super(pWidth, pHeight);
|
||||
}
|
||||
|
||||
public void setAnchor( int pAnchor ) {
|
||||
default_anchor = pAnchor;
|
||||
}
|
||||
|
||||
public void leeren() {
|
||||
clear(200);
|
||||
}
|
||||
|
||||
public void clear(int gray) {
|
||||
clear(gray, gray, gray, 255);
|
||||
}
|
||||
|
||||
public void clear(int gray, int alpha) {
|
||||
clear(gray, gray, gray, alpha);
|
||||
}
|
||||
|
||||
public void clear(int red, int green, int blue) {
|
||||
clear(red, green, blue, 255);
|
||||
}
|
||||
|
||||
public void clear(int red, int green, int blue, int alpha) {
|
||||
clear(new Color(red, green, blue, alpha));
|
||||
}
|
||||
|
||||
public void clear(Color pColor) {
|
||||
/*graphics.setBackground(pColor);
|
||||
graphics.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());*/
|
||||
Color currentColor = zeichnung.getColor();
|
||||
pushMatrix();
|
||||
resetMatrix();
|
||||
zeichnung.setColor(pColor);
|
||||
zeichnung.fillRect(0, 0, puffer.getWidth(), puffer.getHeight());
|
||||
zeichnung.setColor(currentColor);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
public void line(double x1, double y1, double x2, double y2) {
|
||||
Shape line = new Line2D.Double(x1, y1, x2, y2);
|
||||
//line = transformToCanvas(line);
|
||||
|
||||
drawShape(line);
|
||||
}
|
||||
|
||||
public void pixel(double x, double y) {
|
||||
square(x, y, 1);
|
||||
}
|
||||
|
||||
public void square(double x, double y, double w) {
|
||||
rect(x, y, w, w);
|
||||
}
|
||||
|
||||
public void square(double x, double y, double w, int anchor) {
|
||||
rect(x, y, w, w, anchor);
|
||||
}
|
||||
|
||||
public void rect(double x, double y, double w, double h) {
|
||||
rect(x, y, w, h, default_anchor);
|
||||
}
|
||||
|
||||
public void rect(double x, double y, double w, double h, int anchor) {
|
||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, w, h, anchor);
|
||||
Shape rect = new Rectangle2D.Double(
|
||||
anchorPoint.getX(), anchorPoint.getY(), w, h
|
||||
);
|
||||
//rect = transformToCanvas(rect);
|
||||
|
||||
fillShape(rect);
|
||||
drawShape(rect);
|
||||
}
|
||||
|
||||
public void point(double x, double y) {
|
||||
circle(x - 1, y - 1, 2);
|
||||
}
|
||||
|
||||
public void circle(double x, double y, double d) {
|
||||
ellipse(x, y, d, d, default_anchor);
|
||||
}
|
||||
|
||||
public void circle(double x, double y, double d, int anchor) {
|
||||
ellipse(x, y, d, d, anchor);
|
||||
}
|
||||
|
||||
public void ellipse(double x, double y, double w, double h) {
|
||||
ellipse(x, y, w, h, default_anchor);
|
||||
}
|
||||
|
||||
public void ellipse(double x, double y, double w, double h, int anchor) {
|
||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, w, h, anchor);
|
||||
Shape ellipse = new Ellipse2D.Double(
|
||||
anchorPoint.x, anchorPoint.y, w, h
|
||||
);
|
||||
//ellipse = transformToCanvas(ellipse);
|
||||
|
||||
fillShape(ellipse);
|
||||
drawShape(ellipse);
|
||||
}
|
||||
|
||||
public void arc( double x, double y, double d, double angle1, double angle2 ) {
|
||||
while (angle2 < angle1) angle2 += 360.0;
|
||||
|
||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, d, d, ZENTRUM);
|
||||
Shape arc = new Arc2D.Double(
|
||||
anchorPoint.x,
|
||||
anchorPoint.y,
|
||||
d, d,
|
||||
angle1, angle2 - angle1,
|
||||
Arc2D.OPEN
|
||||
);
|
||||
//arc = transformToCanvas(arc);
|
||||
|
||||
drawShape(arc);
|
||||
}
|
||||
|
||||
public void pie( double x, double y, double d, double angle1, double angle2 ) {
|
||||
while (angle2 < angle1) angle2 += 360.0;
|
||||
|
||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, d, d, ZENTRUM);
|
||||
Shape arc = new Arc2D.Double(
|
||||
anchorPoint.x,
|
||||
anchorPoint.y,
|
||||
d, d,
|
||||
angle1, angle2 - angle1,
|
||||
Arc2D.PIE
|
||||
);
|
||||
//arc = transformToCanvas(arc);
|
||||
|
||||
fillShape(arc);
|
||||
drawShape(arc);
|
||||
}
|
||||
|
||||
private Point2D.Double transformToCanvas(double x, double y) {
|
||||
return transformToCanvas(new Point2D.Double(x, y));
|
||||
}
|
||||
|
||||
private Point2D.Double transformToCanvas( Point2D.Double pPoint ) {
|
||||
AffineTransform matrix = getMatrix();
|
||||
matrix.transform(pPoint, pPoint);
|
||||
return pPoint;
|
||||
}
|
||||
|
||||
private Shape transformToCanvas( Shape pShape ) {
|
||||
AffineTransform matrix = getMatrix();
|
||||
return matrix.createTransformedShape(pShape);
|
||||
}
|
||||
|
||||
private Point2D.Double transformToUser(double x, double y) {
|
||||
return transformToUser(new Point2D.Double(x, y));
|
||||
}
|
||||
|
||||
private Point2D.Double transformToUser( Point2D.Double pPoint ) {
|
||||
AffineTransform matrix = getMatrix();
|
||||
|
||||
try {
|
||||
matrix.inverseTransform(pPoint, pPoint);
|
||||
} catch (NoninvertibleTransformException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return pPoint;
|
||||
}
|
||||
|
||||
private Shape transformToUser( Shape pShape ) {
|
||||
AffineTransform matrix = getMatrix();
|
||||
try {
|
||||
matrix = matrix.createInverse();
|
||||
pShape = matrix.createTransformedShape(pShape);
|
||||
} catch (NoninvertibleTransformException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return pShape;
|
||||
}
|
||||
|
||||
private AffineTransform getAnchorTransform( Shape pShape, int anchor ) {
|
||||
AffineTransform at = new AffineTransform();
|
||||
Rectangle2D bounds = pShape.getBounds2D();
|
||||
switch(anchor) {
|
||||
case ZENTRUM:
|
||||
at.translate(
|
||||
bounds.getWidth() / -2.0,
|
||||
bounds.getHeight() / -2.0
|
||||
);
|
||||
break;
|
||||
|
||||
case WESTEN:
|
||||
at.translate(
|
||||
0, bounds.getHeight() / -2.0
|
||||
);
|
||||
break;
|
||||
|
||||
case SUEDWESTEN:
|
||||
at.translate(
|
||||
0, -1.0 * bounds.getHeight()
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return at;
|
||||
}
|
||||
|
||||
private Point2D.Double getAnchorPoint(double x, double y, double w, double h, int anchor) {
|
||||
switch(anchor) {
|
||||
case ZENTRUM:
|
||||
x -= w / 2.0;
|
||||
y -= h / 2.0;
|
||||
break;
|
||||
|
||||
case WESTEN:
|
||||
y -= h / 2.0;
|
||||
break;
|
||||
|
||||
case SUEDWESTEN:
|
||||
y -= h;
|
||||
break;
|
||||
}
|
||||
|
||||
return new Point2D.Double(x, y);
|
||||
}
|
||||
|
||||
private Point2D.Double getAnchorPoint(Shape pShape, int anchor) {
|
||||
Rectangle2D bounds = pShape.getBounds2D();
|
||||
return getAnchorPoint(
|
||||
bounds.getX(), bounds.getY(),
|
||||
bounds.getWidth(), bounds.getHeight(), anchor
|
||||
);
|
||||
}
|
||||
|
||||
private void fillShape( Shape pShape ) {
|
||||
if (fillColor != null && fillColor.getAlpha() > 0.0) {
|
||||
zeichnung.setColor(fillColor);
|
||||
zeichnung.fill(pShape);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawShape( Shape pShape ) {
|
||||
if (strokeColor != null && strokeColor.getAlpha() > 0.0
|
||||
&& strokeWeight > 0.0 ) {
|
||||
zeichnung.setColor(strokeColor);
|
||||
zeichnung.draw(pShape);
|
||||
}
|
||||
}
|
||||
|
||||
public void translate( double dx, double dy ) {
|
||||
zeichnung.translate(dx, dy);
|
||||
}
|
||||
|
||||
public void scale( double factor ) {
|
||||
zeichnung.scale(factor, factor);
|
||||
}
|
||||
|
||||
public void rotate( double pAngle ) {
|
||||
zeichnung.rotate(Math.toRadians(pAngle));
|
||||
}
|
||||
|
||||
public void shear( double dx, double dy ) {
|
||||
zeichnung.shear(dx, dy);
|
||||
}
|
||||
|
||||
public AffineTransform getMatrix() {
|
||||
return zeichnung.getTransform();
|
||||
}
|
||||
|
||||
public void pushMatrix() {
|
||||
transformStack.push(zeichnung.getTransform());
|
||||
}
|
||||
|
||||
public void popMatrix() {
|
||||
if( transformStack.isEmpty() ) {
|
||||
resetMatrix();
|
||||
} else {
|
||||
zeichnung.setTransform(transformStack.pop());
|
||||
}
|
||||
}
|
||||
|
||||
public void resetMatrix() {
|
||||
zeichnung.setTransform(new AffineTransform());
|
||||
}
|
||||
|
||||
}
|
||||
313
src/schule/ngb/zm/Zeichenfenster.java
Normal file
313
src/schule/ngb/zm/Zeichenfenster.java
Normal file
@@ -0,0 +1,313 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.formen.Formenebene;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
public class Zeichenfenster extends Konstanten implements Runnable, MouseInputListener, KeyListener {
|
||||
|
||||
protected Object mouseLock = new Object();
|
||||
/*
|
||||
* Attribute für den Zugriff aus Unterklassen.
|
||||
*/
|
||||
protected Leinwand leinwand;
|
||||
protected Zeichenebene zeichnung;
|
||||
protected Formenebene formen;
|
||||
protected int tick = 0;
|
||||
protected long laufzeit = 0L;
|
||||
protected double delta = 0.0;
|
||||
protected double mausX = 0.0, mausY = 0.0, lmausX = 0.0, lmausY = 0.0;
|
||||
protected int breite = STD_BREITE, hoehe = STD_HOEHE;
|
||||
/*
|
||||
* Interne Attribute zur Steuerung der Zeichenamschine.
|
||||
*/
|
||||
//
|
||||
private JFrame frame;
|
||||
private boolean running = false;
|
||||
private int framesPerSecond;
|
||||
|
||||
public Zeichenfenster() {
|
||||
this(APP_NAME);
|
||||
}
|
||||
|
||||
public Zeichenfenster( String pTitel ) {
|
||||
this(STD_BREITE, STD_HOEHE, pTitel);
|
||||
}
|
||||
|
||||
public Zeichenfenster( int pBreite, int pHoehe, String pTitel ) {
|
||||
frame = new JFrame(pTitel);
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch( Exception e ) {
|
||||
System.err.println("Fehler beim Setzen des look and feel.");
|
||||
}
|
||||
|
||||
breite = pBreite;
|
||||
hoehe = pHoehe;
|
||||
|
||||
frame.setResizable(false);
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
leinwand = new Leinwand(pBreite, pHoehe);
|
||||
frame.setContentPane(leinwand);
|
||||
|
||||
framesPerSecond = STD_FPS;
|
||||
|
||||
zeichnung = getZeichenEbene();
|
||||
formen = getFormenEbene();
|
||||
|
||||
einstellungen();
|
||||
|
||||
frame.addMouseListener(this);
|
||||
frame.addMouseMotionListener(this);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing( WindowEvent e ) {
|
||||
running = false;
|
||||
super.windowClosing(e);
|
||||
}
|
||||
});
|
||||
|
||||
frame.pack();
|
||||
frame.requestFocusInWindow();
|
||||
frame.setVisible(true);
|
||||
|
||||
running = true;
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
public final void setSize( int pWidth, int pHeight ) {
|
||||
//frame.setSize(pWidth, pHeight);
|
||||
|
||||
if( leinwand != null ) {
|
||||
leinwand.setSize(pWidth, pHeight);
|
||||
}
|
||||
breite = pWidth;
|
||||
hoehe = pHeight;
|
||||
frame.pack();
|
||||
}
|
||||
|
||||
public final int getBreite() {
|
||||
return breite;
|
||||
}
|
||||
|
||||
public final int getHoehe() {
|
||||
return hoehe;
|
||||
}
|
||||
|
||||
public final void setTitel( String pTitel ) {
|
||||
frame.setTitle(pTitel);
|
||||
}
|
||||
|
||||
public final Leinwand getLeinwand() {
|
||||
return leinwand;
|
||||
}
|
||||
|
||||
public final void hinzu( Ebene pEbene ) {
|
||||
leinwand.hinzu(pEbene);
|
||||
}
|
||||
|
||||
public final Zeichenebene getZeichenEbene() {
|
||||
Zeichenebene layer = leinwand.getEbene(Zeichenebene.class);
|
||||
if( layer == null ) {
|
||||
layer = new Zeichenebene(getBreite(), getHoehe());
|
||||
leinwand.hinzu(0, layer);
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
|
||||
public final Formenebene getFormenEbene() {
|
||||
Formenebene layer = leinwand.getEbene(Formenebene.class);
|
||||
if( layer == null ) {
|
||||
layer = new Formenebene(getBreite(), getHoehe());
|
||||
leinwand.hinzu(layer);
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
|
||||
public final int getFramesPerSecond() {
|
||||
return framesPerSecond;
|
||||
}
|
||||
|
||||
public final void setFramesPerSecond( int pFramesPerSecond ) {
|
||||
framesPerSecond = pFramesPerSecond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
long start = System.currentTimeMillis();
|
||||
long current = System.nanoTime();
|
||||
int _tick = 0;
|
||||
long _runtime = 0;
|
||||
tick = 0;
|
||||
laufzeit = 0;
|
||||
|
||||
vorbereiten();
|
||||
|
||||
while( running ) {
|
||||
int dt = (int) ((System.nanoTime() - current) / 1E6);
|
||||
current = System.nanoTime();
|
||||
delta = (dt / 1000.0);
|
||||
|
||||
saveMousePosition();
|
||||
|
||||
aktualisieren(delta);
|
||||
zeichnen();
|
||||
|
||||
if( leinwand != null ) {
|
||||
//drawing.invalidate();
|
||||
frame.repaint();
|
||||
}
|
||||
|
||||
try {
|
||||
int sleep = Math.round(1000 / framesPerSecond);
|
||||
if( dt >= sleep ) {
|
||||
sleep -= dt % sleep;
|
||||
}
|
||||
Thread.sleep(Math.max(0, sleep));
|
||||
} catch( InterruptedException e ) {
|
||||
// Interrupt not relevant
|
||||
} finally {
|
||||
_tick += 1;
|
||||
_runtime = System.currentTimeMillis() - start;
|
||||
tick = _tick;
|
||||
laufzeit = _runtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Methoden, die von Unterklassen überschrieben werden können / sollen.
|
||||
*/
|
||||
public void einstellungen() {
|
||||
|
||||
}
|
||||
|
||||
public void vorbereiten() {
|
||||
|
||||
}
|
||||
|
||||
public void zeichnen() {
|
||||
|
||||
}
|
||||
|
||||
public void aktualisieren( double delta ) {
|
||||
running = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mouse handling
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
mausklick();
|
||||
}
|
||||
|
||||
public void mausklick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
maustasteRunter();
|
||||
}
|
||||
|
||||
public void maustasteRunter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
maustasteHoch();
|
||||
}
|
||||
|
||||
public void maustasteHoch() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
mausGezogen();
|
||||
}
|
||||
|
||||
public void mausGezogen() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
mausBewegt();
|
||||
}
|
||||
|
||||
public void mausBewegt() {
|
||||
|
||||
}
|
||||
|
||||
private void saveMousePosition( Point pLocation ) {
|
||||
//pmouseX = mouseX;
|
||||
//pmouseY = mouseY;
|
||||
/*synchronized(mouseLock) {
|
||||
mouseX = pLocation.getX()-this.getRootPane().getX();
|
||||
mouseY = pLocation.getY()-this.getRootPane().getY();
|
||||
}*/
|
||||
}
|
||||
|
||||
private void saveMousePosition() {
|
||||
lmausX = mausX;
|
||||
lmausY = mausY;
|
||||
|
||||
java.awt.Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
|
||||
java.awt.Point compLoc = leinwand.getLocationOnScreen();
|
||||
mausX = mouseLoc.x - compLoc.x;
|
||||
mausY = mouseLoc.y - compLoc.y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keyboard handling
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void keyTyped( KeyEvent e ) {
|
||||
tastendruck();
|
||||
}
|
||||
|
||||
public void tastendruck() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed( KeyEvent e ) {
|
||||
tasteRunter();
|
||||
}
|
||||
|
||||
public void tasteRunter() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased( KeyEvent e ) {
|
||||
tasteHoch();
|
||||
}
|
||||
|
||||
public void tasteHoch() {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user