# Eine Art "Image Map" in Java



## babuschka (1. Mai 2007)

Hallo zusammen,

bin dabei eine GUI (für ein einfaches Spiel) zu konstruieren und der bisherige (recht technische) Entwurf sieht wie folgt aus: http://www.badongo.com/pic/614011

Jetzt möchte ich, dass wenn man mit dem mousecursor über die Spielfläche fährt (Kacheln) immer über dieser Kachel eine gelbe Raute (siehe Bild) aufleuchtet, über der sich der (unsichtbare) mousecursor befindet. Ich hoffe ihr versteht, was ich meine.

Ist das möglich? Und wenn ja, kann mir jemand eine grobe Vorgehensweise angeben, mit der ich weiter komme? Vielen Dank schonmal!

Gruß,
squirrel


----------



## Wildcard (1. Mai 2007)

Na das kommt mir doch sehr bekannt vor  :wink: 
Ich schätze mal du bist mit meinen Anregungen nicht wirklich vorwärts gekommen?


----------



## Marco13 (1. Mai 2007)

Hm - an die Component, wo du das reinzeichnest, kannst du einen MouseMotionListener hängen. Wenn die Maus bewegt wird, wird ausgerechnet, in welchem Feld sie ist, und dieses Feld wird dann gelb umprahmt. Beschreib' ggf. das Problem nochmal genauer...


----------



## babuschka (1. Mai 2007)

Hallo Wildcard,

du sagtest damals, ich soll mit einem MouseMotionListener herausfinden über welcher Raute der Cursor ist und diesem ein 'isSelected' Flag oder etwas in der Art setzen. Das Problem ist aber, genau dass ich nicht weiß, wie ich das machen soll. Also wie erstelle ich eine Image Map, sodass immer genau die gewünschte Raute aufleuchtet? Rein handwerklich.

Gruß,
squirrel


----------



## Wildcard (1. Mai 2007)

'Rein Handwerklich' muss dein Objekt in der Lage sein einen Rahmen zu zeichnen wenn ein bestimmtes Flag auf true steht.
Dieses Flag wird gesetzt wenn der Cursor über dem Objekt steht.
Wie das im Detail aussieht hängt davon ab ob du vorhast mit Standard GUI Komponenten zu arbeiten (davon würde ich in deinem speziellen Fall eher abraten), oder ein eigenes Lightweight Framework implementierst.


----------



## babuschka (1. Mai 2007)

Hallo Marco13,

hab sogar schon einen MouseMotionListener implementiert, mit dem ich immer die aktuelle mouseposition auslese und ausgebe. Das Problem sehe ich genauer hier:

Wie definiere ich diesen (von der Form her: Raute) doch rechte schwierigen Auswahlbereich? Also wenn alternativ z.B. einfach nur ein Rechenkästchen-Muster hätte, wäre das mit der Definition der Auswahlbereiche doch erheblch einfacher. Meine Idee ist, dass ich einfach die Images selbst, die ja nur eine Raute und daneben "Transparenz" enthalten als Vorlage dienen könnten, eben den Bereich zu definieren, der ein "RollOver" haben soll.

Gruß,
squirrel


----------



## Wildcard (1. Mai 2007)

Dieses Objekt erledigt einen großteil deiner Arbeit:
http://java.sun.com/javase/6/docs/api/java/awt/Polygon.html


----------



## babuschka (1. Mai 2007)

Dankeschön!! Das sieht gut aus! Werde mir das jetzt mal in aller Ruhe ansehen.


----------



## Wildcard (1. Mai 2007)

Das kannst du sowohl verwenden um den Rahmen zu zeichnen, als auch für die geometrischen Berechnungen (contains,...).


----------



## babuschka (1. Mai 2007)

Ist es denn grob richtig, wenn ich zunächst eine Klasse

class Kachel extends Polygon

schreibe? Dann habe ich vor, an der Stelle, an der ich bisher in meinem JFrame einfach die Bodenkacheln nebeneinander zeichne, Objekte der Klasse Kachel zu zeichnen.

Diese Klasse hat dann Methoden, die die Mausposition überwachen und ggf. das Image verändern. Richtig?


----------



## Wildcard (1. Mai 2007)

Ja, das kannst du schon so machen.
Eine Sache würde ich allerdings ändern:
In deinem Fall hast du recht viele dieser Polygone.
Anstatt das jedes Polygon darauf hört ob sich die Maus in ihm befindet oder nicht, könntestt du das auch an zentraler Stelle erledigen und dann auf dem entsprechenden Kachel-Objekt setSelected(true/false) aufrufen.


----------



## Gast (2. Mai 2007)

