# STARTHILFE gesucht !! Java-Projekt für Schule !!



## death90 (23. Feb 2009)

*Hallo,*

ich mache zur Zeit mein Abitur und bin im 2. halbjahr der 13. Klasse !
Wir machen seit Beginn der 13. Klasse Java im Informatik Unterricht !

Unser Lehrer ist leider Gottes selten dämlich und hat fast weniger Ahnung
von Java und Informatik allgemein als wir 

*Nun zum Sachverhalt:*
Über das gesamte 2. Halbjahr muss jeder ein Projekt in Java erstellen (Spiel programmieren). Das Spiel soll Grafisch und mit Cursorsteuerung ausgestattet sein.
Ich habe mich für eine vereinfachte Version dieses Flash-Spiels entschieden:
~Hier "The Missile Game"~

Meine vereinfachte Version soll im Groben einen Hintergrund haben, ähnlich einer Röhre, wie im Flash-Spiel ! Weiterhin sollen per zufall die schon im Flash-Spiel zusehenden Scheiben genriert werden bzw. in einem Container bereits erstellt und dann nur per zufall in den Hintergrund (Röhre) gezeichnet werden. Es soll kein Sound mit rein ! Es soll wie im Flash-Spiel ein Fallen bzw. Fliegen eines Objekts in Ich-Perspektive durch diese Röhre stattfinden.
Man soll durch die zufällig gezeichneten Scheiben durchfliegen/durchfallen, wobei die geschwindigkeit des fliegens/fallens mit der zunehmenden Zeit immer höher wird, bis man einen Fehler macht und irgendwo gegen fliegt/fällt ! (Ohne weitere Leben)
Im Endeffekt steht dann im verdunkelten Endbildschirm "Spiel beendet" und darunter die Zeit die man geschafft hat. (z.B. nach 1:20min. gestorben etc. )
alles mit Maussteuerung und ohne weitere Leben/Level/Schwierigkeiten oder einstellungen...Also sehr abgespekt !

*Meine Fragen sind nun:*
- Wie erstelle ich diese Scheiben (Polygon Objekt ?)
- Wie gehe ich die Sache an ?
- brauche ich unbedingt Java 3D ?
- Wie den Hintergrund erstellen ?
- wie kann ich bei Berührung der Scheiben außerhalb der Durchlässe das Spiel beenden lassen ?

Ich frage das alles, da unser Informatik Lehrer uns nichts beibringt und macht was er will. Wir sollen uns die gesamte Theorie selbst erarbeiten und das letzte was wir gemacht hatten war ein wenig grafik mit Swing und AWT....mehr nicht, weshalb wir bzw. ich ziemlich aufgeschmissen bin 

Ich bite inständigst um Hilfe !!!!

Ich brauche wie gesagt eine Starthilfe !

Riesen Dank schonmal im voraus an Alle, die helfen !

MfG
Benni


----------



## Ebenius (23. Feb 2009)

Hallo Benni,

wenn Du nicht wirklich Ahnung von Java hast, warum denn gleich ein Spiel mit 3D? Wie wäre denn etwas einfacheres, wie zum Beispiel Tic Tac Toe, 4 Gewinnt, Snake, Galgenraten, ...? Wenn Du zu schnell vorwärts kommst, dann kannst Du die Spiele ja hinterher aufsexen, mit lustigen kleinen Zusatzbildern, wenn die Schlange sich in den Schwanz beißt, oder ähnliches. Aber Du riskierst nicht von Anfang an, mit Deinem Projekt nicht fertig zu werden.

Grüße,
Ebenius


----------



## death90 (23. Feb 2009)

Hallo,

erstmal danke für deine Antwort...
Es ist ja nicht so, als hätte ich gar keine Ahnung von Java, da wir die Grundlagen ja kennen und schon vorher mit Turbo Pascal und ich Privat schon mit C++ und Flash zutun hatte.

Das Problem ist, das wir unser projekt festlegen mussten und mir dies auf anhieb und Überlegung erstmal ganz gut erschien...wir haben noch bis Ostern Zeit, um das Spiel wenigstens im Groben spielbar zu erstellen...
Ein Wechsel kommt für mich jetzt leider nicht mehr in Frage und ist auch nicht möglich !
Sonst hätte ichs wahrscheinlich schon getan 

Naja ich brauche wie gesagt etwas Starthilfe !

MfG
Benni


----------



## Marco13 (23. Feb 2009)

Vorneweg: Du wirst dich daran gewöhnen müssen, dir Sachen selbst beizubringen. 

Die Fragen, die du gestellt hast ("Wie gehe ich die Sache an ?"), sind etwas zu allgemein. Darum nur ein bißchen Stichpunktartiger, subjektiver Senf:
Diesen 3D-Effekt hinzukriegen könnte "tricky" bis "unverhältnismäßig aufwändig" werden. Die Option, Java3D zu verwenden, würde dich zwar einerseits dramatisch entlasten, weil da Clipping, Rotationsmatrizen, Szenegraph und Camera schon drin sind, aber die Einarbeitungszeit kann recht hoch sein. 
Die Scheiben...die Einfachste Lösung wäre, die Scheiben einmal Vordefiniert zu erstellen (das ist AUCH nicht einfach, aber einfacher, als sie programmatisch zu erstellen) und dann zufällig eine Auszuwählen. In Java3D wären die ein Shape3D, das man vielleicht aus einer OBJ-Datei erstellen könnte. In Java2D wären Polygone wohl ganz OK.
Die Berührung der Scheibe zu erkennen wäre mit einem Polygon fast noch einfacher: Man fragt einfach, ob es den Punkt enthält, an dem man sich gerade befindet. Bei Java3D gibt's zwar auch Kollisionserkenner, aber die sind... naja.

Aber zusammengefasst: Das ganze kann (so oder so) schon ziemlich aufwändig werden.


----------



## hdi (23. Feb 2009)

edit: Nein, das war keine Hilfe sondern nur Rumgerate 
Aber krank, was man heute so in der Schule alles machen muss


----------



## 0x7F800000 (23. Feb 2009)

Hmm, naja, 3D ist an der Sache wirklich nichts, aber es ist eine sehr Hübsche Illusion. Da muss man wohl auch sagen, dass es wirklich mit dem geeignetsten Werkzeug erstellt wurde: für solche kleine aber graphisch hübsche Sinnestäuschungen ist Flash wesentlich angebrachter, als das "plumpe" AWT.

Aber mit ein bisschen Mühe kriegt man das natürlich auch mit AWT hin. Die scheiben an sich würde ich wohl einfach als gif's erstellen und ein wenig mit AffineTransform gedreht zweimal etwas versetzt und verklcinert hinzeichnen. Der 3D eindruck im Spiel scheint auch dadurch zu entstehen, dass zweimal dieselbe platte Form hingemalt wird, wie so eine Art schatten: man sieht ja immer nur einen dünnen Rand, der dazu etwas dunkler zu sein scheint. Wirklich 3D sind die aber nicht, das sind wirklich nur platte Bilder.

Die parallelen Linien sind auch pseudo-3D. Der 3D-Effekt wird dadurch erzeugt, dass der Fluchtpunkt immer in der Mitte bleibt, dafür jedoch ein "Kreis" in der Bildebene, an dem die Linien befestigt sind, hinundhergeschoben wird. Wandert die maus nach links, so wandert der kreis nach rechts usw. Um den Effekt zu verstärken, werden die abstände zwischen den "befestigungspunkte" der parallelen linien variiert werden: wenn man nah an der Röhrenwand ist, scheint der Abstand zwischen den zwei nächsten parallelen geraden sehr groß zu sein, während alle anderen Linien auf der anderen seite enger zusammenrücken. Die Scheiben werden von dem Effekt nicht betroffen.

Wie die abstände umverteilt werden? Nanja, ich glaube nicht, dass da korrekte geometrie darin steckt, wahrscheinlich wird das Intervall [0,2PI] einfach wieder auf [0,2PI] abgebildet, und zwar so, dass die Punkte 0, PI und 2PI dort bleiben wo sie sind, und alles andere durch sowas wie ein polynom dritten Grades verzerrt wird (dieses Polynom steigt zuerst stark an, in der mitte ist es flacher, am ende steigt es nochmal steil an) Dadruch wird dieser verzerrungseffekt erreicht. Wenn du wissen willst, wie ich das konkret meine, dann Frag hier am Wochenende nochmal nach, k?^^ grad zeitdruck.

Ansonsten: Viel spaß mit AWT!


----------



## death90 (23. Feb 2009)

hallo,

erstmal vielen Dank für die vielen raschen Antworten !

einmal hat mich ein wenig schockiert, das es wohl doch sehr schwer sein soll zu programmieren, was sich hoffentlich noch ändert und ich eine gute, nicht ganz so schwere Lösung finde...

Eine andere Sache ist, dass ich froh bin nicht mit Java 3D arbeiten zu müssen....

eine frage bleib aber noch:...welche Lösung wäre einfacher umzusetzten ? 3D API oder 2D ?

und

Wie erstelle ich eine Kreisfläche mit integriertem Polygon Objekt, um quasi diese Scheiben zu erzeugen,...oder soch lieber ganz anders ?

und

Wenn ich kein Java 3D nehme, wie erzeuge ich dann nochmal genau diesen 3D effekt in verbindung mit der Maussteuerung ?

ich hoffe noch auf viele Antworten und ich werde meine Ergebnisse natürlich mit euch teilen und euch auf dem laufenden halten.... 

MfG
Benni


----------



## 0x7F800000 (23. Feb 2009)

Fragen wir mal andersherum: was war deine beste Note in Bildender Kunst für's perspektivische Zeichnen? Wie gesagt, das ist alles eine sehr clevere Illusion, mit Mathe und 3D-Api's kommt man da früher oder später ans Ziel, aber da geht die ganze Eleganz verloren. Das eigentliche Spiel ist womöglich keine 128 zeilen lang, weil es eben mit einem passenden werkzeug clever gelöst wurde.

Also, was ich sagen will: wenn du nicht denselben shicken Trick wie im Originalspiel anwendest, sondern anfängst hier mit den ganzen Krassen J3D-API's rumzuballern, dann kommst du auch früher oder später an's Ziel, aber eben nach 1500 Statt 150 Zeilen. Daher empfehle ich doch dringend, sich ein paar gedanken über die fiesen Tricks der fleißigen aber mathematisch nicht allzu begabten Straßenkünstler des 17. Jahrhunderts zu machen. Dann sieht's coll aus, und passt in 8. schriftgröße auf 2 dinA4 Zettel, wo dein lehrer dann mit dem roten stift rumfummeln kann. Andernfalls wäre der Aufwand tatsächlich unverhältnismäßig groß, dann könntest du auch gleich anfangen Quake 1-2-3 zu klonen...


----------



## Quaxli (24. Feb 2009)

Ich frage mich gerade, wie anspruchsvoll Dein Lehrer ist? Und wie genau ist Dein Projektbeschreibung bzw. wie sklavisch mußt Du Dich daran halten? 

Ich würde erst mal mit der Röhre anfangen und alles andere außen vor lassen. Eine einfache Röhre ohne die perspektivische Verschiebung kriegt man in 10 Minuten hin (etwas länger, wenn man keine Üung hat ). Die könntest Du dann aufsexen, wie sich Ebenius so schön ausgedrückt hat. 
Erst wenn das soweit klappt, daß Du zufrieden bist, frickelst Du Hinternisse rein. Auch hier könnte man es erst mal etwa einfacher gestalten. Ohne Drehung und Variation. Einfach ein un dasselbe Hinterniss. Wenn das Spiel immer schneller wird, knallt man irgendwann dagegen 
Und so weiter und so fort. Ich denk schon, daß man das in 2D realisieren kann.


----------



## death90 (9. Mrz 2009)

*Hallo liebe Leute,*

ich melde mich nun mal wieder !

Ich habe meine Idee vom Spiel nun etwas abgespekt ! 

Also folgendes ist nun noch übrig: (Spiel heißt jetzt ganz Primitiv "Fall Of Ball" ^^)
- im Hintergrund die im Flash-Spiel zu sehende Röhre (Es muss sich nichts drehen, hauptsache iwie den 3D Effekt zustande bringen)
- Bewegung in Ich-Perspektive durch die Röhre (besagter 3D Effekt, aber ohne Java3D)
- per Zufall einfügen dieser vordefinierten Scheiben in die Röhre (siehe Flash-Spiel)
- Spielgeschwindigkeit anzeigen lassen und langsam erhöhen (Keine Levels mehr)

Das wars schon im Groben !

*ich geb mal noch ein Paar Erläuterungen:
*
*zufällige Scheiben:* - Ich dachte mir die Scheiben in ein extra Objekt-Handle erstellen zu lassen und diese beim Programmstart per Methodenaufruf bereit vorladen zu lassen, um Performance-Einbußen während des Spiels zu laden !

*Spielgeschwindigkeit:* - Es soll eine Anzeige während des Spiels angezeigt werden, die mit 0% startet und erstmal zügig auf 100% ansteigt, d.h. das komplette Spiel wird stetig beschleunigt. Bei 100% soll man erstmal kurz spielen (max. 30 sek.), bevor die Spielgeschwindigkeit weiter ansteigt (diesmal ohne stop, also durchgehend).
Bei vielleicht 300% oder so soll dann Schluss sein und man spielt solange bis man irgendwo kollidiert, wenn man nicht bereits woher schon iwo kollidiert ist.

*Ziel:* - Man spielt eine Kugel/Ball in Ich-Perspektive und "fällt" quasi diese Röhre runter, wobei sich die Spielgeschwindigkeit und damit auch die Geschwindigkeit der zufällig gezeichneten Scheiben erhöhen soll. Im Hintergrund wird die Zeit in Min./Sek., vom Start bis zur Kollision gezählt und in einem Game Over Bildschirm angezeigt + die erreichte Geschwindigkeit. Man muss den Ball in der Ich-Perspektive per Cursorsteuerung durch diese Scheiben steuern. Das wars schon 

naja habe mir schon gedanken gemacht und ein paar Methoden für die Skalierung, die Objekte usw. entworfen.

*Meine Fragen sind jetzt nur noch:*
1. Wie erstelle ich nun diese Röhre am besten, damit dieser 3D Effekt zustande kommt ? (ein Gif o.ä. in ein BufferedImage laden und als Hintergrund zeichnen lassen oder Röhre selbst zeichnen lassen?)

2. Wie erstelle ich am besten diese Scheiben ? (Kreis zeichnen lassen + integriertem Polygon-Objekt?)

3. Wie bekomm ich diese Perspektivische Verschiebung hin, wenn man weiter an den "Rand" der Röhre kommt ? (soll nicht auf Scheiben angewendet werden, nur auf die Röhre, damit diese 3D wirkt, siehe Flash-Spiel)

Ich danke euch schonmal im vorraus und hoffe jemand ist so tollerant,
um mir da echt weiterzuhelfen.

Bekomm schließlich ne Zensur dafür !

PS: Ich weiß das ich noch nich viel Ahnung von Java habe, aber unsere Info-Lehrerin
is dermaßen blöde, das die det nicht rafft. Sie meint das es vom Ministerium so vorgegeben ist,..jaja..blabla...^^

Naja hoffe auf Rat.

Danke

Gruß
Benni


----------



## g0d3x (9. Mrz 2009)

Ich bin ja auch in deinem Info-Kurs und ja , es stimmt leider is unsere Lehrering ist wirklich nicht die schlaueste , sie weist jedes Frage-Antwort-Spiel von sich und tut so als wär sie die Queen of Computer Science, is sie aba nicht :lol:. Ich hab auch so ein Problem mit meinem Spiel, da mir ebenfalls der komplette theoretische Hintergrund fehlt, um so etwas zu bewältigen. Ich möchte gerne ein Highscorezähler für verschiedene Objekte programmieren, weiss aba nicht genau ob es ausreicht, jeweils eine Zählevaribale in die einzelnen Entitys einzubauen oder doch lieber eine komplette Klasse dafür zu schreiben. Achso ich versuche mich an einer Kopie von SpaceInvaders mit kleinen Extras.
 ein kleiner Tipp oder eine Anregung würden mir reichen. 

thx im Vorraus 

g0d3x


----------



## hdi (9. Mrz 2009)

Also deine Frage ist eigentlich: Wie mache ich das?

...immerhin sind genau diese Dinge die Arbeit an dem Spiel: 3d-Röhre, Hindernisse, Bewegung in der Röhre.

Dieser ganze Schnickschnack vonwegen Geschwindigkeit erhöhen, und Anzeige von
irgendwelche Dingen ist ja kein Ding.

Kurz zu deiner Idee mit dem Vorladen: Nicht nötig, das is überhaupt kein Problem,
während des Spiels ein solches Objekt zu erstellen.

Naja, also nach wie vor die gleichen Probleme: Wie kriegst du so ein 3D Spiel hin..
Ich kann nur wiederholen was ich schonmal sagte, und zwar dass ich diese Aufgabe
mal total übertrieben für die Schule finde.

