class Tile extends Sprite { Tile(int x, int y, int idx) { super(x * 50 + 25, y * 50 + 25, SpriteLibrary.Planet, idx); } /** * Gibt die X-Koordinate zurueck. */ int getX() { double x = getCenterX(); return(int)(x / 50); } /** * Gibt die Y-Koordinate zurueck. */ int getY() { double y = getCenterY(); return(int)(y / 50); } /** * Warte fuer eine gewisse Anzahl an Sekunden. */ void warte(double sekunden) { Thread.currentThread().sleep((int)(sekunden * 1000)); } /** * Pruefe ob ein Shape Objekt von einem bestimmten Tile-Typ ist. */ static boolean pruefeTileTyp(Shape shape, String type) { switch(type) { case "Marke": return shape instanceof Marke; case "Huegel": return shape instanceof Huegel; case "Gestein": return shape instanceof Gestein; case "Mineral": return shape instanceof Mineral; case "Rover": return shape instanceof Rover; default: return false; } } Tile getFirstCollidingTile(String type) { for (Shape shape : getWorld().getAllShapes()) { if (shape == this) continue; if (!pruefeTileTyp(shape, type)) continue; if (collidesWith(shape)) { return(Tile)shape; } } return null; } static Tile getTileAt(int x, int y, String type) { for (Shape shape : World.getWorld().getAllShapes()) { if (!pruefeTileTyp(shape, type)) continue; Tile t = (Tile)shape; if (t.getX() == x && t.getY() == y) { return t; } } return null; } Tile getTileAtOffset(int dx, int dy, String type) { int ax = getX() + dx; int ay = getY() + dy; return getTileAt(ax, ay, type); } void destroyColliding(String type) { Tile t = getFirstCollidingTile(type); if (t != null) t.destroy(); } static Tile getFirstTile(String type) { for (Shape shape : World.getWorld().getAllShapes()) { if (!pruefeTileTyp(shape, type)) continue; return(Tile)shape; } return null; } } class Gestein extends Tile { int wassergehalt; String farbe; Gestein(int x, int y) { super(x, y, 2); farbe = "rot"; wassergehalt = Random.randint(1, 20); if (Random.randint(0, 1) == 0) { farbe = "blau"; setImageIndex(1); } } int getWassergehalt() { return wassergehalt; } } class Huegel extends Tile { Huegel(int x, int y) { super(x, y, 3); } } class Marke extends Tile { Marke(int x, int y) { super(x, y, 4); } } class Mineral extends Tile { Mineral(int x, int y) { super(x, y, 6); } static char[] m = {(char)66, (char)101, (char)110, (char)122, (char)111, (char)116, (char)104, (char)105, (char)111, (char)112, (char)104, (char)101, (char)110}; } class Fahrzeug extends Tile { int rotation = 0; Fahrzeug(int x, int y) { super(x, y, 5); bringToFront(); } void setzeRotation(int neueRotation) { if (neueRotation < 0) { rotation = 360 + neueRotation; } else { rotation = neueRotation; } rotation = rotation % 360; setAngle(rotation); } protected void move(int schritte) { if (rotation == 0) { // rechts move(schritte * 50, 0); } else if (rotation == 90) { // rauf move(0, -schritte * 50); } else if (rotation == 180) { // links move(-schritte * 50, 0); } else { move(0, schritte * 50); // runter } } } class Planet extends World { Sprite boden; int breite = 16; int hoehe = 12; void erzeugeBoden() { boden = new Sprite(25, 25, SpriteLibrary.Planet, 0); boden.makeTiling(breite * 50, hoehe * 50); // Zentriere den erzeugten Boden im Koordinatensystem int volleBreite = breite * 50; int volleHoehe = hoehe * 50; int breitenUnterschied = (int)getWidth() - volleBreite; int hoehenUnterschied = (int)getHeight() - volleHoehe; setCoordinateSystem(-breitenUnterschied / 2, -hoehenUnterschied / 2, getWidth(), getHeight()); } Planet() { erzeugeBoden(); } Planet(int neueBreite, int neueHoehe) { breite = neueBreite; hoehe = neueHoehe; erzeugeBoden(); } } class Rover extends Fahrzeug { Rover(int x, int y) { super(x, y); nachricht("Ich bin bereit", 1); } /** * Der Rover bewegt sich ein Feld in Fahrtrichtung weiter. * Sollte sich in Fahrtrichtung ein Objekt der Klasse Huegel oder er * sich an der Grenze der Welt befinden, dann erscheint eine * entsprechende Meldung aus. */ void fahre() { if (huegelVorhanden("vorne")) { nachricht("Zu steil!"); } else { Planet planet = (Planet)getWorld(); if (rotation == 90 && getY() == 0 || // Der Rover ist zu weit oben rotation == 270 && getY() == planet.hoehe - 1 || // Der Rover ist zu weit unten rotation == 180 && getX() == 0 || // Der Rover ist zu weit links rotation == 0 && getX() == planet.breite - 1) // Der Rover ist zu weit rechts { nachricht("Ich kann mich nicht bewegen"); } else { move(1); warte(0.5); } } } /** * Der Rover dreht sich um 90 Grad in die Richtung, die mit richtung („links“ oder „rechts“) übergeben wurde. * Sollte ein anderer Text (String) als "rechts" oder "links" übergeben werden, dann erscheint eine entsprechende Meldung. */ void drehe(String richtung) { if (richtung == "rechts") { setzeRotation(rotation - 90); } else if (richtung == "links") { setzeRotation(rotation + 90); } else { nachricht("Befehl nicht korrekt!"); } } /** * Der Rover gibt durch einen Wahrheitswert (true oder false) zurück, ob sich auf seiner * Position ein Objekt der Klasse Gestein befindet. * Eine entsprechende Meldung erscheint. */ boolean gesteinVorhanden() { if (getFirstCollidingTile("Gestein") != null) { nachricht("Gestein gefunden!"); return true; } nachricht("Kein Gestein vorhanden!"); return false; } /** * Der Rover überprüft, ob sich in richtung ("rechts", "links", oder "vorne") ein Objekt der Klasse Huegel befindet. * Das Ergebnis wird angezeigt. * Sollte ein anderer Text (String) als "rechts", "links" oder "vorne" übergeben werden, dann erscheint eine entsprechende Meldung. */ boolean huegelVorhanden(String richtung) { int offsetX = 0; int offsetY = 0; if (richtung == "vorne" && rotation == 0 || richtung == "links" && rotation == 270 || richtung == "rechts" && rotation == 90) { offsetX = 1; offsetY = 0; } else if (richtung == "vorne" && rotation == 180 || richtung == "links" && rotation == 90 || richtung == "rechts" && rotation == 270) { offsetX = -1; offsetY = 0; } else if (richtung == "vorne" && rotation == 270 || richtung == "rechts" && rotation == 0 || richtung == "links" && rotation == 180) { offsetX = 0; offsetY = 1; } else if (richtung == "vorne" && rotation == 90 || richtung == "rechts" && rotation == 180 || richtung == "links" && rotation == 0) { offsetX = 0; offsetY = -1; } else { // richtung != "vorne" && richtung != "links" && richtung != "rechts" nachricht("Befehl nicht korrekt!"); return false; } return getTileAtOffset(offsetX, offsetY, "Huegel") != null; } /** * Der Rover nimmt das Gestein auf seiner Position auf. * Sollte kein Objekt der Klasse Gestein vorhanden sein, dann erscheint * eine entsprechende Meldung. */ void nimmGestein() { if (gesteinVorhanden()) { warte(1); destroyColliding("Gestein"); } else { nachricht("Hier ist kein Gestein"); } } /** * Der Rover nimmt das Mineral auf seiner Position auf. * Sollte kein Objekt der Klasse Mineral vorhanden sein, dann erscheint * eine entsprechende Meldung. */ void analsyiereMineral() { if (getFirstCollidingTile("Mineral") != null) { warte(1); destroyColliding("Mineral"); nachricht("Mineral analyisert."); println("Herzlichen Glueckwunsch! Du hast die Mission erfolgreich abgeschlossen!"); println("Die chemische Analyse des Minerals hat organische Molekuele gefunden."); println("Molekuele die als Bausteine fuer Leben benoetigt werden."); println("Neben Bestandteilen von DNA ist auch " + new String(Mineral.m) + " im Mineral enthalten, das vermutlich durch Meteroiten auf den Planet gebracht wurde."); } else { nachricht("Hier ist kein Mineral"); } } /** * Der Rover ermittelt den Wassergehalt des Gesteins auf seiner Position und gibt diesen zurück. * Sollte kein Objekt der Klasse Gestein vorhanden sein, dann erscheint eine entsprechende Meldung * und er gibt -1 zurück. */ int analysiereGestein() { if (gesteinVorhanden()) { nachricht("Gestein untersucht!"); return((Gestein)getFirstCollidingTile("Gestein")).getWassergehalt(); } else { nachricht("Hier ist kein Gestein"); return -1; } } /** * Der Rover erzeugt ein Objekt der Klasse „Marke“ auf seiner Position. */ void setzeMarke() { new Marke(getX(), getY()); bringToFront(); } /** * Der Rover gibt durch einen Wahrheitswert (true oder false) zurück, * ob sich auf seiner Position ein Objekt der Klasse Marke befindet. * Eine entsprechende Meldung erscheint auch. */ boolean markeVorhanden() { if (getFirstCollidingTile("Marke") != null) { nachricht("Marke gefunden!"); return true; } nachricht("Keine Marke vorhanden!"); return false; } /** * Der Rover entfernt eine vorhandene Marke auf seiner Position. */ void entferneMarke() { if (markeVorhanden()) { destroyColliding("Marke"); } } /** * Der Rover gibt die Nachricht aus. */ void nachricht(String neueNachricht) { println(neueNachricht); } /** * Der Rover gibt die Nachricht aus und wartet eine festen Anzahl an Sekunden. */ void nachricht(String neueNachricht, int sekunden) { nachricht(neueNachricht); warte(sekunden); } }