hmm, du hast doch bestimmt eine klasse "Stein", davon erstellst du ja objekte, und zeichnest diese in dein spielfeld.

wenn du nun in deiner "stein" klasse einfach noch n mouselistener verwendest, und bei mouveover, eine paint methode anstösst, sollte es doch funzen, oder?


----------



## Wildcard (2. Mai 2007)

500 MouseListener sind IMO nicht die beste Lösung.


----------



## Marco13 (2. Mai 2007)

Hm. Wie ZEICHNEST du denn die Rauten? Also, um sie zeichnen zu können, mußt du ja ihre Form kennen, und wenn du ihre Form kennst, kannst du auch gucken, ob der Mauscursor darin enthalten ist. Aber wenn's mit Polygon geht, ist ja vielleicht schon OK.


----------



## babuschka (5. Mai 2007)

Hallo zusammen,

vielen Dank fuer eure wertvollen Gedanken. Ich bin mittlerweile total verzweifelt. Ich merke, dass ich mich viel zu wenig mit Java auskenne und das einarbeiten in die ganzen speziellen Themen extrem zeitaufwändig ist! Ich habe das Gefühl, dass meine Klassen total umständlich und auch teilweise unsinnig programmiert sind ... nichstdestotrotz funktioniert es ganz gut:

Habe eine Main-Klasse, die ein GameFrame-Objekt (extends JFrame) erstellt und dort wird dann ein neues GamePanel-Objekt (extends JPanel) erstellt. In meiner GamePanel-Klasse ist in GamePanel() ein MouseListener integriert und ansonsten ALLES was ich zeichne in der protected void paintComponent(final Graphics g)-Methode. Innerhalb dieser Methode erstelle ich ein Level-Objekt, welches die Daten des Levels enthalten, die die paintComponent-Methode braucht, um die Kacheln zu zeichnen.

Und genau an dieser Stelle möchte ich ansetzen:

1. kann ich nicht einfach statt die Kacheln (in einer komplizierten Schleife) zu zeichnen an dieser Stelle einfach Objekte vom Typ Kachel konstruieren? Ich habe hier bereits mehere Ansätze in den letzten 5 Tagen ausprobiert, alles ohne Erfolg!

2. Wie kann ich mein Programm / Konzept "entwirren"?


@Gast: ja, genau so habe ich mir das gedacht - leider laufe ich mit verschiedenen Ansätzen gegen eine Wand...

@Marco13: die Rauten zeichne ich bisher (also ohne RautenOBJEKT) einfach mittels drawImage und einem transparenten GIF.

@Wildcard: die Klasse Polygon ist echt mächtig und genau das richtige für meine Zwecke! Aber leider komme ich zu keinem brauchbaren Ergebnis.


Wäre super, wenn mir jemand helfen könnte, die Struktur zu verbessern. Ich würde mich auch über ein alternatives Gerüst freuen, wenn da jemand eine spontane Idee hat.

Vielen Dank und viele Grüße,
squirrel


----------



## Wildcard (5. Mai 2007)

Ja, die Idee ist die richtige.
Du brauchst eine Klasse Kachel.
Davon erstellst du dir einige die du in einer Collection speicherst.
Eine Kachel besitzt intern ein Polygon Objekt das den Großteil der Arbeit macht, und hat eine draw(Graphics2D g) Methode.
In der draw Methode wird dann lediglich die Farbe gesetzt und g.draw(polygon) aufgerufen.
In der paintComponent Methode iterierst du über die Collection und rufst auf jedem Objekt draw(g) auf.


----------



## Guest (5. Mai 2007)

Hallo Wildcard,

vielen Dank für deine Antwort. Ich habe aber ein Paar Fragen zu den einzelnen Punkten:

1. Du brauchst eine Klasse Kachel.
ist klar

2. Davon erstellst du dir einige die du in einer Collection speicherst.
Also z.B. mittels einer irdendwie gearteten Schleife Kachel-Objekte erstellen (Daten dazu auf Level.class) und dann in Collection speichern? Wäre auch froh wenn ich erstmal ein einziges Objekt hinbekommen würde.

3. Eine Kachel besitzt intern ein Polygon Objekt das den Großteil der Arbeit macht, und hat eine draw(Graphics2D g) Methode.
Kachel abgeleitet von Polygon, also Kachel extends Polygon? Meinst du mit intern, dass das Polygon quasi nicht gezeichnet wird, weil ich möchte ja keine solid Farbfläche, sondern eine bitmap.

4. In der draw Methode wird dann lediglich die Farbe gesetzt und g.draw(polygon) aufgerufen.
Hmm, jetzt wird das Polygon wohl doch gezeichnet?!