Natürlich hilft dir das nicht weiter, alles was ich sagen will ist eigentlich:
Halt dich nicht auf das Spiel bis ins Detail auszuplanen, kuck dass du einfach
mal ne 3D Röhre hinkriegst.
Dann kuck wie man sich darin bewegen kann.
Dann mach die Hindernisse.

Der Rest ist dann einfach nur noch Schreibarbeit, und n bisschen Logik was aber
kein Problem ist.

Genug Palaber: Du willst kein Java3D, d.h. du musst das Mapping von 3d zu 2d manuell
machen.

Schau dir diesen Code mal an: (das Programm lässt sich starten, mit der Maus
kannste was machen)

---- CODE by: *Marco13* ---

[HIGHLIGHT="Java"]import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Cube3DTest extends JFrame implements MouseListener, MouseMotionListener,
      MouseWheelListener {

   public static Cube3DTest c3dtest;

   public static void main(String[] args) {
      c3dtest = new Cube3DTest();
      c3dtest.setVisible(true);
   }

   public int width = 200;
   public int height = 200;
   public JPanel panel;
   public float distance;
   public float angle;
   Point prev = new Point();
   public Cube cube;

   public Cube3DTest() {
      super("3D Demo");

      /* view setup */
      angle = (float) Math.toRadians(40);
      distance = (width / 2) / (float) (Math.tan(angle / 2));
      System.out.println("distance: " + distance);

      panel = new JPanel() {
         @Override
         protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            cube.project(g);
         }
      };
      panel.setPreferredSize(new Dimension(300, 300));
      add(panel);
      pack();
      setLocationRelativeTo(null);
      setDefaultCloseOperation(EXIT_ON_CLOSE);

      this.addMouseListener(this);
      this.addMouseMotionListener(this);
      this.addMouseWheelListener(this);

      cube = new Cube();
   }

   class Cube {

      public int size = 50; // kantelänge
      Vector3D ulf, urf, llf, lrf; // upper left front, upper right front, usw..
      Vector3D ulb, urb, llb, lrb; // upper left back ,...

      public Cube() {
                        // würfel soll zentriert sein, die koordinaten für den oberen linken (front-)punkt also:
         int startx = width / 2 - size / 2;
         int starty = height / 2 - size / 2;

                       // alle 8 würfel-punkte:
         ulf = new Vector3D(startx, starty, 0);
         urf = new Vector3D(startx + size, starty, 0);
         llf = new Vector3D(startx, starty+size, 0);
         lrf = new Vector3D(startx + size, starty + size, 0);

         ulb = new Vector3D(startx, starty, -size);
         urb = new Vector3D(startx + size, starty, -size);
         llb = new Vector3D(startx, starty+size, -size);
         lrb = new Vector3D(startx + size, starty + size, -size);
      }

      public void move(int dx, int dy)
      {
         ulf.x += dx;
         urf.x += dx;
         llf.x += dx;
         lrf.x += dx;
         ulb.x += dx;
         urb.x += dx;
         llb.x += dx;
         lrb.x += dx;

         ulf.y += dy;
         urf.y += dy;
         llf.y += dy;
         lrf.y += dy;
         ulb.y += dy;
         urb.y += dy;
         llb.y += dy;
         lrb.y += dy;

      }


      public void project(Graphics g) {

         Point pulf = ulf.to2D();
         Point purf = urf.to2D();
         Point pllf = llf.to2D();
         Point plrf = lrf.to2D();
         Point pulb= ulb.to2D();
         Point purb= urb.to2D();
         Point pllb= llb.to2D();
         Point plrb= lrb.to2D();

         g.drawLine(pulf.x, pulf.y, purf.x, purf.y);
         g.drawLine(pulf.x, pulf.y, pllf.x, pllf.y);
         g.drawLine(pulf.x, pulf.y, pulb.x, pulb.y);
         g.drawLine(purb.x, purb.y, pulb.x, pulb.y);
         g.drawLine(pllb.x, pllb.y, pulb.x, pulb.y);
         g.drawLine(pllb.x, pllb.y, pllf.x, pllf.y);
         g.drawLine(pllb.x, pllb.y, plrb.x, plrb.y);
         g.drawLine(purb.x,purb.y, plrb.x, plrb.y);
         g.drawLine(purb.x,purb.y, purf.x, purf.y);
         g.drawLine(plrf.x, plrf.y, purf.x, purf.y);
         g.drawLine(plrf.x, plrf.y, pllf.x, pllf.y);
         g.drawLine(plrf.x, plrf.y, plrb.x, plrb.y);
      }

      public void further() {
         ulf.z -= 1;
         urf.z -= 1;
         llf.z -= 1;
         lrf.z -= 1;
         ulb.z -= 1;
         urb.z -= 1;
         llb.z -= 1;
         lrb.z -= 1;

      }

      public void closer() {
         ulf.z += 1;
         urf.z += 1;
         llf.z += 1;
         lrf.z += 1;
         ulb.z += 1;
         urb.z += 1;
         llb.z += 1;
         lrb.z += 1;

      }
   }

   class Vector3D {
      public float x, y, z;

      public Vector3D(float x, float y, float z) {
         this.x = x;
         this.y = y;
         this.z = z;
      }

      public String toString() {
         return "(" + x + "," + y + "," + z + ")";
      }

      public Point to2D() {

         Point p;
         /* 3d -> 2d */
         float Z = distance + z;
         p = new Point((int) (distance * this.x / Z), (int) (distance * this.y / Z));


         p.x += width / 2;
         p.y += height / 2;

         System.out.println(this + " -> (" + p.x + "," + p.y + ")");
         return p;
      }
   }

   @Override
   public void mouseWheelMoved(MouseWheelEvent e) {
      if (e.getWheelRotation() < 0) {
         // zoom in
         cube.closer();
         panel.repaint();
      } else {
         // zoom out
         cube.further();
         panel.repaint();
      }

   }

   @Override
   public void mouseClicked(MouseEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void mouseEntered(MouseEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void mouseExited(MouseEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void mousePressed(MouseEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void mouseReleased(MouseEvent e) {
      // TODO Auto-generated method stub

   }
   @Override
   public void mouseMoved(MouseEvent e) {
      prev = e.getPoint();
   }
   @Override
   public void mouseDragged(MouseEvent e) {
      int dx = e.getX()-prev.x;
      int dy = e.getY()-prev.y;
      cube.move(dx,dy);
      panel.repaint();
      prev = e.getPoint();
   }
}[/HIGHLIGHT]

Verstehe es, spiel damit rum.

Versuch dann aus dem Quader eine Röhre zu machen, schieb das ganze rum
und verändere die Koordinaten damit zu siehst wie ungefähr das intern aussieht
wenn du so einen Blick in eine Röhre willst.

Wenn du das hast, hast du die Röhre.

Denn im Spiel bewegt sich die Röhre ja nicht, das sieht nur so aus als ob man durchfliegt.
Nur diese Hindernisse werden hinten in der Röhre erstellt und fliegen vorwärts.


----------



## death90 (9. Mrz 2009)

@hdi

Hallo,

ich dank dir erstmal 1000Fach für das Beispiel ! jetzt kann ich mir erstmal richtig vorstellen, wie ichs angehen kann/muss !

Ich werde mich da mal reinarbeiten und schauen wie weit ich da komme ! :rtfm:

Naja eine Frage hätte ich aber nochmal, ist es klug das Spiel in mehrere Dateien aufzusplitten ? (Start.java + Objects.java + Bin.java) ?

Das war jetzt mal so meine Vorstellung. Objects.java soll ein Handle sein, indem die Objekte erstellt werden. Bin.java könnte vielleicht die Berechnungen usw. enthalten!
Ist das überhaupt sinnvoll ?

Danke schonmal für die Antworten !

Gruß
Benni


----------



## hdi (9. Mrz 2009)

Eine der Grundideen von OO Programmierung ist Probleme zu abstrahieren.
Von daher macht es immer Sinn Dinge in einzelne Dateien zu splitten.

Für Anfänger macht es das aber oft schwieriger als alles in eine Klasse zu schreiben,
weil man sich dann überlegen muss wie diese Klassen kommunizieren.

Aber allein für Testzwecke ist es eben eleganter, eigene Klassen zu schreiben.
Beispielsweise solltest du erstmal ein Hinderniss im freien Raum testen,
bevor du es irgendwie in eine Röhre setzt.

Ich würd jetz - grob gesagt - folgende Klassen machen:

Start.java (Macht Initialisierungen, startet deine GUI)
GameFrame.java (Das ist dein Spielfenster, das zB ein Menü enthält und ein:
ArenaPanel.java (Das ist wo gezeichnet wird, also das spiel an sich dann
Hindernis.java (Enthält Aufbau und Grundlogik von Hindernissen)
HindernisCreator.java (statische Klasse die ein bestimmtes Hindernis erstellt)
GameLoop.java (Steuert das Spiel, indem er sich Objekte vom HindernisCreator holt, die Geschwidnigkeit erhöht, die Zeit mitzählt usw.)


----------



## death90 (9. Mrz 2009)

Hallo,

meine Fresse bist du schnell ! ^^
Machst du das Posten hier hauptberuflich ? *Joke**grins*

naja wie gesagt danke ich dir mal wieder!

Ich wollte zwar das Programm splitten aber nicht in soviel Teile.
Es ist für mich so schon kompliziert genug, deswegen würden mir eigentlich schon 3 Dateien genügen.

Ich dachte da mal an: 1. Start.java, 2. Objects.java, 3. Bin.java !

*zu1.* dort soll schon fast alles rein ^^....Spielfeld hab ich schon drin ! dann den Zufallsgenerator (evtl.), den GameLoop, Die Röhre + Verschiebung oder so, halt fast alles wichtige ^^.

*zu2.* hier sollen die Hindernisse rein + Aufbau und logik wenns geht, halt alles was dazu gehört !

*zu3.* hier die mathematischen sachen, Zähler, Bewegung evtl., usw.

Ist das irgendwie auch in diesen 3 Klassen zu realisieren ? Also ich würde schon gerne bei max. diesen 3 Dateien bleiben, aber vielleicht hast du noch ein paar Ideen, was ich wo rausnehmen und wo mit reinnehmen sollte ?

Danke mal wieder im vorraus !

Gruß
Benni


----------



## hdi (9. Mrz 2009)

edit:
Naja mach's wie du willst 

Du kannst ja auch erstmal alles in eine Klasse schreiben und alle Variablen
public machen, nur damit du das spiel mal hinkriegst.

Danach kannst du noch immer umschreiben und Dinge kapseln. 
Ist zwar eigentlich doppelte Arbeit, aber als Anfänger ohne grosse Design-Erfahrung
geht das noch immer schneller als zu versuchen, eleganten Code zu schreiben und 
dabei kein Stück weiter zu kommen oder irgendwo hängen zu bleiben.

Wenn du ne Note drauf kriegst, schau erstmal dass es überhaupt läuft, sonst 6 oder?
Und wenn's dann am Ende nich so geil gecodet ist: Was soll's, das Spiel läuft!


----------



## Quaxli (11. Mrz 2009)

Ich hab' mal ein bißchen mit rumgespielt, weil's mich interessiert hat. Ich hab mal eine Jar-Datei angehängt. Da man in diesem Java-Forum keine Jar-Dateien anhängen darf, habe ich sie nach zip umbenannt. Also runterladen, umbenennen, doppelklicken 

Das Ganze ist sehr primitiv. Aber es wird eine "Röhre" aus Grafikprimitiven erzeugt und man kann mit den Cursor-Tasten ein bißchen steuern, wobei ich nicht abgefangen habe, daß zu weit gesteuert wird - ist ja nur ein Versuch. 

Da es eine Hausaufgabe ist und Du die Arbeit machen sollst, habe ich keine Source-Dateien reingepackt und werde auch keinen Code posten.


----------



## Marco13 (12. Mrz 2009)

hdi hat gesagt.:


> ...
> ---- CODE by: *Marco13* ---
> ...



Ich erinnere mich, dass ich dem Ersteller dieses Codes mal irgendeinen Hinweis gegeben hatte, weil er da ein Problem mit der perspektivischen Darstellung hatte. Aber ich finde es ...zumindest unangemessen... MIR solchen... :autsch:

```
ulf.x += dx;
         urf.x += dx;
         llf.x += dx;
         lrf.x += dx;
         ulb.x += dx;
         urb.x += dx;
         llb.x += dx;
         lrb.x += dx;
```
:autsch: - Code zuzuschreiben....


----------



## hdi (12. Mrz 2009)

@Marco
Okay, das kann ich nachvollziehen  Sorry dafür, ich dachte ich will nur keinen Code
zitieren und meinen Namen hinschreiben, wenn es eigentlich dir zu verdanken ist,
dass die Demo funzt und einen Sinn macht.

Dass der Code scheisse aussieht, da hab ich jetz nich so dran gedacht.
Aber ich glaub du stehst da drüber, oder


----------



## slawaweis (13. Mrz 2009)

@death90
das verlinkte Flash-Spiel ist eine reine 2D-Lösung. Selbstverständlich kann man es auch mit 3D umsetzen, aber das Flash-Spiel ist jedenfalls 2D. Ich habe aus Experimentierfreude die Kernfunktionalität nachgebildet, sehe Screenshot im Anhang. Wenn Du willst, poste ich meinen Quelltext.

Falls Du das Spiel in 2D machen willst, musst Du vor allem Java2D kennen. Dazu empfehle ich das Buch "Java 2D Graphics" von Jonathan B. Knudsen, es ist wirklich gut und in vielen Bibliotheken zu finden. Es wurde zwar 1999 geschrieben, ist aber Heute genauso aktuell wie vor 10 Jahren, Java2D hat sich kaum verändert. Wenn man sich ransetzt, kann man das Buch in einer Woche durcharbeiten. Hinzu noch etwas Trigonometrie aus der Schule, wie Punkt auf einer Linie oder einem Kreis bestimmen. Dann noch etwas über Threads nachlesen und man hat schon die ganzen Grundlagen die man braucht.

Slawa


----------



## Marco13 (13. Mrz 2009)

Irgendwie habe ich das Gefühl, dass die Definitionen und Interpretationen hier leicht ... unterschiedlich sind. Aber ... streng genommen sind ja ALLE Lösungen nur 2D. Spätestens, wenn sie durch eine zweidimensionale, rechteckige Anordnung von Pixeln dargestellt werden.


----------



## slawaweis (13. Mrz 2009)

Marco13 hat gesagt.:


> Irgendwie habe ich das Gefühl, dass die Definitionen und Interpretationen hier leicht ... unterschiedlich sind. Aber ... streng genommen sind ja ALLE Lösungen nur 2D. Spätestens, wenn sie durch eine zweidimensionale, rechteckige Anordnung von Pixeln dargestellt werden.


oh ja, sage das meinem Bekanntenkreis, wenn mal wieder ein 3D-Animationsfilm im Kino läuft. Die werden dich eines besseren belehren 

Ich habe bei meiner Lösung allerdings mit 2D-Koordinaten gearbeitet, also betrachte ich es auch als 2D-Lösung. Ist eben eine optische Täuschung.

Slawa


----------



## Marco13 (15. Mrz 2009)

Auch ein 3D-Film ist nur 2D. Das linke und rechte Auge bekommen verschiedene Bilder, so dass man "denkt", es wäre 3D, aber das ist es nicht. Es sind nur 2 unterschiedliche 2D-Bilder. Also, in dem Moment wo man die 2D-Koordinaten so anpasst, dass es nach 3D aussieht, ist es genauso 3D wie der neueste, aufwändigste 3D-Animations-Blockbuster... ("genauso" hat hier eine Bedeutung, die man nicht überinterpretieren sollte...)


----------



## hdi (15. Mrz 2009)

Geil, eine Grundsatzdiskussion  Man muss unterscheiden, worüber man redet: 
Darüber, wie etwas aussieht, oder darüber, wie etwas ist?

Objekte aus der Realität sind 3d, obwohl sie wie 2d aussehen können.
Und Flächen sind per Definition 2d, obwohl sie wie 3d aussehen können.
Nicht-Greifbares kann beliebige Dimensionen haben (1-n).
Mit "nicht-greifbar" mein ich einfach "erfundenes", oder virtuelles.

Bei Spielen wie diesem hier hat man nicht-greifbare Objekte, die 3d _sind_, 
und was man sieht, ist eine Fläche, die 2d ist.

Deswegen wundert mich auch grad diese Aussage:


> Ich habe bei meiner Lösung allerdings mit 2D-Koordinaten gearbeitet



Es ist doch gar nicht _möglich_, so ein Spiel mit 2d-Objekten zu erstellen.
Das ist wie wenn du Pong mit 1d-Objekten programmieren willst.
Da fehtl doch eine Info, um den Spielablauf zu regeln, und daraus resultiert dass
du da nix gescheites zur Anzeige bringen kannst.

edit: Ok sry es ist möglich. Theoretisch. Aber doch nicht in der Praxis, was soll
das für ein Algorithmus sein der hunderte 2d-punkte bei einer Bewegung anpassen soll?
Das kann man doch nich ausrechnen, wie sich das verschiebt, wenn man intern
nicht diese Tiefen-Info hat..


----------



## 0x7F800000 (15. Mrz 2009)

hdi hat gesagt.:


> Objekte aus der Realität sind 3d, obwohl sie wie 2d aussehen können.


Hoffentlich nicht, sonst ist schon wieder alles am Arsch, und die Physiker müssen wieder ein Jahrhundert lang nach einer neuen plausiblen Theorie suchen:
etwa sieben fehlen noch

Außerdem wär's mit ein paar dimensionen mehr doch viel lustiger, wie gefällt dir zB. ein Schwarzes Loch mit folgender Topologie:
"schwarzer Saturn". Hab irgendwo ein lustiges Artikel gesehen, wo irgendwelche schlauen leute richtig viele Typen von Schwarzen Löchern mit unterschiedlicher Topologie bei der annahme von 1-2 weiteren [evtl kompakten] Dimensionen klassifiziert haben: da wird die vielfalt schwarzer Löcher richtig bunt! tolle Sache^^ 



> Es ist doch gar nicht _möglich_, so ein Spiel mit 2d-Objekten zu erstellen.
> Das ist wie wenn du Pong mit 1d-Objekten programmieren willst.
> Da fehtl doch eine Info, um den Spielablauf zu regeln, und daraus resultiert dass
> du da nix gescheites zur Anzeige bringen kannst.


Ich habe es vorhin schon gesagt, und sage es jetzt auch: es ist alles pures 2D. Alle Objekte sind rein 2D. Alle Koordinaten werden rein 2D abgespeichert. Es gibt halt noch zusätzlich ein paar extra variablen wie zeit/geschwindigkeit und tiefe, aber diese werden wohl separat von anderen Koordinaten abgespeichert. Hier werden jedenfalls keine der 3D-Typischen transformationen mit diesen 4x4-Matrizen ausgeführt, die Grafikkarten so gerne zum frühstück essen. Einfach nur eine sehr hübsche Illusion.


----------



## Illuvatar (15. Mrz 2009)

Andrey hat gesagt.:


> [evtl kompakten] Dimensionen



Hmm, da muss ich nachfragen  Mit "kompakt" ist hier der topologische Begriff der Kompaktheit gemeint? Ich glaub ich versuch besser gar nicht mir vorzustellen, wie eine Dimension aussieht, die diesen Ansprüchen genügt ???:L


----------



## 0x7F800000 (15. Mrz 2009)

ehrlich gesagt: ich weiß es nicht. Das ist alles ziemlich abgefahrener Kram, schließlich haben sich das die hardcorigsten hardcoretheoretiker ausgedacht 

Da hin und wieder auch begriff "large dimensions" fällt, würde ich fast dazu tendieren, das eher mit dem umgangssprachlichen "klein" zu identifizieren.

Wenn man sich die exakte definition von "kompakt" nimmt, kann man sich da natürlich sehr merkwürdige sachen drunter vorstellen, dieser begriff ist schließlich ziemlich allgemein und trifft auf viele gebilde zu...

Aber man muss sich da ja nicht viel kompliziertes ausdenken:
In unserem raum gibts vorne/hinten, oben/unten, links/rechts, vorher/nachher.
Das mit "vorher" ist schwierig, weil es da irgendeine grenze nach unten gibt (big bang heißt die oder so^^)
Man denke also nur an den 3D-Raum der uns umgibt, und einfachheitshalber stelle man sich das alles in form einer 1-D gerade vor, und sage zu allen positionen in 3D nur noch "links/rechts".
Das würde etwa so aussehen:
-Inf ___________________________________________________________ +Inf
in beide richtungen unbeschränkt.

Einfachste kompakte extradimension wäre einfach eine dimension mit endlich vielen Zuständen, dann gäbe es zB. 2 1D-Linien:
__________________________________________________


__________________________________________________
Dann könnte man alle "paralleluniversen" ganz einfach aufzählen, sagen: teilchen ist jetzt im universum 1 oder universum 2

Man könnte sich die extra-dimension als irgendein Intervall, zB. [0,1] vorstellen, sodass man auch alle zustände dazwischen annehmen kann. Das ganze Universum wäre dann sowas wie eine unendlicher Papierstreifen der breite 1.

Um sich keine sorgen darum zu machen, ob das [0,1] oder [0,1) ist, und wie es da am rand des Streifens aussieht, könnte man sich das noch angenehmer vorstellen, und die beiden ränder des papierstreifens einfach zusammenkleben. Dann hätte man sowas wie ein Rohr. Dann könnte man nicht nur entlang unserer drei bekannten dimensionen nach "links/rechts" laufen, sondern auch noch seitlich in die extra-dimension rein, dann würde man aus unserer welt in richtung "extra-oben" loslaufen, einmal im kreis um das rohr laufen, und wieder in unserer welt aus der richtung "extra-unten" ankommen. 

...Kann ja sein, kA. Vielleicht schwingen alle Teilchen um uns herum ein kleines bisschen zwischen diesem "extra-oben" und "extra-unten" hin und her, nur wir merken's nicht, weil sie bei diesem vorgang genauso schmecken und ihre farbe nicht ändern und überhaupt nichts auffälliges anstellen^^

Also, wie gesagt, man kann sich da schnell ein paar leichte beispiele ausdenken, muss ja nichts kompliziertes sein...


----------



## Spacerat (15. Mrz 2009)

Andrey hat gesagt.:


> Ich habe es vorhin schon gesagt, und sage es jetzt auch: es ist alles pures 2D. Alle Objekte sind rein 2D. Alle Koordinaten werden rein 2D abgespeichert. Es gibt halt noch zusätzlich ein paar extra variablen wie zeit/geschwindigkeit und tiefe, aber diese werden wohl separat von anderen Koordinaten abgespeichert. Hier werden jedenfalls keine der 3D-Typischen transformationen mit diesen 4x4-Matrizen ausgeführt, die Grafikkarten so gerne zum frühstück essen. Einfach nur eine sehr hübsche Illusion.


Hoch interessant... aber ich fürchte völlig falsch. Hab' an anderer Stelle schon mal das JDK-Demo "WireFrame" erwähnt. Dort werden vom Objekt definitiv die 3D-Koordinaten gespeichert. Die Umrechnung nach 2D geschieht jedesmal während der Ausführung von "paint()". Ich kann mir auch kaum vorstellen, das man ohne gespeicherte 3. Dimension die spezifische Tiefe eines Objektes darstellen kann, geschweige denn 3D-Objekte scheinbar im Raum bewegen kann. Ok, "WireFrame" verwendet nur eine 3x3-Matrix, weswegen das dargestellte Objekt auch nur rotiert und nicht bewegt werden kann (fehlender Translations-Anteil in der Matrix).


----------



## slawaweis (15. Mrz 2009)

Marco13 hat gesagt.:


> Auch ein 3D-Film ist nur 2D. Das linke und rechte Auge bekommen verschiedene Bilder, so dass man "denkt", es wäre 3D, aber das ist es nicht. Es sind nur 2 unterschiedliche 2D-Bilder. Also, in dem Moment wo man die 2D-Koordinaten so anpasst, dass es nach 3D aussieht, ist es genauso 3D wie der neueste, aufwändigste 3D-Animations-Blockbuster... ("genauso" hat hier eine Bedeutung, die man nicht überinterpretieren sollte...)


es gibt aber noch die Perspektive, die schon vor Jahrhunderten die Maler räumliche Bilder zeichnen ließt. Man kann sich jetzt darüber streiten, aber meiner Meinung nach ist es immer noch 2D. Sogar in der theoretischen Geometrie ist die Perspektive eine eigene Kategorie, neben dem Raum. Was den 3D-Animationfilm angeht, da meinte ich nicht die Technik, sondern wie es die meisten Menschen, ohne Hintergrundwissen, interpretieren. Stereoskopie ist wieder eine andere Kategorie, richtig gesehen ist es 2x2D, aber für die meisten Menschen ist dabei wieder kein Unterschied.



hdi hat gesagt.:


> edit: Ok sry es ist möglich. Theoretisch. Aber doch nicht in der Praxis, was soll
> das für ein Algorithmus sein der hunderte 2d-punkte bei einer Bewegung anpassen soll?
> Das kann man doch nich ausrechnen, wie sich das verschiebt, wenn man intern
> nicht diese Tiefen-Info hat..


Tiefeninformation habe ich schon, von 0.0 bis 1.0. Der Ausgangs- (0.0) und Endpunkt (1.0) ist aber immer noch (x, y).

Slawa


----------



## death90 (18. Mrz 2009)

*Hallo,*

Halleluja ! Was für umfangreiche Ausschweifungen ^^

Nochmal zum eigentlichen Thema, dem Spiel! So langsam dreht mein Info-Lehrer
am Rad, der will das Spiel in einer Woche fertig haben, was ich ohne eure Hilfe wahrscheinlich nicht packen würde,...
Hab mich jetzt etwas mit Java2D beschäftigt.

*@slawaweis:*
Hi ich könnte deinen Quellcode ziemlich gut gebrauchen !
wäre wirklich net, wenn du ihn posten könntest.
Danke!

Ansonsten könnte mir vll. einer Verraten, wie ich diese Trennscheiben erstelle ?
Habe schonmal Ansätze mit dem polygon-Objekt probiert und versucht es mit einem gezeichneten Kreis zu verbinden, hat aber leider nicht so funktioniert wie es sollte ^^

Also ich freu mich wie immer auf Anregungen

Danke schonmal im vorraus !

MFG
Benni


----------



## slawaweis (18. Mrz 2009)

death90 hat gesagt.:


> *@slawaweis:*
> Hi ich könnte deinen Quellcode ziemlich gut gebrauchen !
> wäre wirklich net, wenn du ihn posten könntest.
> Danke!


OK, da ist es. Es sind zwei Klassen, wobei die zweite sehr viele Sachen enthält und man diese ruhig auf andere Dateien verteilen kann. Die beiden Dateien müssen im Package "rocketgame" abgelegt werden. Der Quelltext ist teilweise dokumentiert. Falls Du was nicht verstehst, schneide den Teil raus und poste den hier. *Ich übernehme keine Haftung für eventuelle Schäden die damit entstehen können! Es ist ein ungetestetes Programm, ein "Dirty Proof of Concept".* Es läuft aber, jedenfalls bei mir.

Die Hilfsgrafiken sind aktiviert, dass sind die bunten Linien und Kreise. Rot steht für den Sichtpunkt der Rakete oder des Spielers, das ist der eigentliche Kollisionspunkt mit einer Barriere. Blau steht für die zentrale Linie des Tunnels. Grün ist der Vorderkreis, also die vordere Wand des Tunnels, die sollte man im fertigen Spiel nicht sehen.

Bis jetzt fliegt nur eine Barriere durch den Tunnel. Mehrere Barrieren, die Kollisionsberechnung und Spielabbruch, die Textur der Barrieren und das gesamte Interface fehlen. Die meisten Probleme bereiteten mir die Geschwindigkeiten, da muss man noch viel experimentieren.

[highlight="java"]

package rocketgame;

import java.awt.event.*;

import javax.swing.*;

public class RocketGameStart
{
 public static void main(String [] args)
  {
  JFrame frame = new JFrame("Rocket Game");
  frame.setSize(800, 800);
//  frame.setResizable(false);
  frame.setLocationRelativeTo(null);

//  final TunnelPanel tp = new TunnelPanel(400);
  final TunnelPanel tp = new TunnelPanel(1100);
  tp.setHelpGraphicsEnabled(true);
  frame.getContentPane().add(tp);

  frame.addWindowListener(new WindowAdapter() {
   @Override
   public void windowClosing(WindowEvent e)
    {
    tp.stopAnimation();
    }
  });

  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);

  SwingUtilities.invokeLater(new Runnable() {
   @Override
   public void run()
    {
    tp.startAnimation();
    }
  });
  }

}
[/highlight]

[highlight="java"]

package rocketgame;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;

import javax.swing.*;

public class TunnelPanel extends JPanel
{
 protected float tunnel_radius = 0;
 protected float tunnel_diameter = 0;

 /** diese Variable speichert den Center des vorderen Kreises (den grünen).
     Diese Variable wird nach der Mausbewegung angepasst. */
 protected Point2D.Float tunnel_front_center = new Point2D.Float(0f, 0f);

 /** der graue Kreis */
 protected MovementCircle movement_circle = null;

 /** Eine Liste mit allen verfügbaren Barrieren */
 protected ArrayList<AbstractBarrier> barrier_list = null;
 /** die aktuell angezeigte Barriere */
 protected AbstractBarrier current_barrier = null;

 /** die Positionen der Seitenlinien auf dem Vorderkreis (den grünen) */
 protected float [] tinnel_side_positions = {
     360f*(1.0f/6.0f),
     360f*(2.0f/6.0f),
     360f*(3.0f/6.0f),
     360f*(4.0f/6.0f),
     360f*(5.0f/6.0f),
     360f*(6.0f/6.0f)
   };

 protected Thread thread = null;
 protected TunnelRunner tunnel_runner = null;

 protected boolean help_graphics_enabled = false;

 public TunnelPanel(float tunnel_radius)
  {
  super(null);

  this.tunnel_radius = tunnel_radius;
  this.tunnel_diameter = tunnel_radius*2;

  this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
  this.addMouseMotionListener(new MouseController());

  movement_circle = new MovementCircle();

  barrier_list = new ArrayList<AbstractBarrier>();
  barrier_list.add(new BigHoleBarrier());
  barrier_list.add(new RectangleHoleBarrier());

  // hier wird eine Barriere als aktive (die sichtbar ist) ausgewählt
  current_barrier = barrier_list.get(0);
  }

 public boolean isHelpGraphicsEnabled()
  {
  return help_graphics_enabled;
  }

 public void setHelpGraphicsEnabled(boolean enabled)
  {
  this.help_graphics_enabled = enabled;
  }

////////////////////////////////////////////////////////////////////////
// Paint

 @Override
 public void paintComponent(Graphics g)
  {
  super.paintComponent(g);

  Dimension size = getSize();
  Graphics2D g2 = (Graphics2D)g;

  g2.setBackground(Color.white);
  g2.clearRect(0, 0, size.width, size.height);
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  g2.translate(size.width/2, size.height/2);

  paintTunnelSideLines(g2, Color.black);
  paintBarrier(g2, movement_circle);
  paintBarrier(g2, current_barrier);

  if(help_graphics_enabled)
    paintHelpGraphics(g2);
  }

// die nächsten zwei Funktionen zeichnen die Seitenlinien

 protected void paintTunnelSideLines(Graphics2D g2, Color color)
  {
  g2.setColor(Color.black);
  paintTunnelSideLine(g2, 0);
  paintTunnelSideLine(g2, 1);
  paintTunnelSideLine(g2, 2);
  paintTunnelSideLine(g2, 3);
  paintTunnelSideLine(g2, 4);
  paintTunnelSideLine(g2, 5);
  }

 protected void paintTunnelSideLine(Graphics2D g2,
                                   int side_line_index)
  {
  Point2D.Float poc = getPointOnCircle(tunnel_front_center,
                                       tunnel_radius,
                                       tinnel_side_positions[side_line_index]);

  Line2D.Float base_line = new Line2D.Float(0f, 0f, poc.x, poc.y);

  Point2D.Float tp1 = getPointOnLine(base_line, 0.02f);
  Point2D.Float tp2 = getPointOnLine(base_line, 0.02f);

  Path2D.Float path = new Path2D.Float();
  path.moveTo(tp1.x, tp1.y);
  path.lineTo(poc.x+tp2.y, poc.y-tp2.x);
  path.lineTo(poc.x-tp2.y, poc.y+tp2.x);
  path.closePath();

  g2.fill(path);
  }

// die nächste Funktion zeichnet eine Barriere

 protected void paintBarrier(Graphics2D g2, AbstractBarrier barrier)
  {
  barrier.updateBarrierShapes();

  if(barrier instanceof MovementCircle)
    {
    g2.setColor(Color.gray);
    g2.draw(barrier.front);
    }
  else
    {
    g2.setColor(new Color(235, 235, 235));
    g2.fill(barrier.back);
    g2.setColor(Color.black);
    g2.draw(barrier.back);

    g2.setColor(Color.white);
    g2.fill(barrier.front);
    g2.setColor(Color.black);
    g2.draw(barrier.front);
    }
  }

// die nächste Funktion zeichnet die Hilfsgrafiken

 protected void paintHelpGraphics(Graphics2D g2)
  {
  g2.setColor(Color.green);
  g2.drawOval((int)(-tunnel_radius+tunnel_front_center.x),
              (int)(-tunnel_radius+tunnel_front_center.y),
              (int)tunnel_diameter,
              (int)tunnel_diameter);

  g2.setColor(Color.blue);
  g2.drawLine(0, 0, (int)tunnel_front_center.x,
                    (int)tunnel_front_center.y);

  g2.setColor(Color.red);
  g2.drawLine(-10, 0, 10, 0);
  g2.drawLine(0, -10, 0, 10);
  }

// Paint END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Animation & Interactivity

 public synchronized void startAnimation()
  {
  if(thread == null)
    {
    tunnel_runner = new TunnelRunner();
    thread = new Thread(tunnel_runner);
    thread.start();
    }
  }

 public synchronized void stopAnimation()
  {
  if(thread != null)
    {
    tunnel_runner.loop = false;
    thread = null;
    }
  }

 protected class TunnelRunner implements Runnable
 {
  protected boolean loop = true;

  @Override
  public void run()
   {
   // In dieser Schleife werden die Positionen und die Geschwindigkeiten
   // der aktiven Elemente (Barriere, Seitenlinien) angepasst
   while(loop)
        {
        // das ist der graue Kreis, der sich asymetrisch zu den Barieren bewegt
        // und so ein Gefühl für Bewegung und Geschwindigkeit gibt
        movement_circle.barrier_pos = (movement_circle.barrier_pos + 0.005f*(0.5f+movement_circle.barrier_pos*3f)) % 1f;

        // hier wird die Position und die Geschwindigkeit eine Barriere angepasst
        current_barrier.barrier_pos = (current_barrier.barrier_pos + 0.005f*(0.5f+current_barrier.barrier_pos*2.0f)) % 1f;

        // die Seitenlinienpositionen auf dem Vorderkreis (den grünen) verschieben,
        // um den Rotationseffekt zu erzeugen
        float side_rotation_speed = 0.4f;
        for(int i = 0; i < tinnel_side_positions.length; i++)
           tinnel_side_positions_ = (tinnel_side_positions + side_rotation_speed) % 360f;

        repaint();

        try { Thread.sleep(10); }
        catch(InterruptedException e) { loop = false; e.printStackTrace(); }
        }
   }
 }

 protected class MouseController extends MouseAdapter
 {
  @Override
  public void mouseMoved(MouseEvent e)
   {
   super.mouseMoved(e);

   Dimension size = getSize();

//   tunnel_center.setLocation(e.getX() - size.width/2, e.getY() - size.height/2);
   tunnel_front_center.setLocation(-(e.getX() - size.width/2), -(e.getY() - size.height/2));

   repaint();
   }
 }

// Animation & Interactivity END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Barriers

 protected abstract class AbstractBarrier
 {
  /** Form, welche die Vorderseite eine Barriere darstellt */
  protected Shape front = null;
  /** Form, welche die Hinterseite eine Barriere darstellt */
  protected Shape back = null;

  /** Position im Tunnel zwischen 0f (Hinten) und 1f (Vorne).
      Kann man auch als Tiefe ansehen */
  protected float barrier_pos = 0f;

  protected abstract void updateBarrierShapes();
 }

 protected class MovementCircle extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   float barrier_radius = barrier_pos*tunnel_radius;

   front = new Ellipse2D.Float(-barrier_radius+pit.x, -barrier_radius+pit.y,
                               barrier_radius*2, barrier_radius*2);
   }
 }

 protected class BigHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_radius = barrier_radius*0.9f;
   float hole_diameter = hole_radius*2;

   Ellipse2D.Float barrier_base = null;
   Ellipse2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_radius = barrier_radius*0.9f;
   hole_diameter = hole_radius*2;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

 protected class RectangleHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_width = barrier_radius*0.7f;
   float hole_height = barrier_radius*0.2f;

   Ellipse2D.Float barrier_base = null;
   Rectangle2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_width = barrier_radius*0.7f;
   hole_height = barrier_radius*0.2f;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

// Barriers END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Geometric Help Functions

 protected static Point2D.Float getPointOnCircle(Point2D.Float center,
                                                 float radius, float angle)
  {
  return getPointOnCircle(center.x, center.y, radius, angle);
  }

 protected static Point2D.Float getPointOnCircle(float x, float y,
                                                 float radius, float angle)
  {
  return new Point2D.Float(x + (float)(radius*Math.cos(Math.toRadians(angle))),
                           y + (float)(radius*Math.sin(Math.toRadians(angle))));
  }

 public static Point2D.Float getPointOnLine(Line2D.Float line,
                                            float t)
  {
  return getPointOnLine(line.x1, line.y1, line.x2, line.y2, t);
  }

 public static Point2D.Float getPointOnLine(float x1, float y1,
                                            float x2, float y2,
                                            float t)
  {
  return new Point2D.Float((x2 - x1)*t + x1,
                           (y2 - y1)*t + y1);
  }

// Geometric Help Functions END
////////////////////////////////////////////////////////////////////////
}
[/highlight]

Slawa_


----------



## death90 (19. Mrz 2009)

Hallo,
ich bin echt zu dämlich !

was meinst du denn damit, dass ich beide Dateien in das package "rocketgame" legen soll ?
doofe Frage ich weiß, doch mit Packages hab ich mich noch nicht wirklich beschäftigt

danke schonmal !
Der Code hat schon sehr geholfen.

MFG

Benni


----------



## Landei (19. Mrz 2009)

Dann wird's Zeit:

Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 3.9 Compilationseinheiten und eigene Pakete schnüren


----------



## death90 (22. Mrz 2009)

@slawaweis:

Hallo,
bräuchte da nochmal deine Hilfe !

ich hab jezz schon ewig rumprobiert und nen paar Errors beseitigt, aber
aus irgendeinem Grund kommt bei der Hauptdatei "RocketGameStart" am Ende ein Error:
*"RocketGameStart.java:77: reached end of file while parsing
 }"*

Ansonsten sollte alles funktionieren,..deshalb frage ich mich was das jetzt zu bedeuten hat ?
und 2. wollte ich mal fragen, wie man die Steigerung der Spielgeschwindigkeit erzielen kann ?

Ich danke euch allen wie immer !
besonders amer slawaweis, danke

MFG
Benni


----------



## slawaweis (22. Mrz 2009)

death90 hat gesagt.:


> ich hab jezz schon ewig rumprobiert und nen paar Errors beseitigt, aber
> aus irgendeinem Grund kommt bei der Hauptdatei "RocketGameStart" am Ende ein Error:
> *"RocketGameStart.java:77: reached end of file while parsing
> }*


