Hey Leute,
Ich bin auf einem ITG und hab bis nach Weihnachten auf, ein (für euch wahrscheinlich seeehhhhrr) einfaches Spiel zu proggen...
Soweit sogut, ich hab auch schon eine Idee, aber die Umsetzung is doch ziemlich schwer, weil ich nicht wirklich gut proggen kann...! Deshalb hoff ich auf ein paar gute Tips, Denkanstöße und vllt. sogar ein paar Beispiele, die mir den Einstig etwas erleichtern.
*** Spieleprinzip:
Das Spiel (2D) soll aus einem Punkt (der durch die Maus kontrolliert wird) und "fallenden" Objekten bestehen, denen man mit der Maus ausweichen soll... (kennt ihr bestimmt) =)
Falls nicht, hab ich hier ein Link zum Beispiel: Klick mich
aber ich weiß echt nicht, wie ich das gestalten soll...
z.B. gibts ja den "mouseEntered" Befehl, aber wie benutz ich den?
Ich hab vom Lehrer eine: "GrLib" ausgeteilt bekommen...
anhand dieser können wir arbeiten...
Bis jetzt hab ich nur etwas herum experimentiert, also Kästchen erstellt und z.B. per "mousePressed" die Farbe geändert usw...
Vllt. noch interessant zu wissen, wir arbeiten mit "BlueJ".
Würd mich über etwas Hilfe sehr freuen!!!
Danke schonmal!
Gruß
Dschuls
Ich bin auf einem ITG und hab bis nach Weihnachten auf, ein (für euch wahrscheinlich seeehhhhrr) einfaches Spiel zu proggen...
Soweit sogut, ich hab auch schon eine Idee, aber die Umsetzung is doch ziemlich schwer, weil ich nicht wirklich gut proggen kann...! Deshalb hoff ich auf ein paar gute Tips, Denkanstöße und vllt. sogar ein paar Beispiele, die mir den Einstig etwas erleichtern.
*** Spieleprinzip:
Das Spiel (2D) soll aus einem Punkt (der durch die Maus kontrolliert wird) und "fallenden" Objekten bestehen, denen man mit der Maus ausweichen soll... (kennt ihr bestimmt) =)
Falls nicht, hab ich hier ein Link zum Beispiel: Klick mich
aber ich weiß echt nicht, wie ich das gestalten soll...
z.B. gibts ja den "mouseEntered" Befehl, aber wie benutz ich den?
Ich hab vom Lehrer eine: "GrLib" ausgeteilt bekommen...
Code:
/*************************************************************************
*
* Kompilieren: javac GrLib.java
*
* Ausfuehren: java GrLib
*
*************************************************************************/
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.imageio.ImageIO;
public final class GrLib
implements ActionListener, MouseListener, MouseMotionListener {
// vordefinierte Farben
public static final Color BLACK = Color.BLACK;
public static final Color BLUE = Color.BLUE;
public static final Color CYAN = Color.CYAN;
public static final Color DARK_GRAY = Color.DARK_GRAY;
public static final Color GRAY = Color.GRAY;
public static final Color GREEN = Color.GREEN;
public static final Color LIGHT_GRAY = Color.LIGHT_GRAY;
public static final Color MAGENTA = Color.MAGENTA;
public static final Color ORANGE = Color.ORANGE;
public static final Color PINK = Color.PINK;
public static final Color RED = Color.RED;
public static final Color WHITE = Color.WHITE;
public static final Color YELLOW = Color.YELLOW;
// Standardfarben
public static final Color DEFAULT_PEN_COLOR = BLACK;
public static final Color DEFAULT_CLEAR_COLOR = WHITE;
// momentane Stiftfarbe
private static Color penColor;
// Standardgroesse fuer die Leinwand (canvas): SIZE mal SIZE
private static final int SIZE = 512;
private static int width = SIZE;
private static int height = SIZE;
// Standardradius fuer den Stift
private static final double DEFAULT_PEN_RADIUS = 0.002;
// momentaner Stiftradius
private static double penRadius;
// gleich alles zeichnen oder bis zum naechsten draw warten?
private static boolean defer = false;
// Grenze der Leinwand: 5%
private static final double BORDER = 0.05;
private static final double DEFAULT_XMIN = 0.0;
private static final double DEFAULT_XMAX = 1.0;
private static final double DEFAULT_YMIN = 0.0;
private static final double DEFAULT_YMAX = 1.0;
private static double xmin, ymin, xmax, ymax;
// Standardschriftart
private static final Font DEFAULT_FONT = new Font("Serif", Font.PLAIN, 16);
// Momentane Schriftart
private static Font font;
// Zwischenspeicher fuer die Grafik
private static BufferedImage offscreenImage, onscreenImage;
private static Graphics2D offscreen, onscreen;
// Bibliothek wird nur einmal erzeugt: ein Singleton
private static GrLib std = new GrLib();
// der Rahmen fuer das Fenster
private static JFrame frame;
// Maus-status Mausklicks und -position
private static boolean mousePressed = false;
private static double mouseX = 0;
private static double mouseY = 0;
// nicht instantiierbar
private GrLib() { }
// die static Initialisierung
static { init(); }
// Fenstergroesse wird auf w mal h pixel gesetzt
public static void setCanvasSize(int w, int h) {
width = w;
height = h;
init();
}
// init Methode fuer die static Initialisierung
private static void init() {
if (frame != null) frame.setVisible(false);
frame = new JFrame();
offscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
onscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
offscreen = offscreenImage.createGraphics();
onscreen = onscreenImage.createGraphics();
setXscale();
setYscale();
offscreen.setColor(DEFAULT_CLEAR_COLOR);
offscreen.fillRect(0, 0, width, height);
setPenColor();
setPenRadius();
setFont();
clear();
// antialiasing verbessert die Schriftdarstellung etwas
RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
offscreen.addRenderingHints(hints);
// fuer den Rahmen
ImageIcon icon = new ImageIcon(onscreenImage);
JLabel draw = new JLabel(icon);
// wir geben auf die Maus acht
draw.addMouseListener(std);
draw.addMouseMotionListener(std);
// schon mal die Grundlagen
frame.setContentPane(draw);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // alle Fenster schliesse
// frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // nur aktuelles Fenster schliessen
frame.setTitle("Grafik Bibliothek");
frame.setJMenuBar(createMenuBar());
frame.pack();
frame.setVisible(true);
}
// Menueleiste anlegen
public static JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Datei");
menuBar.add(menu);
JMenuItem menuItem1 = new JMenuItem(" Speichern... ");
menuItem1.addActionListener(std);
menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
menu.add(menuItem1);
return menuBar;
}
// die Skalierung des Koordinatensystems
public static void setXscale() { setXscale(DEFAULT_XMIN, DEFAULT_XMAX); }
public static void setYscale() { setYscale(DEFAULT_YMIN, DEFAULT_YMAX); }
public static void setXscale(double min, double max) {
double size = max - min;
xmin = min - BORDER * size;
xmax = max + BORDER * size;
}
public static void setYscale(double min, double max) {
double size = max - min;
ymin = min - BORDER * size;
ymax = max + BORDER * size;
}
// Hilfsfunktionen, die zwischen Benutzerkoordinaten und Schirmkoordinaten umwandeln
private static double scaleX (double x) { return width * (x - xmin) / (xmax - xmin); }
private static double scaleY (double y) { return height * (ymax - y) / (ymax - ymin); }
private static double factorX(double w) { return w * width / Math.abs(xmax - xmin); }
private static double factorY(double h) { return h * height / Math.abs(ymax - ymin); }
private static double userX (double x) { return xmin + x * (xmax - xmin) / width; }
private static double userY (double y) { return ymax - y * (ymax - ymin) / height; }
// den Schirm mit der uebergebenen Farbe loeschen
public static void clear() { clear(DEFAULT_CLEAR_COLOR); }
public static void clear(Color color) {
offscreen.setColor(color);
offscreen.fillRect(0, 0, width, height);
offscreen.setColor(penColor);
show();
}
// die Stiftgroesse einstellen
public static void setPenRadius() { setPenRadius(DEFAULT_PEN_RADIUS); }
public static void setPenRadius(double r) {
penRadius = r * SIZE;
BasicStroke stroke = new BasicStroke((float) penRadius);
offscreen.setStroke(stroke);
}
// die Stiftfarbe einstellen
public static void setPenColor() { setPenColor(DEFAULT_PEN_COLOR); }
public static void setPenColor(Color color) {
penColor = color;
offscreen.setColor(penColor);
}
// eine Zeichenkette in der eingestellten Schriftart ausgeben
public static void setFont() { setFont(DEFAULT_FONT); }
public static void setFont(Font f) { font = f; }
// eine Linie zeichnen: von (x0, y0) zu (x1, y1)
public static void line(double x0, double y0, double x1, double y1) {
offscreen.draw(new Line2D.Double(scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1)));
show();
}
// einzelnen Pixel bei (x, y) zeichnen
private static void pixel(double x, double y) {
offscreen.fillRect((int) Math.round(scaleX(x)), (int) Math.round(scaleY(y)), 1, 1);
}
// einen Punkt bei (x, y) zeichnen
public static void point(double x, double y) {
double xs = scaleX(x);
double ys = scaleY(y);
double r = penRadius;
// double ws = factorX(2*r);
// double hs = factorY(2*r);
// if (ws <= 1 && hs <= 1) pixel(x, y);
if (r <= 1) pixel(x, y);
else offscreen.fill(new Ellipse2D.Double(xs - r/2, ys - r/2, r, r));
show();
}
// einen Kreis zeichnen, Radius r und Mittelpunkt (x,y)
public static void circle(double x, double y, double r) {
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*r);
double hs = factorY(2*r);
if (ws <= 1 && hs <= 1) pixel(x, y); // Radius zu klein? dann Pixel
else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));
show();
}
// einen gefuellten Kreis zeichnen. Radius r, Mittelpunkt (x, y)
public static void filledCircle(double x, double y, double r) {
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*r);
double hs = factorY(2*r);
if (ws <= 1 && hs <= 1) pixel(x, y); // Radius zu klein? dann Pixel
else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs));
show();
}
// Quadrat zeichnen. Seitenlaenge 2r, Mittelpunkt (x, y)
public static void square(double x, double y, double r) {
// screen coordinates
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*r);
double hs = factorY(2*r);
if (ws <= 1 && hs <= 1) pixel(x, y); // zu klein? dann Pixel
else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));
show();
}
// Quadrat zeichnen. Seitenlaenge 2r, Mittelpunkt (x, y)
public static void filledSquare(double x, double y, double r) {
// screen coordinates
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*r);
double hs = factorY(2*r);
if (ws <= 1 && hs <= 1) pixel(x, y); // zu klein? dann Pixel
else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs));
show();
}
// Polygon zeichnen. Koordinaten werden als (x[i], y[i]) uebergeben
public static void polygon(double[] x, double[] y) {
int N = x.length;
GeneralPath path = new GeneralPath();
path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0]));
for (int i = 0; i < N; i++)
path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i]));
path.closePath();
offscreen.draw(path);
show();
}
// Polygon zeichnen. Koordinaten werden als (x[i], y[i]) uebergeben
public static void filledPolygon(double[] x, double[] y) {
int N = x.length;
GeneralPath path = new GeneralPath();
path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0]));
for (int i = 0; i < N; i++)
path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i]));
path.closePath();
offscreen.fill(path);
show();
}
// Bild aus Datei/URL einlesen
private static Image getImage(String filename) {
// aus Datei einlesen
ImageIcon icon = new ImageIcon(filename);
// aus URL einlesen
if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) {
try {
URL url = new URL(filename);
icon = new ImageIcon(url);
} catch (Exception e) { /* das ist keine url! */ }
}
// falls die Datei in einem .jar Archiv ist
if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) {
URL url = GrLib.class.getResource(filename);
if (url == null) throw new RuntimeException("Bild " + filename + " nicht gefunden");
icon = new ImageIcon(url);
}
return icon.getImage();
}
// Bild zeichnen (gif, jpg, oder png). Mittelpunkt (x, y)
public static void picture(double x, double y, String s) {
Image image = getImage(s);
double xs = scaleX(x);
double ys = scaleY(y);
int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new RuntimeException("Bild " + s + " ist kaputt");
offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null);
show();
}
// Bild zeichnen (gif, jpg, oder png). Mittelpunkt (x, y), skaliert fuer w mal h
public static void picture(double x, double y, String s, double w, double h) {
Image image = getImage(s);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(w);
double hs = factorY(h);
if (ws <= 1 && hs <= 1) pixel(x, y);
else {
offscreen.drawImage(image, (int) Math.round(xs - ws/2.0),
(int) Math.round(ys - hs/2.0),
(int) Math.round(ws),
(int) Math.round(hs), null);
}
show();
}
// schreibe s mit der aktuellen Schrift, Mittelpunkt (x, y)
public static void text(double x, double y, String s) {
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(s);
int hs = metrics.getDescent();
offscreen.drawString(s, (float) (xs - ws/2.0), (float) (ys + hs));
show();
}
// zeige auf dem Bildschirm, Pausiere t Millisekunden
public static void show(int t) {
defer = true;
onscreen.drawImage(offscreenImage, 0, 0, null);
frame.repaint();
try { Thread.currentThread().sleep(t); }
catch (InterruptedException e) { System.out.println("Fehler: bin eingeschlafen"); }
}
// zeige auf dem Bildschirm, falls noetig, lege einen neuen Rahmen an
public static void show() {
if (!defer) onscreen.drawImage(offscreenImage, 0, 0, null);
if (!defer) frame.repaint();
}
// als Datei speichern - Endung muss png, jpg, oder gif sein
public static void save(String filename) {
File file = new File(filename);
String suffix = filename.substring(filename.lastIndexOf('.') + 1);
// png Datei
if (suffix.toLowerCase().equals("png")) {
try { ImageIO.write(offscreenImage, suffix, file); }
catch (IOException e) { e.printStackTrace(); }
}
// etwas komplizierter bei JPG
// s. [url]http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727[/url]
else if (suffix.toLowerCase().equals("jpg")) {
WritableRaster raster = offscreenImage.getRaster();
WritableRaster newRaster;
newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
DirectColorModel cm = (DirectColorModel) offscreenImage.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(),
cm.getGreenMask(),
cm.getBlueMask());
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
try { ImageIO.write(rgbBuffer, suffix, file); }
catch (IOException e) { e.printStackTrace(); }
}
else {
System.out.println("Dateityp stimmt nicht: " + suffix);
}
}
// Speichern-Dialog fuer das Menue
public void actionPerformed(ActionEvent e) {
FileDialog chooser = new FileDialog(GrLib.frame, ".png oder .jpg Dateinamen verwenden", FileDialog.SAVE);
chooser.setVisible(true);
String filename = chooser.getFile();
if (filename != null) {
GrLib.save(chooser.getDirectory() + File.separator + chooser.getFile());
}
}
public static boolean mousePressed() { return mousePressed; }
public static double mouseX() { return mouseX; }
public static double mouseY() { return mouseY; }
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
public void mousePressed (MouseEvent e) {
mouseX = GrLib.userX(e.getX());
mouseY = GrLib.userY(e.getY());
mousePressed = true;
}
public void mouseReleased(MouseEvent e) { mousePressed = false; }
public void mouseDragged(MouseEvent e) {
mouseX = GrLib.userX(e.getX());
mouseY = GrLib.userY(e.getY());
}
public void mouseMoved(MouseEvent e) {
mouseX = GrLib.userX(e.getX());
mouseY = GrLib.userY(e.getY());
}
// kleine Testmethode
public static void main(String[] args) {
GrLib.square(.2, .8, .2);
GrLib.filledSquare(.8, .8, .2);
GrLib.circle(.2, .2, .2);
// fuer Zeichnung
GrLib.setPenColor(GrLib.GREEN);
double[] x = { .1, .2, .3, .2 };
double[] y = { .2, .3, .2, .1 };
GrLib.filledPolygon(x, y);
// fuer text
GrLib.text(0.8, 0.2, "Supi-Foo! Dupi-Bar!");
}
}
anhand dieser können wir arbeiten...
Bis jetzt hab ich nur etwas herum experimentiert, also Kästchen erstellt und z.B. per "mousePressed" die Farbe geändert usw...
Vllt. noch interessant zu wissen, wir arbeiten mit "BlueJ".
Würd mich über etwas Hilfe sehr freuen!!!
Danke schonmal!
Gruß
Dschuls