5. In der paintComponent Methode iterierst du über die Collection und rufst auf jedem Objekt draw(g) auf.
Wo wird denn die Bitmap gezeichnet? In draw im Kachel-Objekt oder in paintComponent?

Danke und Gruß,
squirrel


----------



## Wildcard (5. Mai 2007)

3. Extends Polygon würde nicht machen, ein Polygon wird einfach ein Member der Kachel.
Stimmt, du willst ja ein Bild zeichnen. Dann dient das Polygon hauptsächlich für die Geometrie-Berechnung.
Weiterhin kannst du dir den Rahmen den du anzeigen willst wenn ein Feld ausgewählt wird mit einem Polygon zeichnen.

4.
Hat sich dann erledigt.

5.
In der draw der einzelnen Objekte. Die paintComponent ruft die draw Methode jeder Kachel auf.
Allerdings habe ich nicht ganz verstanden ob du jetzt ein bitmap hast, oder eins pro Kachel.
Wenn es nur eins ist, würde ich es in der paintComponent zeichnen.


----------



## babuschka (5. Mai 2007)

Bevor ich mich unglücklich mache, möchte ich dir/euch mal kurz meinen bisherigen Code zeigen (Kacheln nicht als Objekte) und um konstruktive Kritik bitten:

1. Klasse GameFrame
2. Klasse GameGraphics
3. Klasse Level

Meine Frage ist: kann/soll ich auf meinem obigem Code aufbauen um die Kacheln als Objekte zu realisieren? Oder ist alles zu verworren? Sollte ich Teile in eigene Klassen auslagern? Oder generell etwas anders machen?

Danke und Gruß,
squirrel


----------



## Wildcard (5. Mai 2007)

Einige Unschönheiten drin.
-Die paintComponent ist viel zu lang und aufwendig.
-Das entzerrt sich wenn du Objekte verwendest.
-in der PaintComponent sollten nach Möglichkeit keine Objekte instanziert werden
-Bilder in der paint laden ist ein absolutes no-go


----------



## babuschka (5. Mai 2007)

Okay! Danke schonmal.

1. Meinst du es macht Sinn meine Kachelobjekte vom Level instanzieren zu lassen?

2. Wo soll ich denn dann meine Bilder laden? Soll ich eine Art Preloader Klasse bauen?


----------



## Wildcard (5. Mai 2007)

1. kann man machen
2. zum Beispiel im Konstruktor


----------



## babuschka (5. Mai 2007)

Okay, haben jetzt eine Klasse Kachel, die jetzt das Image auf unser Panel zeichnen soll. Die Bilder werden im Konstruktor der Kachel geladen.

Wie kann die Kachelklasse in das Panel zeichnen bzw. wie/wo muss die draw-Methode implementiert werden? Stehe hier voll auf dem Schlauch.

Danke und Gruß,
squirrel


----------



## Wildcard (5. Mai 2007)

In der Kachel eine draw(kann auch anders heißen) die als Parameter ein Graphics Objekt (vom JPanel) bekommt auf das sie zeichnen kann.


----------



## babuschka (5. Mai 2007)

Ich möchte in der Kachel drawImage verwenden. Das klappt aber leider nicht. Es heißt immer "The method drawImage is undefined for the type Kachel". Wie kann ich das ändern?


----------



## Wildcard (5. Mai 2007)

g.drawImage. Das g muss übergeben werden.


----------



## babuschka (5. Mai 2007)

Wie erstelle ich denn ein Graphics Objekt g (im JPanel), so dass ich es an drawImage() uebergeben kann?


----------



## Wildcard (5. Mai 2007)

Du erstellst keins, sondern du bekommst eins (in paintComponent).


----------



## babuschka (5. Mai 2007)

Hab jetzt meine Level-Klasse verändert und in GameGraphics folgendes Konstrukt eingebaut (natürlich erstmal nur zum testen, deswegen "harte Werte".

Ich muss leider nochmal nachfragen: wie muss denn jetzt meine draw()-Funktion in Kachel aussehen?


----------



## Wildcard (5. Mai 2007)

Ja, so.


----------



## babuschka (5. Mai 2007)

Okay, das funzt jetzt.

Aber jetzt zum Wesentlichen:

1. Wie bringe ich jetzt die Klasse Polygon mit ins Spiel? Du sagtest was von member? Könntest du vielleicht anhand meines Codes skizzieren, wo ich ansetzen muss?

2. Wo bringe ich die Listener unter, die das Polygon dann "auf" der entsprechenden Kachel aufleuchten lassen sollen?


----------