wahrscheinlich hast Du irgendwo am Ende eine } Klammer entweder vergessen oder eine zu viel. Weiterhin ging meine Version nur bis Zeile 41.



death90 hat gesagt.:


> Ansonsten sollte alles funktionieren,..deshalb frage ich mich was das jetzt zu bedeuten hat ?


was genau meinst Du?



death90 hat gesagt.:


> und 2. wollte ich mal fragen, wie man die Steigerung der Spielgeschwindigkeit erzielen kann ?


dazu muss man die Werte in der Unterklasse TunnelRunner anpassen. Wie ich schon sagte, da muss man experimentieren. Einmal mit der linearen Verschiebung, einmal mit der Beschleunigung und einmal mit dem Thread.sleep().

Slawa


----------



## death90 (22. Mrz 2009)

Hallo slawaweis,

hab jezz nochmal durchgeguckt und echt germerkt, dass da noch ne Klammer fehlte 

naja und in der TunnelPanel.java gabs auch noch nen paar komische Errors, die ich aber beseitigt bekommen hab ! Nun sind aber 2 Errors in der RocketGameStart.java aufgetaucht, die ich nicht verstehe.

ganz plötzlich meint er:
1. Error - *RocketGameStart.java:25:9: cannot find symbol
symbol  : class TunnelPanel
location: class rocketgame.RocketGameStart
  final TunnelPanel tp = new rocketgame.TunnelPanel(1100);
*
2. Error - *RocketGameStart.java:25:40: cannot find symbol
symbol  : class TunnelPanel
location: package rocketgame
  final TunnelPanel tp = new rocketgame.TunnelPanel(1100);
*

beide Dateien sind über das package "rocketgame" eigentlich implementiert. Und es wird doch richtig auf TunnelPanel zugegriffen oder überseh ich da wieder was ?

Wieso findet er die Klasse nicht ?

MFG
benni


----------



## slawaweis (22. Mrz 2009)

wenn beide Dateien in einem Ordner "rocketgame" liegen, bei beiden am Anfang "package rocketgame;" steht und die Dateinamen gleich dem jeweiligen Klassennamen sind, dann darf dieser Fehlen nicht auftauchen. Aber da ich bereits an der Zeilennummer sehe, dass Du größere Änderungen im Quelltext vorgenommen hast, kann ich nur raten.

Slawa


----------



## death90 (22. Mrz 2009)

Hey Slawaweis,

hab eigentlich nix groß geändert am Quellcode, da ich das Programm noch nich einmal zum laufen gebracht habe 

die größere Anzahl an Zeilen kommt lediglich durch ein paar Leerzeilen zustande, die ich der Übersichtlichkeit wegen eingefügt habe.

Beide dateien liegen im Ordner "rocketgame", das hatte ich ja schon gemacht !
Beide heißen so, wie sie sollen und enthalten am Anfang das package.

*hier mal der Code, wie er bei mir aussieht + Errors:*

*RocketGameStart.java*

[HIGHLIGHT="Java"]package rocketgame;
import java.awt.event.*;
import javax.swing.*;


public class RocketGameStart {

  public static void main(String [] args)
  {

    JFrame frame = new JFrame("Rocket Game");

    frame.setSize(800, 800);

    //  frame.setResizable(false);

    frame.setLocationRelativeTo(null);



    //  final TunnelPanel tp = new TunnelPanel(400);

    final TunnelPanel tp = new TunnelPanel(1100);

    tp.setHelpGraphicsEnabled(true);

    frame.getContentPane().add(tp);



   frame.addWindowListener(new WindowAdapter() {

    @Override

    public void windowClosing(WindowEvent e)

    {

    tp.stopAnimation();

    }

   });



    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);





   SwingUtilities.invokeLater(new Runnable() {

   @Override

   public void run()

    {

    tp.startAnimation();

    }

   });

  }
 }[/HIGHLIGHT]

Errors:
*RocketGameStart.java:23:11: cannot find symbol
symbol  : class TunnelPanel
location: class rocketgame.RocketGameStart
    final TunnelPanel tp = new TunnelPanel(1100);

RocketGameStart.java:23:32: cannot find symbol
symbol  : class TunnelPanel
location: class rocketgame.RocketGameStart
    final TunnelPanel tp = new TunnelPanel(1100);
*
*
TunnelPanel.java*

[HIGHLIGHT="Java"]package rocketgame;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;



public class TunnelPanel extends JPanel

{

 protected float tunnel_radius = 0;

 protected float tunnel_diameter = 0;



 /** diese Variable speichert den Center des vorderen Kreises (den grünen).

     Diese Variable wird nach mit Mausbewegung angepasst. */

protected Point2D.Float tunnel_front_center = new Point2D.Float(0f, 0f);



 /** der graue Kreis */

 protected MovementCircle movement_circle = null;



 /** Eine Liste mit allen verfügbaren Barrieren */

 protected ArrayList<AbstractBarrier> barrier_list = null;

 /** die aktuell angezeigte Barriere */

 protected AbstractBarrier current_barrier = null;



 /** die Positionen der Seitenlinien auf dem Vorderkreis (den grünen) */

 protected float [] tinnel_side_positions = {

     360f*(1.0f/6.0f),

     360f*(2.0f/6.0f),

     360f*(3.0f/6.0f),

     360f*(4.0f/6.0f),

     360f*(5.0f/6.0f),

     360f*(6.0f/6.0f)

   };



 protected Thread thread = null;

 protected TunnelRunner tunnel_runner = null;



 protected boolean help_graphics_enabled = false;



public TunnelPanel(float tunnel_radius)

  {

  super(null);



  this.tunnel_radius = tunnel_radius;

  this.tunnel_diameter = tunnel_radius*2;



  this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));

  this.addMouseMotionListener(new MouseController());



  movement_circle = new MovementCircle();



  barrier_list = new ArrayList<AbstractBarrier>();

  barrier_list.add(new BigHoleBarrier());

  barrier_list.add(new RectangleHoleBarrier());



  // hier wird eine Barriere als aktive (die sichtbar ist) ausgewählt

  current_barrier = barrier_list.get(0);

  }



 public boolean isHelpGraphicsEnabled()

  {

  return help_graphics_enabled;

  }



 public void setHelpGraphicsEnabled(boolean enabled)

  {

  this.help_graphics_enabled = enabled;

  }



////////////////////////////////////////////////////////////////////////

// Paint



 @Override

 public void paintComponent(Graphics g)

  {

 super.paintComponent(g);


  Dimension size = getSize();

  Graphics2D g2 = (Graphics2D)g;



  g2.setBackground(Color.white);

  g2.clearRect(0, 0, size.width, size.height);

  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

  g2.translate(size.width/2, size.height/2);



  paintTunnelSideLines(g2, Color.black);

  paintBarrier(g2, movement_circle);

  paintBarrier(g2, current_barrier);



  if(help_graphics_enabled)

    paintHelpGraphics(g2);

  }



// die nächsten zwei Funktionen zeichnen die Seitenlinien



 protected void paintTunnelSideLines(Graphics2D g2, Color color)

  {

  g2.setColor(Color.black);

  paintTunnelSideLine(g2, 0);

  paintTunnelSideLine(g2, 1);

  paintTunnelSideLine(g2, 2);

  paintTunnelSideLine(g2, 3);

  paintTunnelSideLine(g2, 4);

  paintTunnelSideLine(g2, 5);

  }



 protected void paintTunnelSideLine(Graphics2D g2,

                                   int side_line_index)

  {

  Point2D.Float poc = getPointOnCircle(tunnel_front_center,

                                       tunnel_radius,

                                       tinnel_side_positions[side_line_index]);



  Line2D.Float base_line = new Line2D.Float(0f, 0f, poc.x, poc.y);



  Point2D.Float tp1 = getPointOnLine(base_line, 0.02f);

  Point2D.Float tp2 = getPointOnLine(base_line, 0.02f);



  Path2D.Float path = new Path2D.Float();

  path.moveTo(tp1.x, tp1.y);

  path.lineTo(poc.x+tp2.y, poc.y-tp2.x);

  path.lineTo(poc.x-tp2.y, poc.y+tp2.x);

  path.closePath();



 g2.fill(path);

  }



// die nächste Funktion zeichnet eine Barriere


 protected void paintBarrier(Graphics2D g2, AbstractBarrier barrier)

  {

  barrier.updateBarrierShapes();


 if(barrier instanceof MovementCircle)

    {

    g2.setColor(Color.gray);

    g2.draw(barrier.front);

    }

  else

   {

    g2.setColor(new Color(235, 235, 235));

   g2.fill(barrier.back);

    g2.setColor(Color.black);

    g2.draw(barrier.back);



    g2.setColor(Color.white);

    g2.fill(barrier.front);

    g2.setColor(Color.black);

    g2.draw(barrier.front);

    }

  }



// die nächste Funktion zeichnet die Hilfsgrafiken



 protected void paintHelpGraphics(Graphics2D g2)

  {

  g2.setColor(Color.green);

  g2.drawOval((int)(-tunnel_radius+tunnel_front_center.x),

              (int)(-tunnel_radius+tunnel_front_center.y),

              (int)tunnel_diameter,

              (int)tunnel_diameter);



  g2.setColor(Color.blue);

  g2.drawLine(0, 0, (int)tunnel_front_center.x,

                   (int)tunnel_front_center.y);


  g2.setColor(Color.red);

  g2.drawLine(-10, 0, 10, 0);

  g2.drawLine(0, -10, 0, 10);

  }



// Paint END

////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////

// Animation & Interactivity



 public synchronized void startAnimation()

  {

  if(thread == null)

    {

    tunnel_runner = new TunnelRunner();

    thread = new Thread(tunnel_runner);

    thread.start();

    }

  }



 public synchronized void stopAnimation()

  {

  if(thread != null)

    {

    tunnel_runner.loop = false;

    thread = null;

    }

  }



 protected class TunnelRunner implements Runnable

 {

  protected boolean loop = true;



  @Override

  public void run()

   {

   // In dieser Schleife werden die Positionen und die Geschwindigkeiten

   // der aktiven Elemente (Barriere, Seitenlinien) angepasst

   while(loop)

        {

        // das ist der graue Kreis, der sich asymetrisch zu den Barieren bewegt

        // und so ein Gefühl für Bewegung und Geschwindigkeit gibt

       movement_circle.barrier_pos = (movement_circle.barrier_pos + 0.005f*(0.5f+movement_circle.barrier_pos*3f)) % 1f;



        // hier wird die Position und die Geschwindigkeit eine Barriere angepasst

        current_barrier.barrier_pos = (current_barrier.barrier_pos + 0.005f*(0.5f+current_barrier.barrier_pos*2.0f)) % 1f;



        // die Seitenlinienpositionen auf dem Vorderkreis (den grünen) verschieben,

        // um den Rotationseffekt zu erzeugen

        float side_rotation_speed = 0.4f;

        for(int i = 0; i < tinnel_side_positions.length; i++)

           tinnel_side_positions_ = (tinnel_side_positions + side_rotation_speed) % 360f;



        repaint();



        try { Thread.sleep(10); }

        catch(InterruptedException e) { loop = false; e.printStackTrace(); }

        }

   }

}


protected class MouseController extends MouseAdapter

{

 @Override

 public void mouseMoved(MouseEvent e)

  {

   super.mouseMoved(e);



   Dimension size = getSize();



//   tunnel_center.setLocation(e.getX() - size.width/2, e.getY() - size.height/2);

   tunnel_front_center.setLocation(-(e.getX() - size.width/2), -(e.getY() - size.height/2));



   repaint();

   }

}


// Animation & Interactivity END

///////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////

// Barriers



protected abstract class AbstractBarrier

{

  /** Form, welche die Vorderseite eine Barriere darstellt */

  protected Shape front = null;

 /** Form, welche die Hinterseite eine Barriere darstellt */

  protected Shape back = null;


  /** Position im Tunnel zwischen 0f (Hinten) und 1f (Vorne).

      Kann man auch als Tiefe ansehen */

 protected float barrier_pos = 0f;

  protected abstract void updateBarrierShapes();

 }


 protected class MovementCircle extends AbstractBarrier

 {

  @Override

  protected void updateBarrierShapes()

   {

   // 2D Postion im Tunnel anhand der Tiefe ermitteln

   Point2D.Float pit = getPointOnLine(0, 0,

                                      tunnel_front_center.x,

                                      tunnel_front_center.y,

                                      barrier_pos);



   float barrier_radius = barrier_pos*tunnel_radius;



   front = new Ellipse2D.Float(-barrier_radius+pit.x, -barrier_radius+pit.y,

                               barrier_radius*2, barrier_radius*2);

   }

 }



 protected class BigHoleBarrier extends AbstractBarrier

 {

  @Override

  protected void updateBarrierShapes()

   {

   // 2D Postion im Tunnel anhand der Tiefe ermitteln

   Point2D.Float pit = getPointOnLine(0, 0,

                                      tunnel_front_center.x,

                                      tunnel_front_center.y,

                                      barrier_pos);



   // Vorderform für die Barriere aufbauen



   float barrier_radius = (barrier_pos*tunnel_radius);

   float barrier_diameter = barrier_radius*2;

   float hole_radius = barrier_radius*0.9f;

   float hole_diameter = hole_radius*2;



   Ellipse2D.Float barrier_base = null;

   Ellipse2D.Float barrier_hole = null;

   Area area = null;



   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,

                                      -barrier_radius+pit.y,

                                      barrier_diameter,

                                      barrier_diameter);

   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,

                                     -hole_radius+pit.y,

                                     hole_diameter,

                                     hole_diameter);


  area = new Area(barrier_base);
  area.subtract(new Area(barrier_hole));

  this.front = area;


  // Hinterform für die Barriere aufbauen


  barrier_radius = barrier_radius*0.96f;

  barrier_diameter = barrier_radius*2;

   hole_radius = barrier_radius*0.9f;

  hole_diameter = hole_radius*2;


   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,

                                     -barrier_radius+pit.y,

                                     barrier_diameter,

                                     barrier_diameter);

  barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,

                                     -hole_radius+pit.y,

                                     hole_diameter,

                                     hole_diameter);


  area = new Area(barrier_base);

  area.subtract(new Area(barrier_hole));

  this.back = area;

   }

 }


protected class RectangleHoleBarrier extends AbstractBarrier

{

 @Override

 protected void updateBarrierShapes()

  {

  // 2D Postion im Tunnel anhand der Tiefe ermitteln

   Point2D.Float pit = getPointOnLine(0, 0,

                                     tunnel_front_center.x,

                                     tunnel_front_center.y,

                                     barrier_pos);


  // Vorderform für die Barriere aufbauen


  float barrier_radius = (barrier_pos*tunnel_radius);

  float barrier_diameter = barrier_radius*2;

   float hole_width = barrier_radius*0.7f;

  float hole_height = barrier_radius*0.2f;


  Ellipse2D.Float barrier_base = null;

  Rectangle2D.Float barrier_hole = null;

  Area area = null;


  barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,

                                     -barrier_radius+pit.y,

                                     barrier_diameter,

                                     barrier_diameter);

  barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,

                                       -hole_height+pit.y,

                                       hole_width*2,

                                        hole_height*2);


  area = new Area(barrier_base);

  area.subtract(new Area(barrier_hole));

  this.front = area;


  // Hinterform für die Barriere aufbauen


  barrier_radius = barrier_radius*0.96f;

  barrier_diameter = barrier_radius*2;

  hole_width = barrier_radius*0.7f;

  hole_height = barrier_radius*0.2f;


  barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,

                                      -barrier_radius+pit.y,

                                     barrier_diameter,

                                     barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,

                                       -hole_height+pit.y,

                                        hole_width*2,

                                       hole_height*2);


   area = new Area(barrier_base);

   area.subtract(new Area(barrier_hole));

   this.back = area;

  }

 }



// Barriers END

////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////

// Geometric Help Functions



 protected static Point2D.Float getPointOnCircle(Point2D.Float center,

                                                 float radius, float angle)

  {

  return getPointOnCircle(center.x, center.y, radius, angle);

  }


protected static Point2D.Float getPointOnCircle(float x, float y,

                                                float radius, float angle)

  {

  return new Point2D.Float(x + (float)(radius*Math.cos(Math.toRadians(angle))),

                           y + (float)(radius*Math.sin(Math.toRadians(angle))));

  }



 public static Point2D.Float getPointOnLine(Line2D.Float line,

                                            float t)

  {

  return getPointOnLine(line.x1, line.y1, line.x2, line.y2, t);

  }



 public static Point2D.Float getPointOnLine(float x1, float y1,

                                            float x2, float y2,

                                            float t)

  {

  return new Point2D.Float((x2 - x1)*t + x1,

                           (y2 - y1)*t + y1);

  }



// Geometric Help Functions END

////////////////////////////////////////////////////////////////////////

}[/HIGHLIGHT]

Errors:
*java.lang.NoClassDefFoundError: rocketgame/TunnelPanel

Caused by: java.lang.ClassNotFoundException: rocketgame.TunnelPanel
 at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
 at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
Could not find the main class: rocketgame.TunnelPanel.  Program will exit.
Exception in thread "main" *

hoffe du findest da vll. auf anhieb etwas.

ich bin dir so schon dankbar genug

also nochmal danke ^^

MFG
Benni_


----------



## slawaweis (22. Mrz 2009)

bei mir läuft es. Mit welcher IDE arbeitest Du? Wie startest Du es? kommt der Fehler beim Kompilieren oder beim Ausführen?

Slawa


----------



## Apo (22. Mrz 2009)

Ich kann slawa nur beipflichten, bei mir läuft es auch in Eclipse.

Ich persönlich würde dir auch dringend raten, die meisten Leerzeilen wegzunehmen. Gerade bei größeren Java-Dateien wird es sonst noch unübersichtlicher. Wenn du statt 500 Zeilen Code auf einmal 1000 Zeilen Code hast ... das liest sich noch viel schwieriger.


----------



## death90 (22. Mrz 2009)

Hallo,

der Fehler kommt beim kompilieren,...

ich arbeite mit dem freien JavaEditor 9.x

MFG 
Benni


----------



## slawaweis (22. Mrz 2009)

poste bitte einen Screenshot von dem Programm, so wie Du es verwendest. Besonders die Projektverwaltung (dort wo man die beiden Java-Dateien sehen kann) sollte sichtbar sein.

Slawa


----------



## death90 (22. Mrz 2009)

hallo,

hier mal nen bild !



MFG
Benni


----------



## Apo (22. Mrz 2009)

Bist du dir sicher das beide Java-Dateien im gleichen Ordner liegen?
Slawa meinte die Projektverwaltung. Bei Eclipse sieht die z.B. so aus.
Da sieht man das package was rocketgame heisst und beide javaDateien enthält. Sowas in der Art sollte auch der JavaEditor haben ... diesen Screen bräuchten wir =)


----------



## slawaweis (22. Mrz 2009)

OK, jetzt Punkt für Punkt:

Level 1 -------------------

1. lege Dir einen Ordner "C:\RGP" an (oder anders, falls so einer schon vorhanden ist)
2. Lege darin den Ordner "rocketgame" an, so dass es "C:\RGP\rocketgame" ergibt.
3. Kopieren die beiden Dateien nach "C:\RGP\rocketgame". Am besten Du ziehst sie noch mal aus meinem Post, indem Du den Post zitierst und dann aus dem Forum-Editor die beiden Dateien kopierst.
4. Erstelle mit dem JavaEditor ein Projekt in "C:\RGP"
5. Binde die beiden Dateien und das Package in das Projekt ein.
6. Kompiliere es

Level 2 -------------------

7. Wenn es immer noch nicht funktioniert, dann:
8. gehe auf Eclipse.org home und ziehe Dir "Eclipse IDE for Java Developers (85 MB)" runter:

Eclipse Downloads

9. Entpacke das Zip-File in den Ordner "C:\Eclipse-Ganymede-SR2\"
10. Suche dort eclipse.exe und starte es.
11. Wiederholle Punkt 1 bis 6, nur diesmal mit Eclipse

Slawa


----------



## death90 (22. Mrz 2009)

Hallo,

ok hab das jetzt gemacht, weiß bloß noch nich genau was du mit einbinden der Dateien und des packages in ein neues projekt meinst ???:L

Ich bin zuu doof glaub ich ,...komm mir schon richtig schlecht vor :noe:

meinst du vll. im ordner RPG ne neue, zB. Start.java und da drin denn die beiden Dateien aufrufen oder wie ?

 MFG
Benni


----------



## hdi (22. Mrz 2009)

Lad dir Eclipse runter, installier es, starte es, wähle einen  beliebigen Workspace, gehe auf

File -> New -> Java Project

Links wird das Projekt in einem Browser angezeigt, Rechtsklick darauf -> New -> Package

nenne das Package "rocketgame".

Mach Rechtsklick auf dieses Package -> New -> Java Class für beide Dateien.
Bennene sie so, wie sie im Quellcode heissen.

Kopiere den Code der jeweiligen Dateien in die Klassen, indem du Doppelklick
auf eine Klasse machst und im grossen Hauptfenster den Code reinkopierst.

Wähle das Projekt an (einfach den Namen anklicken) und drücke oben in der Leiste von Eclipse
den grünen Start-Button.


----------



## death90 (22. Mrz 2009)

Ach du scheiße wie geil seid ihr denn !

OMG...es funktioniert, mit eclipse 

Also ich sag mal das Wort "danke" triffts nich mal annähernd. 
Ihr seid die besten, vielen dank, endlich gehts :toll:

jezz kann ich endlich nen bissl rumbasteln und gleich ausprobieren.

Jetzt weiß ich auch was ihr mit einbinden der dateien und des packages meintet 

Naja gut, ich meld mich wieder

MFG
Benni


----------



## death90 (22. Mrz 2009)

Hallo,

ich hätt mal wieder ne Frage !

Wie bekomm ich den Cursor transparent ?, d.h. man soll ganz normal steuern können mit der Maus, aber ohne das man einen Cursor sieht !

geht das irgendwie ?

MFG
Benni


----------



## hdi (22. Mrz 2009)

Soweit ich weiss macht man sowas mit einem transparenten Bild.
D.h. du erstellst dir eine transparente Bild-Datei, lädst das Bild im Programm:

[HIGHLIGHT="Java"]BufferedImage myImg = ImageIO.read(DeineKlasse.class
				.getResourceAsStream("myInvisiblePic.png"));[/HIGHLIGHT]

und erstellst dann damit einen Custom Cursor:

[HIGHLIGHT="Java"]Toolkit.getDefaultToolkit().createCustomCursor(myImg,new Point(0,0),"invisible");[/HIGHLIGHT]


----------



## death90 (25. Mrz 2009)

Hallo,
ich melde mich mal wieder !

Bin mit dem Programm jetzt schonmal voran gekommen 

Ich will jetzt in der TunnelPanel.java eine variable Timedraw einbringen,
die vom beginn der animation an in der linken oberen Ecke des Frames gezeichnet wird.
Sie soll so Aussehen: Speed 100% (und dann steigend auf 300%)!

Die Berechnung der prozentualen Geschwindigkeit hab ich schon gemacht und in einer
Variable: protected float Time; in der While Schleife gespeichert.

Wie und Wo muss ich jetzt die Variablen implementieren !

Über Graphics und dann "drawString" funktioniert das nicht 

Hoffe ihr könnt mir Helfen
(mal wieder ^^)

danke natürlich, wie immer im voraus !

MFG
Benni


----------



## hdi (25. Mrz 2009)

Die Variable sollte Member-Variable deines Threads sein, der die while-Schleife
abläuft und diese Variable ändert.
Dann noch einen schönen getter dafür und schon kannst du diese Info wo auch
immer (TunnPanel nehm ich an) auslesen, und jawohl mit g.drawString geht das sehr wohl.

Falls doch nicht, poste mal Code.


----------



## death90 (25. Mrz 2009)

Hallo,

@hdi:

Habs mal probiert, will aber nicht so richtig !

*Hier mal der Code der System.java (früher TunnelPanel.java):*

[HIGHLIGHT="Java"]package rocketgame;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;

import javax.swing.*;

public class System extends JPanel
{
	private static final long serialVersionUID = 1L;

protected float tunnel_radius = 0;
 protected float tunnel_diameter = 0;

 /** diese Variable speichert den Center des vorderen Kreises (den grünen).
     Diese Variable wird nach der Mausbewegung angepasst. */
 protected Point2D.Float tunnel_front_center = new Point2D.Float(0f, 0f);

 /** der graue Kreis */
 protected MovementCircle movement_circle = null;

 /** Eine Liste mit allen verfügbaren Barrieren */
 protected ArrayList<AbstractBarrier> barrier_list = null;
 /** die aktuell angezeigte Barriere */
 protected AbstractBarrier current_barrier = null;

 /** die Positionen der Seitenlinien auf dem Vorderkreis (den grünen) */
 protected float [] tinnel_side_positions = {
     360f*(1.0f/6.0f),
     360f*(2.0f/6.0f),
     360f*(3.0f/6.0f),
     360f*(4.0f/6.0f),
     360f*(5.0f/6.0f),
     360f*(6.0f/6.0f)
   };

 protected Thread thread = null;
 protected TunnelRunner tunnel_runner = null;

 protected boolean help_graphics_enabled = false;

 public System(float tunnel_radius)
  {
  super(null);

  this.tunnel_radius = tunnel_radius;
  this.tunnel_diameter = tunnel_radius*2;

  this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
  this.addMouseMotionListener(new MouseController());

  movement_circle = new MovementCircle();

  barrier_list = new ArrayList<AbstractBarrier>();
  barrier_list.add(new BigHoleBarrier());
  barrier_list.add(new RectangleHoleBarrier());

  // hier wird eine Barriere als aktive (die sichtbar ist) ausgewählt
  current_barrier = barrier_list.get(0);
  }

 public boolean isHelpGraphicsEnabled()
  {
  return help_graphics_enabled;
  }

 public void setHelpGraphicsEnabled(boolean enabled)
  {
  this.help_graphics_enabled = enabled;
  }

////////////////////////////////////////////////////////////////////////
// Paint
 @Override
 public void paintComponent(Graphics g)
  {
  super.paintComponent(g);

  Dimension size = getSize();
  Graphics2D g2 = (Graphics2D)g;

  g2.setBackground(Color.white);
  g2.clearRect(0, 0, size.width, size.height);
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  g2.translate(size.width/2, size.height/2);

  paintTunnelSideLines(g2, Color.black);
  paintBarrier(g2, movement_circle);
  paintBarrier(g2, current_barrier);

  if(help_graphics_enabled)
    paintHelpGraphics(g2);
  }


 protected void paintSpeed(Graphics g2)
 {
  g2.setColor(Color.black);
  g2.drawString("Speed "+getTimedraw(td), -390, -370);
 }


// die nächsten zwei Funktionen zeichnen die Seitenlinien

 protected void paintTunnelSideLines(Graphics2D g2, Color color)
  {
  g2.setColor(Color.black);
  paintTunnelSideLine(g2, 0);
  paintTunnelSideLine(g2, 1);
  paintTunnelSideLine(g2, 2);
  paintTunnelSideLine(g2, 3);
  paintTunnelSideLine(g2, 4);
  paintTunnelSideLine(g2, 5);
  }

 protected void paintTunnelSideLine(Graphics2D g2,
                                   int side_line_index)
  {
  Point2D.Float poc = getPointOnCircle(tunnel_front_center,
                                       tunnel_radius,
                                       tinnel_side_positions[side_line_index]);

  Line2D.Float base_line = new Line2D.Float(0f, 0f, poc.x, poc.y);

  Point2D.Float tp1 = getPointOnLine(base_line, 0.02f);
  Point2D.Float tp2 = getPointOnLine(base_line, 0.02f);

  Path2D.Float path = new Path2D.Float();
  path.moveTo(tp1.x, tp1.y);
  path.lineTo(poc.x+tp2.y, poc.y-tp2.x);
  path.lineTo(poc.x-tp2.y, poc.y+tp2.x);
  path.closePath();

  g2.fill(path);
  }

// die nächste Funktion zeichnet eine Barriere

 protected void paintBarrier(Graphics2D g2, AbstractBarrier barrier)
  {
  barrier.updateBarrierShapes();

  if(barrier instanceof MovementCircle)
    {
    g2.setColor(Color.gray);
    g2.draw(barrier.front);
    }
  else
    {
    g2.setColor(new Color(235, 235, 235));
    g2.fill(barrier.back);
    g2.setColor(Color.black);
    g2.draw(barrier.back);

    g2.setColor(Color.white);
    g2.fill(barrier.front);
    g2.setColor(Color.black);
    g2.draw(barrier.front);
    }
  }

// die nächste Funktion zeichnet die Hilfsgrafiken

 protected void paintHelpGraphics(Graphics2D g2)
  {
  g2.setColor(Color.green);
  g2.drawOval((int)(-tunnel_radius+tunnel_front_center.x),
              (int)(-tunnel_radius+tunnel_front_center.y),
              (int)tunnel_diameter,
              (int)tunnel_diameter);

  g2.setColor(Color.blue);
  g2.drawLine(0, 0, (int)tunnel_front_center.x,
                    (int)tunnel_front_center.y);

  g2.setColor(Color.red);
  g2.drawLine(-10, 0, 10, 0);
  g2.drawLine(0, -10, 0, 10);
  }


// Paint END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Animation & Interactivity

 public synchronized void startAnimation()
  {
  if(thread == null)
    {
    tunnel_runner = new TunnelRunner();
    thread = new Thread(tunnel_runner);
    thread.start();
    }
  }

 public synchronized void stopAnimation()
  {
  if(thread != null)
    {
    tunnel_runner.loop = false;
    thread = null;
    }
  }

 protected class TunnelRunner implements Runnable
 {
  protected boolean loop = true;
  protected float Time = (float) 0.000;
  protected float Timedraw = 100;
  @Override
  public void run()
   {
   // In dieser Schleife werden die Positionen und die Geschwindigkeiten
   // der aktiven Elemente (Barriere, Seitenlinien) angepasst
   while(loop)
        {
	   if(Time<2)
        Time=(float) (Time+0.001f);
	   if(Timedraw<200)
        Timedraw=Timedraw+(Time*100);

        // das ist der graue Kreis, der sich asymetrisch zu den Barieren bewegt
        // und so ein Gefühl für Bewegung und Geschwindigkeit gibt
        movement_circle.barrier_pos = (movement_circle.barrier_pos+0.0042f*(Time+movement_circle.barrier_pos*3.0f)) % 1f;

        // hier wird die Position und die Geschwindigkeit eine Barriere angepasst
        current_barrier.barrier_pos = (current_barrier.barrier_pos+0.0065f*(Time+current_barrier.barrier_pos*2.0f)) % 1f;

        // die Seitenlinienpositionen auf dem Vorderkreis (den grünen) verschieben,
        // um den Rotationseffekt zu erzeugen
        float side_rotation_speed = 0.5f;
        for(int i = 0; i < tinnel_side_positions.length; i++)
           tinnel_side_positions_ = (tinnel_side_positions + side_rotation_speed) % 360f;

        repaint();

        try { Thread.sleep(15); }
        catch(InterruptedException e) { loop = false; e.printStackTrace(); }
        }
   }

  public void getTimedraw(float td){
	  td=Timedraw;
	  return;
  }

private String toString(float f) {
	// TODO Auto-generated method stub
	return null;
}
 }

 protected class MouseController extends MouseAdapter
 {
  @Override
  public void mouseMoved(MouseEvent e)
   {
   super.mouseMoved(e);

   Dimension size = getSize();

//   tunnel_center.setLocation(e.getX() - size.width/2, e.getY() - size.height/2);
   tunnel_front_center.setLocation(-(e.getX() - size.width/2), -(e.getY() - size.height/2));

   repaint();
   }
 }

// Animation & Interactivity END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Barriers

 protected abstract class AbstractBarrier
 {
  /** Form, welche die Vorderseite eine Barriere darstellt */
  protected Shape front = null;
  /** Form, welche die Hinterseite eine Barriere darstellt */
  protected Shape back = null;

  /** Position im Tunnel zwischen 0f (Hinten) und 1f (Vorne).
      Kann man auch als Tiefe ansehen */
  protected float barrier_pos = 0.5f;

  protected abstract void updateBarrierShapes();
 }

 protected class MovementCircle extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   float barrier_radius = barrier_pos*tunnel_radius;

   front = new Ellipse2D.Float(-barrier_radius+pit.x, -barrier_radius+pit.y,
                               barrier_radius*2, barrier_radius*2);
   }
 }

 protected class BigHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_radius = barrier_radius*0.9f;
   float hole_diameter = hole_radius*2;

   Ellipse2D.Float barrier_base = null;
   Ellipse2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_radius = barrier_radius*0.9f;
   hole_diameter = hole_radius*2;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

 protected class RectangleHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_width = barrier_radius*0.7f;
   float hole_height = barrier_radius*0.2f;

   Ellipse2D.Float barrier_base = null;
   Rectangle2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_width = barrier_radius*0.7f;
   hole_height = barrier_radius*0.2f;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

// Barriers END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Geometric Help Functions

 protected static Point2D.Float getPointOnCircle(Point2D.Float center,
                                                 float radius, float angle)
  {
  return getPointOnCircle(center.x, center.y, radius, angle);
  }

 protected static Point2D.Float getPointOnCircle(float x, float y,
                                                 float radius, float angle)
  {
  return new Point2D.Float(x + (float)(radius*Math.cos(Math.toRadians(angle))),
                           y + (float)(radius*Math.sin(Math.toRadians(angle))));
  }

 public static Point2D.Float getPointOnLine(Line2D.Float line,
                                            float t)
  {
  return getPointOnLine(line.x1, line.y1, line.x2, line.y2, t);
  }

 public static Point2D.Float getPointOnLine(float x1, float y1,
                                            float x2, float y2,
                                            float t)
  {
  return new Point2D.Float((x2 - x1)*t + x1,
                           (y2 - y1)*t + y1);
  }

// Geometric Help Functions END
////////////////////////////////////////////////////////////////////////
}[/HIGHLIGHT]

Hoffe du findest was !

danke schonmal für die Antwort bzw. Hilfe !

MFG
Benni_


----------



## hdi (25. Mrz 2009)

JA die paintSpeed() musst du schon irgendwo aufrufen.
In der paintComponent oder sonstwo, wo du das Graphics-Objekt zur Verfügung hast.


----------



## death90 (25. Mrz 2009)

*Hallo,*

ich habe meine paintSpeed methode in der paintComponent nun aufgerufen,
aber irgendwie haut meine getter methode nicht hin ! 

Er kann irgendwie die variable Timedraw, die ein float ist nicht in dem String
verarbeiten bzw. abrufen !

...habe die methode in die while-schleife integriert, die sich in der Klasse TunnelRunner befindet... hmmm bin nun ein wenig ratlos !???:L

*Hier nun nochmal der etwas veränderte Code:*

[HIGHLIGHT="Java"]package rocketgame;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;

import javax.swing.*;

public class System extends JPanel
{
	private static final long serialVersionUID = 1L;

protected float tunnel_radius = 0;
 protected float tunnel_diameter = 0;

 /** diese Variable speichert den Center des vorderen Kreises (den grünen).
     Diese Variable wird nach der Mausbewegung angepasst. */
 protected Point2D.Float tunnel_front_center = new Point2D.Float(0f, 0f);

 /** der graue Kreis */
 protected MovementCircle movement_circle = null;

 /** Eine Liste mit allen verfügbaren Barrieren */
 protected ArrayList<AbstractBarrier> barrier_list = null;
 /** die aktuell angezeigte Barriere */
 protected AbstractBarrier current_barrier = null;

 /** die Positionen der Seitenlinien auf dem Vorderkreis (den grünen) */
 protected float [] tinnel_side_positions = {
     360f*(1.0f/6.0f),
     360f*(2.0f/6.0f),
     360f*(3.0f/6.0f),
     360f*(4.0f/6.0f),
     360f*(5.0f/6.0f),
     360f*(6.0f/6.0f)
   };

 protected Thread thread = null;
 protected TunnelRunner tunnel_runner = null;

 protected boolean help_graphics_enabled = false;

 public System(float tunnel_radius)
  {
  super(null);

  this.tunnel_radius = tunnel_radius;
  this.tunnel_diameter = tunnel_radius*2;

  this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
  this.addMouseMotionListener(new MouseController());

  movement_circle = new MovementCircle();

  barrier_list = new ArrayList<AbstractBarrier>();
  barrier_list.add(new BigHoleBarrier());
  barrier_list.add(new RectangleHoleBarrier());

  // hier wird eine Barriere als aktive (die sichtbar ist) ausgewählt
  current_barrier = barrier_list.get(0);
  }

 public boolean isHelpGraphicsEnabled()
  {
  return help_graphics_enabled;
  }

 public void setHelpGraphicsEnabled(boolean enabled)
  {
  this.help_graphics_enabled = enabled;
  }

////////////////////////////////////////////////////////////////////////
// Paint
 public void paintComponent(Graphics g)
  {
  super.paintComponent(g);

  Dimension size = getSize();
  Graphics2D g2 = (Graphics2D)g;

  g2.setBackground(Color.white);
  g2.clearRect(0, 0, size.width, size.height);
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  g2.translate(size.width/2, size.height/2);

  paintTunnelSideLines(g2, Color.black);
  paintBarrier(g2, movement_circle);
  paintBarrier(g2, current_barrier);
  paintSpeed(g2);

  if(help_graphics_enabled)
    paintHelpGraphics(g2);
  }


 protected void paintSpeed(Graphics g2)
 {
  g2.setColor(Color.black);
  g2.drawString("Speed ", -390, -370);
 }


// die nächsten zwei Funktionen zeichnen die Seitenlinien

 protected void paintTunnelSideLines(Graphics2D g2, Color color)
  {
  g2.setColor(Color.black);
  paintTunnelSideLine(g2, 0);
  paintTunnelSideLine(g2, 1);
  paintTunnelSideLine(g2, 2);
  paintTunnelSideLine(g2, 3);
  paintTunnelSideLine(g2, 4);
  paintTunnelSideLine(g2, 5);
  }

 protected void paintTunnelSideLine(Graphics2D g2,
                                   int side_line_index)
  {
  Point2D.Float poc = getPointOnCircle(tunnel_front_center,
                                       tunnel_radius,
                                       tinnel_side_positions[side_line_index]);

  Line2D.Float base_line = new Line2D.Float(0f, 0f, poc.x, poc.y);

  Point2D.Float tp1 = getPointOnLine(base_line, 0.02f);
  Point2D.Float tp2 = getPointOnLine(base_line, 0.02f);

  Path2D.Float path = new Path2D.Float();
  path.moveTo(tp1.x, tp1.y);
  path.lineTo(poc.x+tp2.y, poc.y-tp2.x);
  path.lineTo(poc.x-tp2.y, poc.y+tp2.x);
  path.closePath();

  g2.fill(path);
  }

// die nächste Funktion zeichnet eine Barriere

 protected void paintBarrier(Graphics2D g2, AbstractBarrier barrier)
  {
  barrier.updateBarrierShapes();

  if(barrier instanceof MovementCircle)
    {
    g2.setColor(Color.gray);
    g2.draw(barrier.front);
    }
  else
    {
    g2.setColor(new Color(235, 235, 235));
    g2.fill(barrier.back);
    g2.setColor(Color.black);
    g2.draw(barrier.back);

    g2.setColor(Color.white);
    g2.fill(barrier.front);
    g2.setColor(Color.black);
    g2.draw(barrier.front);
    }
  }

// die nächste Funktion zeichnet die Hilfsgrafiken

 protected void paintHelpGraphics(Graphics2D g2)
  {
  g2.setColor(Color.green);
  g2.drawOval((int)(-tunnel_radius+tunnel_front_center.x),
              (int)(-tunnel_radius+tunnel_front_center.y),
              (int)tunnel_diameter,
              (int)tunnel_diameter);

  g2.setColor(Color.blue);
  g2.drawLine(0, 0, (int)tunnel_front_center.x,
                    (int)tunnel_front_center.y);

  g2.setColor(Color.red);
  g2.drawLine(-10, 0, 10, 0);
  g2.drawLine(0, -10, 0, 10);
  }


// Paint END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Animation & Interactivity

 public synchronized void startAnimation()
  {
  if(thread == null)
    {
    tunnel_runner = new TunnelRunner();
    thread = new Thread(tunnel_runner);
    thread.start();
    }
  }

 public synchronized void stopAnimation()
  {
  if(thread != null)
    {
    tunnel_runner.loop = false;
    thread = null;
    }
  }

 protected class TunnelRunner implements Runnable
 {
  protected boolean loop = true;
  protected float Time = (float) 0.000;
  protected float Timedraw = 100;
  @Override
  public void run()
   {
   // In dieser Schleife werden die Positionen und die Geschwindigkeiten
   // der aktiven Elemente (Barriere, Seitenlinien) angepasst
   while(loop)
        {
	   if(Time<2)
        Time=(float) (Time+0.001f);
	   if(Timedraw<200)
        Timedraw=Timedraw+(Time*100);

        // das ist der graue Kreis, der sich asymetrisch zu den Barieren bewegt
        // und so ein Gefühl für Bewegung und Geschwindigkeit gibt
        movement_circle.barrier_pos = (movement_circle.barrier_pos+0.0042f*(Time+movement_circle.barrier_pos*3.0f)) % 1f;

        // hier wird die Position und die Geschwindigkeit eine Barriere angepasst
        current_barrier.barrier_pos = (current_barrier.barrier_pos+0.0065f*(Time+current_barrier.barrier_pos*2.0f)) % 1f;

        // die Seitenlinienpositionen auf dem Vorderkreis (den grünen) verschieben,
        // um den Rotationseffekt zu erzeugen
        float side_rotation_speed = 0.5f;
        for(int i = 0; i < tinnel_side_positions.length; i++)
           tinnel_side_positions_ = (tinnel_side_positions + side_rotation_speed) % 360f;

        repaint();

        try { Thread.sleep(15); }
        catch(InterruptedException e) { loop = false; e.printStackTrace(); }
        }
   }

  public float getTimedraw(float td){
	 td=Timedraw;
	  return td;
  }

 }

 protected class MouseController extends MouseAdapter
 {
  @Override
  public void mouseMoved(MouseEvent e)
   {
   super.mouseMoved(e);

   Dimension size = getSize();

//   tunnel_center.setLocation(e.getX() - size.width/2, e.getY() - size.height/2);
   tunnel_front_center.setLocation(-(e.getX() - size.width/2), -(e.getY() - size.height/2));

   repaint();
   }
 }

// Animation & Interactivity END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Barriers

 protected abstract class AbstractBarrier
 {
  /** Form, welche die Vorderseite eine Barriere darstellt */
  protected Shape front = null;
  /** Form, welche die Hinterseite eine Barriere darstellt */
  protected Shape back = null;

  /** Position im Tunnel zwischen 0f (Hinten) und 1f (Vorne).
      Kann man auch als Tiefe ansehen */
  protected float barrier_pos = 0.5f;

  protected abstract void updateBarrierShapes();
 }

 protected class MovementCircle extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   float barrier_radius = barrier_pos*tunnel_radius;

   front = new Ellipse2D.Float(-barrier_radius+pit.x, -barrier_radius+pit.y,
                               barrier_radius*2, barrier_radius*2);
   }
 }

 protected class BigHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_radius = barrier_radius*0.9f;
   float hole_diameter = hole_radius*2;

   Ellipse2D.Float barrier_base = null;
   Ellipse2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_radius = barrier_radius*0.9f;
   hole_diameter = hole_radius*2;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

 protected class RectangleHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_width = barrier_radius*0.7f;
   float hole_height = barrier_radius*0.2f;

   Ellipse2D.Float barrier_base = null;
   Rectangle2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_width = barrier_radius*0.7f;
   hole_height = barrier_radius*0.2f;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

// Barriers END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Geometric Help Functions

 protected static Point2D.Float getPointOnCircle(Point2D.Float center,
                                                 float radius, float angle)
  {
  return getPointOnCircle(center.x, center.y, radius, angle);
  }

 protected static Point2D.Float getPointOnCircle(float x, float y,
                                                 float radius, float angle)
  {
  return new Point2D.Float(x + (float)(radius*Math.cos(Math.toRadians(angle))),
                           y + (float)(radius*Math.sin(Math.toRadians(angle))));
  }

 public static Point2D.Float getPointOnLine(Line2D.Float line,
                                            float t)
  {
  return getPointOnLine(line.x1, line.y1, line.x2, line.y2, t);
  }

 public static Point2D.Float getPointOnLine(float x1, float y1,
                                            float x2, float y2,
                                            float t)
  {
  return new Point2D.Float((x2 - x1)*t + x1,
                           (y2 - y1)*t + y1);
  }

// Geometric Help Functions END
////////////////////////////////////////////////////////////////////////
}[/HIGHLIGHT]

So hoffe du kannst mir das nochmal erklären bzw. sagen, wo ichs lieber einfügen sollte !

Naja danke schonmal...

MFG
Benni_


----------



## slawaweis (25. Mrz 2009)

@death90
erstens, es ist eine ziemlich dumme Idee eine Klasse "System" und eine Variable "Time" zu nennen. Diese Namen werden schon im Kern-API für ziemlich prominente Klassen verwenden. Wie willst Du jetzt System.out.println() schreiben? Variablennamen solle man außerdem klein schreiben, also "time" und "timedraw".

Die Variablen "Time" "Timedraw" können auch in der Hauptklasse definiert werden und nicht erst im TunnelRunner. Bei mehreren Threads ist nur wichtig zu beachten, welcher Thread welche Variable nur liest und welcher diese liest und schreibt. Falls Du die Variablen doch im TunnelRunner haben willst, musst Du über die Variable tunnel_runner darauf zugreifen, aber am Prinzip ändert es nichts.

Das Du paintSpeed erstellt hast, ist schon ein guter Weg, es sollte aber schon ein Graphics2D als Parameter bekommen. Weiterhin ist es nicht nötig, den Speed mit Minuskoordinaten auf den Bildschirm zu malen. Dazu sollte man sich ein zusätzliches Graphics2D Objekt machen:

[HIGHLIGHT="Java"]
 public void paintComponent(Graphics g)
  {
  super.paintComponent(g);

  Dimension size = getSize();
  Graphics2D g2 = (Graphics2D)g;

  // zwei Graphics2D Objekte für verschiedene Arten der Darstellung

  // ein Graphics2D für das Interface, beginnt oben links
  Graphics2D g2_interface = (Graphics2D)g2.create();
  // ein Graphics2D für den Tunnel, beginnt in der mitte des Bildschirms
  Graphics2D g2_tunnel = (Graphics2D)g2.create();

  g2_tunnel.setBackground(Color.white);
  g2_tunnel.clearRect(0, 0, size.width, size.height);
  g2_tunnel.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  g2_tunnel.translate(size.width/2, size.height/2);

  g2_interface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

  paintTunnelSideLines(g2_tunnel, Color.black);
  paintBarrier(g2_tunnel, movement_circle);
  paintBarrier(g2_tunnel, current_barrier);

  if(help_graphics_enabled)
    paintHelpGraphics(g2_tunnel);

  paintSpeed(g2_interface);
  }


 protected void paintSpeed(Graphics2D g2)
 {
  g2.setColor(Color.black);
  g2.drawString("Speed ", 20, 20);
 }
[/HIGHLIGHT]

Slawa


----------



## hdi (26. Mrz 2009)

ein Getter ist per Definition parameterlos und führt keine Seiteneffekt aus.
D.h. das muss so aussehen:

[HIGHLIGHT="Java"]public float getTimedraw(){
     return this.Timedraw // Variablen schreibt man übrigens klein
}[/HIGHLIGHT]

und:

[HIGHLIGHT="Java"]paintSpeed(Graphics g){
     g.drawString("Speed: " + deinTunnelObjekt.getTimedraw() + " %",5,5);
}[/HIGHLIGHT]


----------



## death90 (29. Mrz 2009)

*Hallo,*

ich meld mich mal wieder !

habe es mittlerweile hinbekommen, dass Zeit und Geschwindigkeit angezeigt werden !

Nun gibt es noch 3 Dinge die ich machen muss:
*1.* ca. 3 versch. Barrieren erstellen, die sich eventuell mit drehen (nur wie ? polygon-objekt ?)
*2.* Kollisionsabfrage (stopAnimation, wenn kollision =true,. oder so, bloß wie soll die aussehen ? )
*3.* das zeichnen von 2 Barrieren während des Gameloops in einem bestimmten abstand, so dass nicht immer erst eine neue erscheint, wenn die erste schon vorbei ist !

ich stell mir vor das das erstellen dieser Barrieren das schwerste ist oder ?

Naja ich hoffe auf tatkräftige unterstützung, da morgen schon eine erste Generalprobe des Spiels erfolgt 

vielen Dank schonmal im Vorraus !

MFG
Benni


----------



## g0d3x (29. Mrz 2009)

Hey hab auch solche Probleme


----------



## death90 (29. Mrz 2009)

Hallo,

niemand da der mir helfen kann ??

;(

MFG
Benni


----------



## hdi (29. Mrz 2009)

Dass das Einbauen von Hindernissen grad erst die Schwierigkeit an dem Game ist,
war doch von Anfang an klar.
Damit hättest du auch anfangen sollen, bevor du den Schnickschnack drumrum machst.

...wie sieht denn deine Röhre im Moment aus? Java3D, oder per Mapping?
Oder sogar komplett 2d gespeichert?
Kann man sich darin schon bewegen?


----------



## death90 (29. Mrz 2009)

Hallo,

hab mal ne Jar-Datei im Anhang !
Die Bilddatei dazu muss in einen Ordner "images" !

So nunja, also wie ich weitere Barrieren erstelle wei0 ich schon, ich brauch nun noch
einen Zufallsgenerator, der per Zufall in der Game-Schleife die current_barrier ermittelt !

und denn brauche ich noch eine Kollisionsabfrage ! und evtl. noch eine Möglichkeit, dass diese Barrieren rotieren.

naja aber wie schon gesagt, das ist erstmal noch Schnickschnack !

PS: 2 Barrieren habe ich ja schon !

Hier nochmal der aktuelle Code zum Verständnis:

*FallOfBall.java*

[HIGHLIGHT="Java"]import java.awt.*;
import java.awt.event.*;
import javax.swing.*;



public class FallOfBall extends JPanel
{	
private static final long serialVersionUID = 1L;

public static boolean run = false;

 public static void main(String [] args)
  {
	 new FallOfBall(800,800);
  }
  public FallOfBall(int w, int h){
      this.setPreferredSize(new Dimension(800,800));
      this.setBackground(Color.white);

      JLabel label = new JLabel(new ImageIcon("images/logo.jpg"));
      label.setSize(new Dimension(800,222));
      label.add(this);
      label.setLocation(0,0);

      JLabel caption = new JLabel("Copyright © 2009 by H@ckz0r");
      caption.setSize(new Dimension(800,50));
      caption.setFont(new Font("Tw Cen MT",Font.PLAIN,18));
      caption.add(this);
      caption.setLocation(280, 700);


      JButton but = new JButton();
      but.setSize(new Dimension(794,40));
      but.setBackground(Color.white);
      but.setBorderPainted(true);
      but.setRolloverEnabled(true);
      but.setText("                                     Start                                       ");
      but.setFont(new Font("Tw Cen MT",Font.ITALIC,34));
      but.setForeground(Color.black);
      but.setLocation(0,400);

      JFrame frame = new JFrame("Fall Of Ball - Pre-Alpha 0.12"); 
      frame.setLocation(100,100);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(caption);
      frame.add(but);
      frame.add(label);
      frame.add(this);
      frame.setSize(new Dimension(800, 800));
      frame.setResizable(false);
      frame.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
      frame.setVisible(true);

  while(run==false){
	  but.addActionListener(
		      new ActionListener() {
		      public void actionPerformed(ActionEvent e){
		       run = true;
	 }
	}
   );
  }


  if(run==true) {

  frame.remove(but);
  frame.remove(label);
  frame.remove(this);
  frame.remove(caption);

  final Function func = new Function(1100);
  func.setHelpGraphicsEnabled(false);
  frame.add(func);

  frame.addWindowListener(new WindowAdapter() {
   @Override
   public void windowClosing(WindowEvent e)
    {
    func.stopAnimation();
    }
   });


  frame.setVisible(true);


  SwingUtilities.invokeLater(new Runnable() {
   @Override
   public void run()
    {
    func.startAnimation();
    }
   });

   }
  }

}[/HIGHLIGHT]

*und hier die Function.java*

[HIGHLIGHT="Java"]package rocketgame;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;

import javax.swing.*;

public class Function extends JPanel
{
	private static final long serialVersionUID = 1L;

protected float tunnel_radius = 0;
 protected float tunnel_diameter = 0;

 /** diese Variable speichert den Center des vorderen Kreises (den grünen).
     Diese Variable wird nach der Mausbewegung angepasst. */
 protected Point2D.Float tunnel_front_center = new Point2D.Float(0f, 0f);

 /** der graue Kreis */
 protected MovementCircle movement_circle = null;

 /** Eine Liste mit allen verfügbaren Barrieren */
 protected ArrayList<AbstractBarrier> barrier_list = null;
 /** die aktuell angezeigte Barriere */
 protected AbstractBarrier current_barrier = null;

 /** die Positionen der Seitenlinien auf dem Vorderkreis (den grünen) */
 protected float [] tinnel_side_positions = {
     360f*(1.0f/6.0f),
     360f*(2.0f/6.0f),
     360f*(3.0f/6.0f),
     360f*(4.0f/6.0f),
     360f*(5.0f/6.0f),
     360f*(6.0f/6.0f)
   };

 protected Thread thread = null;
 protected TunnelRunner tunnel_runner = null;

 protected boolean help_graphics_enabled = false;

 public Function(float tunnel_radius)
  {
  super(null);

  this.tunnel_radius = tunnel_radius;
  this.tunnel_diameter = tunnel_radius*2;

  this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
  this.addMouseMotionListener(new MouseController());

  movement_circle = new MovementCircle();

  barrier_list = new ArrayList<AbstractBarrier>();
  barrier_list.add(new BigHoleBarrier());
  barrier_list.add(new RectangleHoleBarrier());

  // hier wird eine Barriere als aktive (die sichtbar ist) ausgewählt
  current_barrier = barrier_list.get(0);
  }

 public boolean isHelpGraphicsEnabled()
  {
  return help_graphics_enabled;
  }

 public void setHelpGraphicsEnabled(boolean enabled)
  {
  this.help_graphics_enabled = enabled;
  }

////////////////////////////////////////////////////////////////////////
// Paint
 public void paintComponent(Graphics g)
 {
 super.paintComponent(g);

 Dimension size = getSize();
 Graphics2D g2 = (Graphics2D)g;

 // zwei Graphics2D Objekte für verschiedene Arten der Darstellung

 // ein Graphics2D für das Interface, beginnt oben links
 Graphics2D g2_interface = (Graphics2D)g2.create();
 // ein Graphics2D für den Tunnel, beginnt in der mitte des Bildschirms
 Graphics2D g2_tunnel = (Graphics2D)g2.create();

 g2_tunnel.setBackground(Color.white);
 g2_tunnel.clearRect(0, 0, size.width, size.height);
 g2_tunnel.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
 g2_tunnel.translate(size.width/2, size.height/2);

 g2_interface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

 paintTunnelSideLines(g2_tunnel, Color.black);
 paintBarrier(g2_tunnel, movement_circle);
 paintBarrier(g2_tunnel, current_barrier);

 if(help_graphics_enabled)
   paintHelpGraphics(g2_tunnel);

 paintSpeed(g2_interface);
 }


protected void paintSpeed(Graphics2D g2)
{
 g2.setColor(Color.red);
 g2.setFont(new Font("Tw Cen MT",Font.PLAIN,20));
 g2.drawString("Speed: " + getspeed() + " %", 20, 20);
 g2.drawString("Speed-Factor: " + getspeedfactor(), 20, 40);
 g2.drawString("Zeit: " + gettimeM() + ":" + gettimeS(), 700, 20);
}


// die nächsten zwei Funktionen zeichnen die Seitenlinien

 protected void paintTunnelSideLines(Graphics2D g2, Color color)
  {
  g2.setColor(Color.black);
  paintTunnelSideLine(g2, 0);
  paintTunnelSideLine(g2, 1);
  paintTunnelSideLine(g2, 2);
  paintTunnelSideLine(g2, 3);
  paintTunnelSideLine(g2, 4);
  paintTunnelSideLine(g2, 5);
  }

 protected void paintTunnelSideLine(Graphics2D g2,
                                   int side_line_index)
  {
  Point2D.Float poc = getPointOnCircle(tunnel_front_center,
                                       tunnel_radius,
                                       tinnel_side_positions[side_line_index]);

  Line2D.Float base_line = new Line2D.Float(0f, 0f, poc.x, poc.y);

  Point2D.Float tp1 = getPointOnLine(base_line, 0.02f);
  Point2D.Float tp2 = getPointOnLine(base_line, 0.02f);

  Path2D.Float path = new Path2D.Float();
  path.moveTo(tp1.x, tp1.y);
  path.lineTo(poc.x+tp2.y, poc.y-tp2.x);
  path.lineTo(poc.x-tp2.y, poc.y+tp2.x);
  path.closePath();

  g2.fill(path);
  }

// die nächste Funktion zeichnet eine Barriere

 protected void paintBarrier(Graphics2D g2, AbstractBarrier barrier)
  {	 
  barrier.updateBarrierShapes();

  if(barrier instanceof MovementCircle)
    {
    g2.setColor(Color.gray);
    g2.draw(barrier.front);
    }
  else
    {
    g2.setColor(new Color(235, 235, 235));
    g2.fill(barrier.back);
    g2.setColor(Color.black);
    g2.draw(barrier.back);

    g2.setColor(Color.white);
    g2.fill(barrier.front);
    g2.setColor(Color.black);
    g2.draw(barrier.front);
    }
  }

// die nächste Funktion zeichnet die Hilfsgrafiken

 protected void paintHelpGraphics(Graphics2D g2)
  {
  g2.setColor(Color.green);
  g2.drawOval((int)(-tunnel_radius+tunnel_front_center.x),
              (int)(-tunnel_radius+tunnel_front_center.y),
              (int)tunnel_diameter,
              (int)tunnel_diameter);

  g2.setColor(Color.blue);
  g2.drawLine(0, 0, (int)tunnel_front_center.x,
                    (int)tunnel_front_center.y);

  g2.setColor(Color.red);
  g2.drawLine(-10, 0, 10, 0);
  g2.drawLine(0, -10, 0, 10);
  }


// Paint END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Animation & Interactivity
 private float speedfactor = (float) 0.0000;
 private double speed = 100;
 public double speedfactorR;
 public double speedR;
 public int timeS;
 public int timeM;
 public double t;
 public String string_timeM;
 public double time_buffer;

 public synchronized void startAnimation()
  {
  if(thread == null)
    {
    tunnel_runner = new TunnelRunner();
    thread = new Thread(tunnel_runner);
    thread.start();
    }
  }

 public synchronized void stopAnimation()
  {
  if(thread != null)
    {
    tunnel_runner.loop = false;
    thread = null;
    }
  }

 protected class TunnelRunner implements Runnable
 {
  protected boolean loop = true;
  @Override
  public void run()
   {  
   time_buffer=System.currentTimeMillis();

   // In dieser Schleife werden die Positionen und die Geschwindigkeiten
   // der aktiven Elemente (Barriere, Seitenlinien) angepasst
   while(loop)
   		{
	    if(speed<400.0)
	    {
	        speedfactor=(float)(speedfactor+0.0001*2);
	        speed=speed+(speedfactor/10);

	        speedfactorR=Math.round(speedfactor*100)/100.00;
	        speedR=Math.round(speed);
	    }

        // das ist der graue Kreis, der sich asymetrisch zu den Barieren bewegt
        // und so ein Gefühl für Bewegung und Geschwindigkeit gibt
        movement_circle.barrier_pos = (movement_circle.barrier_pos+0.0042f*(speedfactor+movement_circle.barrier_pos*3.0f)) % 1f;

        // hier wird die Position und die Geschwindigkeit eine Barriere angepasst
        current_barrier.barrier_pos = (current_barrier.barrier_pos+0.0065f*(speedfactor+current_barrier.barrier_pos*2.0f)) % 1f;

        // die Seitenlinienpositionen auf dem Vorderkreis (den grünen) verschieben,
        // um den Rotationseffekt zu erzeugen
        float side_rotation_speed = 0.2f;
        for(int i = 0; i < tinnel_side_positions.length; i++)
           tinnel_side_positions_ = (tinnel_side_positions + side_rotation_speed) % 360f;

        if(timeS<60){
        timeS=(int)Math.round(((System.currentTimeMillis()-time_buffer)/100)*100.0)/1000;
        }
        else{
        timeM=timeM+1;
        timeS=0;
        time_buffer=System.currentTimeMillis();
        }

        repaint();

        try { Thread.sleep(15); }
        catch(InterruptedException e) { loop = false; e.printStackTrace(); }

        if(current_barrier.barrier_pos==0.5){
        for (int i=0; i<1;i++)
	    {
	    current_barrier =barrier_list.get((int) Math.floor(2*Math.random()));
	    System.out.println(current_barrier);
	    }  	
        }
        }
   }

 }


 public double getspeed(){
     return this.speedR;
}

 public double getspeedfactor(){
	 return this.speedfactorR;
 }

 public int gettimeS(){
	 return this.timeS;
 }
 public int gettimeM(){
	 return this.timeM;
 }


 protected class MouseController extends MouseAdapter
 {
  @Override
  public void mouseMoved(MouseEvent e)
   {
   super.mouseMoved(e);

   Dimension size = getSize();

//   tunnel_center.setLocation(e.getX() - size.width/2, e.getY() - size.height/2);
   tunnel_front_center.setLocation(-(e.getX() - size.width/2), -(e.getY() - size.height/2));

   repaint();
   }
 }

// Animation & Interactivity END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Barriers

 protected abstract class AbstractBarrier
 {
  /** Form, welche die Vorderseite eine Barriere darstellt */
  protected Shape front = null;
  /** Form, welche die Hinterseite eine Barriere darstellt */
  protected Shape back = null;

  /** Position im Tunnel zwischen 0f (Hinten) und 1f (Vorne).
      Kann man auch als Tiefe ansehen */
  protected float barrier_pos = 0.5f;

  protected abstract void updateBarrierShapes();
 }

 protected class MovementCircle extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   float barrier_radius = barrier_pos*tunnel_radius;

   front = new Ellipse2D.Float(-barrier_radius+pit.x, -barrier_radius+pit.y,
                               barrier_radius*2, barrier_radius*2);
   }
 }

 protected class BigHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_radius = barrier_radius*0.9f;
   float hole_diameter = hole_radius*2;

   Ellipse2D.Float barrier_base = null;
   Ellipse2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_radius = barrier_radius*0.9f;
   hole_diameter = hole_radius*2;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
                                      -hole_radius+pit.y,
                                      hole_diameter,
                                      hole_diameter);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

 protected class RectangleHoleBarrier extends AbstractBarrier
 {
  @Override
  protected void updateBarrierShapes()
   {
   // 2D Postion im Tunnel anhand der Tiefe ermitteln
   Point2D.Float pit = getPointOnLine(0, 0,
                                      tunnel_front_center.x,
                                      tunnel_front_center.y,
                                      barrier_pos);

   // Vorderform für die Barriere aufbauen

   float barrier_radius = (barrier_pos*tunnel_radius);
   float barrier_diameter = barrier_radius*2;
   float hole_width = barrier_radius*0.7f;
   float hole_height = barrier_radius*0.2f;

   Ellipse2D.Float barrier_base = null;
   Rectangle2D.Float barrier_hole = null;
   Area area = null;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.front = area;

   // Hinterform für die Barriere aufbauen

   barrier_radius = barrier_radius*0.96f;
   barrier_diameter = barrier_radius*2;
   hole_width = barrier_radius*0.7f;
   hole_height = barrier_radius*0.2f;

   barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
                                      -barrier_radius+pit.y,
                                      barrier_diameter,
                                      barrier_diameter);
   barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
                                        -hole_height+pit.y,
                                        hole_width*2,
                                        hole_height*2);

   area = new Area(barrier_base);
   area.subtract(new Area(barrier_hole));
   this.back = area;
   }
 }

// Barriers END
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Geometric Help Functions

 protected static Point2D.Float getPointOnCircle(Point2D.Float center,
                                                 float radius, float angle)
  {
  return getPointOnCircle(center.x, center.y, radius, angle);
  }

 protected static Point2D.Float getPointOnCircle(float x, float y,
                                                 float radius, float angle)
  {
  return new Point2D.Float(x + (float)(radius*Math.cos(Math.toRadians(angle))),
                           y + (float)(radius*Math.sin(Math.toRadians(angle))));
  }

 public static Point2D.Float getPointOnLine(Line2D.Float line,
                                            float t)
  {
  return getPointOnLine(line.x1, line.y1, line.x2, line.y2, t);
  }

 public static Point2D.Float getPointOnLine(float x1, float y1,
                                            float x2, float y2,
                                            float t)
  {
  return new Point2D.Float((x2 - x1)*t + x1,
                           (y2 - y1)*t + y1);
  }

// Geometric Help Functions END
////////////////////////////////////////////////////////////////////////
}[/HIGHLIGHT]

Vielen Dank schonmal im vorraus !

PPS: Ich habe schon einen Zufallsgenerator drin, weiß aber nicht so recht wie bzw. eher wo ich ihn einbinden muss, damit er jeweils nur am Anfang der Röhre (wenn die Barrieren gezeichnet werden) die aktuelle Barriere abfragt !

MFG
Benni_


----------



## hdi (29. Mrz 2009)

Sieht ja schon mal ganz gut aus, aber eine Frage:
Kann es sein, dass deine Röhre viieeeeel zu weit in die Tiefe geht?
Und gleichzeitig die Geschwindigkeit etwas zu hoch ist?

Denn diese Zwischen-Dinger, die immermal wieder kommen, tauchen plötzlich
wie mit Lichtgeschwindigkeit aus dem nix auf, mitten in der Röhre, und sind auf
einmal wieder weg...

Dann noch etwas:
Vllt sieht es ja nur so aus aber ich hatte das Gefühl, ich konnte mit der Maus nicht
ganz an die Seiten der Röhre gehen, weil die Bewegung zu langsam war. D.h. meine Maus
war schon ausserhalb des Fenster bevor ich nach ganz rechts gehen konnte.
Hier sollte man vllt den Wert der Bewegung etwas erhöhen.

Und Barrieren... habe ich aber keine gesehen?
Hast du denn schon ein Klassen-Konzept für so eine Barriere?

PS: Nicht dass es so rüberkommt ich will das Spiel nur schlecht reden, ich wollte nur
sagen wie jetzt mein Eindruck war.


----------



## death90 (29. Mrz 2009)

Hallo,

ja einiges stimmt schon,..

aber wichtig wäre mir nun mal, wo ich den Zufallsgenerator hinsetze, damit er zu beginn jedes Durchlaufes, abfragt, welche Barriere er nehmen soll,...halt den Zufallsgenerator abfragt ?

und wie ich so eine Kollisionsabfrage schreiben kann !

danke schonmal

MFG
Benni


----------



## hdi (30. Mrz 2009)

Was ich grad per Zufall in deinem Code gesehen habe:

[HIGHLIGHT="Java"]while(run==false){
      but.addActionListener(
              new ActionListener() {
              public void actionPerformed(ActionEvent e){
               run = true;
     }
    }
);[/HIGHLIGHT]

Du addest dem Button permanent einen ActionListener. D.h. du erstellst in der Sekunde
ca. 500 ActionListener-Klassen, implementierst sie, und addest sie zu dem Button, um
sie gleich danach wieder wegzuwerfen.

Lass mal die while-Schleife drumrum *komplett* weg! Es reicht, das einmal zu tun.

Um jetzt den Spielablauf zu steuern sollte der Klick auf den Button nicht den boolean
run auf true setzen, sondern einfach eine Methode aufrufen:

[HIGHLIGHT="Java"]
      but.addActionListener(
              new ActionListener() {
              public void actionPerformed(ActionEvent e){
                   startGame();
     }
    });
[/HIGHLIGHT]

[HIGHLIGHT="Java"]private void startGame(){
      // hier kommt alles rein was in deiner Version in dem Block
      // zu (if run == true) steht
}[/HIGHLIGHT]

...diese Methode wird ja nicht aufgerufen, solange du nicht auf den Button drückst,
kein Grund das Programm in einer Endlosschleife mit "busy waiting" zu knechten.
Das ist ja noch schlimmer als Busy-Waiting, ich weiss ja nicht was so eine inner class
an Speicher frisst, bzw. wie aktiv der GC da ist.
Aber damit kannste denk ich (sehr) alte System glatt lahmlegen :toll:

Wegen den Barrieren: Die solltest du halt an enstprechender Stelle in deinen GameLoop
schreiben, also while(loop){... hier ...}


----------



## slawaweis (30. Mrz 2009)

death90 hat gesagt.:


> habe es mittlerweile hinbekommen, dass Zeit und Geschwindigkeit angezeigt werden !


gut gemacht.



death90 hat gesagt.:


> Nun gibt es noch 3 Dinge die ich machen muss:
> *1.* ca. 3 versch. Barrieren erstellen, die sich eventuell mit drehen (nur wie ? polygon-objekt ?)


um weitere Barrieren zu erstellen, musst Du von der Klasse AbstractBarrier ableiten und die Funktion updateBarrierShapes() implementieren. In dem Quelltext sind zwei Beispiele schon drin. Der Rest ist Java2D, Geometrie/Trigonometrie und boolesche Operationen, das hier zu erklären würde zu lange dauern. Schnapp Dir am besten ein Buch über Java2D.

Das Drehen ist nicht schwer, die Barrieren sind einfache Kreise. Dazu sollte die Klasse AbstractBarrier eine neue Variable bekommen, den Drehwinkel, analog zu "barrier_pos". Diese neue Variable wird dann zusammen mit barrier_pos verändert. Am Ende der updateBarrierShapes() Funktion von jeder Barriere muss man dann die "front" und "back" Formen mit AffineTransform um den Zentralenpunkt der Barriere "pit" drehen. Alternativ kann man auch eine Funktion in AbstractBarrier erstellen, welche es für alle Barrieren macht.



death90 hat gesagt.:


> *2.* Kollisionsabfrage (stopAnimation, wenn kollision =true,. oder so, bloß wie soll die aussehen ? )


das habe ich eigentlich schon im meinen ersten Post mit dem Quelltext erwähnt. Der Spieler sitzt immer auf dem Punkt (0, 0), welcher mit dem roten Kreuz markiert ist, d.h. man muss nur die Kollision zwischen der Front der vordersten Barriere und dem (0, 0) Punkt berechnen, ungefähr so:

[highlight="java"]
if(current_barrier.front.contains(0, 0))
  {
  // Kollision
  }
[/highlight]



death90 hat gesagt.:


> *3.* das zeichnen von 2 Barrieren während des Gameloops in einem bestimmten abstand, so dass nicht immer erst eine neue erscheint, wenn die erste schon vorbei ist !


dazu muss Du eine zweite Liste anlegen. In barrier_list liegen alle möglichen Barrieren. Jetzt muss noch eine Liste "visible_barrier_list" her, die nur die aktuell sichtbaren Barrieren enthält, sagen wir mit der Anzahl N. Eigentlich ist es auch keine Liste, sondern eine Schlange, First-In-First-Out.

Nehmen wir jetzt an, wir haben N=5, also 5 gleichzeitig sichtbare (oder durch die Röhre laufenden) Barrieren. Diese werden mit einem gleichen Abstand zwischeneinander angeordnet. Die Tiefe beträgt immer 1.0f, d.h. die Barrieren laufen von 0.0f bis 1.0f. Deshalb müssen die Barrieren für N=5 mit 0.2f Abstand laufen. Zuerst wird die erste Barriere bei 0.0f eingefügt und läuft durch. Wenn diese 0.2f erreicht, wird die zweite eingefügt. So geht es bis zu fünften Barriere durch. Wenn dann die erste Barriere, die zuerst in die Schlange eingefügt wurde, 1.0f erreicht, wird diese aus der Schlange entfernt und hinten kommt eine neue rein. Zum Schluss muss man die Barrieren in umgekehrten Reihenfolge zeichnen, also die hinterste zuerst, die vorderste zuletzt.



death90 hat gesagt.:


> ich stell mir vor das das erstellen dieser Barrieren das schwerste ist oder ?


würde ich nicht sagen.



death90 hat gesagt.:


> Naja ich hoffe auf tatkräftige unterstützung, da morgen schon eine erste Generalprobe des Spiels erfolgt


dann viel Erfolg!

Slawa


----------



## death90 (31. Mrz 2009)

*Hallo,*

habe schon angefangen deine Lösungsvorschlage umzusetzten,...klappt schon ganz gut !

Meine Frage wäre nun noch wie ich den Zufallsgenerator vernünftig einfügen könnte ?
Hab schon einiges probiert, doch irgendwie funktioniert das nicht richtig 
Der Generator soll ja lediglich zufällig eine Barriere auswählen !
*(Barrier_list.get(Zufallsgenerator))*

Hat da jemand ne Idee ?

danke schonmal

MFG
Benni


----------



## hdi (31. Mrz 2009)

Generell kriegst du aus einer Liste von Objekten ein zufälliges so:

[HIGHLIGHT="Java"]Random ran = new Random();
Object randomObject = myListOfObjects.get(ran.nextInt(myListOfObjects.size()));[/HIGHLIGHT]

Aber Vorsicht: ran.nextInt(0) gibt einen Runtime-Error, also stell vorher sicher dass die Liste auch nicht leer ist.


----------



## death90 (1. Apr 2009)

*Hallo,*

ich weiß ja wie ich den Zufallsgenerator hinbekomme, nur nicht wo ich ihn in
meinem Programm einbinde, da er immer nur zum Einsatz kommen soll, wenn die 
Barrieren erneut durch die Röhre laufen.
Es soll quasi bei jedem Röhrendurchlauf eine zufällig gewählte Barriere gezeichnet werden!

Wenn ich den Zufallsgenerator einfach in die Hauptschleife einbinde, dann wählt er bei jedem schritt vorwärts in der Röhre eine neue Barriere, ist ja klar !

Nur wie bzw. wo kann ich sonst diesen Generator einbinden ?

Der code des Zufallsgenerators: *Math.floor(3*Math.random());*

Schonmal vielen Dank für Ideen

MFG
Benni


----------



## hdi (1. Apr 2009)

Nur weil etwas in einer Schleife steht, heisst das ja nicht gleich, dass es bei
jedem Schleifendurchlauf ausgeführt wird:

[HIGHLIGHT="Java"]while(true){
       barriere.z--;
       if(barriere.z < 0){
           barriere = Generator.getRandomBarriere();
       }
}      [/HIGHLIGHT]      

D.h. du lässt eine Barriere solange näher kommen / bewegst dich selbst darauf zu,
bis du halt vorbei bist (bzw die Barriere vorbei ist).
Dann machste ne neue...


----------



## death90 (1. Apr 2009)

Hallo,

habe das mit der Position der Barrieren schon probiert !

Nur leider funktioniert das aus irgendeinem Grund nicht. Er ermittelt ab einer bestimmten
hinter dem sichtbaren Bereich per zufall eine neue Barriere, aber zeichnet diese noch
1-2 mal vor einem neuen Röhrendurchlauf und man sieht, das 2 mal eine Scheibe direkt vor der ich-Perspektive gezeichnet wird, bevor eine neue Runde startet !

Das funktioniert dann zwar mit dem Zufall, aber sieht beschissen aus !

Hat jemand eine Idee ? ( iehe weiter oben den Code zum verständnis )

vielen Dank mal wieder

MFG
Benni


----------



## death90 (1. Apr 2009)

*Hallo,*

ich mal wieder ^^

Habs jezz etwas besser hinbekommen mit dem Zufallsgenerator !

Meine neue Frage ist nun, wie ich bei ner Barriere die position der Aussparung bzw. des Loches zum Rand hin veränder ?

Ich bekomm das irgendwie nich hin 

*! siehe Code weiter oben !*

vielen Dank mal wieder

MFG
Benni


----------



## death90 (1. Apr 2009)

Hallo,

schade das sich noch keiner gemeldet hat, aber ich habs jezz
mittlerweile hinbekommen ! :toll:

Nun noch eine letzte Frage:

Wie kann ich, wenn die Abbruchbedingung der Game-Schleife erfüllt ist und die Animation
gestoppt ist, einen transparenten roten Bildschirm zeichnen lassen, mit einem text in der Mitte ?

Es soll dabei das gesamte Frame rot transparent sein, so dass man durch das rot noch die gestoppte Animation sieht !

Wäre für Ideen und Lösungen sehr sehr dankbar

MFG
Benni


----------



## hdi (2. Apr 2009)

Dafür brauchst du doch nicht extra ein Frame erstellen.
Dein Spiel läuft ja wohl in einem JPanel. In dessen paintComponent-Methode
kannst du ja einbauen (als letzte Anweisung):

[HIGHLIGHT="Java"]if(gameover){
    Color c = new Color(255,0,0,200) // der letzte Wert ist der alpha-Kanal -> transparenz
    g.setColor(c);
    g.fillRect(...);
    g.setColor(Color.black);
    g.drawString("Du hast leider verloren, oh wie schade usw usw",...);
}[/HIGHLIGHT]


----------

