# Rechteck zeichnen auf JPanel?



## jannik (19. Februar 2011)

Hey Leute,

ich hab bereits auf einem anderen Board nachgefragt, allerdings gibt es hier hoffentlich ein paar mehr Java-Benutzer.

Ich habe ein großes JPanel für eine Art Spiel, das soll das Spielfeld darstellen bzw die "Map".
Darauf lass ich 4 verschiedene Spielfiguren als weitere kleine JPanels sich bewegen mittels der Pfeiltasten. Dies klappt auch wunderbar. Nur habe ich jetzt das Problem, dass ich eine Art Schleimspur hinter den Spielern machen möchte, die entsteht, wenn man über die Map mit dem Spieler "läuft. (So in der Art wie Snake)... 
Aber bei mir bleibt das JPanel einfach schwarz 

Hier ist der Code fürs zeichnen, also erstmal ein Beispiel

```
solved
```

Ich habe den Code nicht in einer Paint/Paint Component Funktion drin, ich müsste es außerhalb machen, erscheint mir irgendwie leichter zu realisieren.

Hier ist mein komplettes Projekt: (Der SinglePlayer()-Teil sollte wichtig sein 

```
solved
```

Wäre echt nett, wenn ihr mir weiterhelfen könntet, ich habe jetzt ziemlich viel Zeit verbraucht, um den Fehler zu finden, ohne Glück .

Vielen Dank im Vorraus!
Jannik


----------



## AntiCampeR (19. Februar 2011)

du denkst nur dass das panel schwarz bleibt aber in wirklichkeit wird dein rechteck einfach wieder übermalt...


```
while (true) {
    Graphics gr = meinJPanel.getGraphics();
    gr.setColor(Color.black);
    gr.fillRect(0,0,100,100);
}
```

so würde es gehen aber das is wohl nicht in deinem sinn...
deshalb empfehl ich dir die paintComponent zu benutzen auch wenns etwas mehr code ist...


----------



## jannik (20. Februar 2011)

Okay, danke für die Antwort.

Könntest du mir da etwas auf die Sprünge helfen? Wie baue ich PainComponent() ein und kann nach und nach das Panel bemalen. Die Rechteckigen schleimspuren sollen ja nicht alle am anfang gleich dfa sein sondern nach und nach entstehen, je nachdem, wie man mit der Spielfigur auf dem Panel rumfährt 

Wäre echt super, wenn das irgendjemand mir erklären könnte


----------



## AntiCampeR (20. Februar 2011)

das könntest du z.b so machen:


```
class Schleimspur extends JPanel {

      int x,y,width,height;
      boolean drawSchleimspur;

      public Schleimspur () {
          drawSchleimspur=false;
          x=0;
          y=0;
          width=0;
          height=0;
      }

      @Override
      public void paintComponent (Graphics g) {
         super.paintComponent(g);
         if (drawSchleimspur) {
            g.setColor(Color.black);
            g.fillRect(x,y,width,height);
         }
      }

      public void drawSchleimspur (int x, int y, int width, int height) {
        this.x=x;
        this.y=y;
        this.width=width;
        this.height=height;
        drawSchleimspur=true;
        repaint();
      }

      public void delSchleimspur () {
        drawSchleimspur=false;
        repaint();
      }
  }
```


----------



## jannik (20. Februar 2011)

danke, dass ist schonmal ein Anfang. 

Das Problem ist halt nun, dass ich nicht nur ein Rechteck brauche, sondern möglicherweise unendliche viele, außerdem werden andere Spieler eine Dreiecke sogar überfahren, das müsste ja eigentlich kein Problem sein. Ich erklärs mal mit einem Bild:


```
http://img402.imageshack.us/img402/8418/bgry.png
```

Ich hab grad nix von erlaubten ImageHostern in den Rules gefunden, wenn ich was falsch mache, bitte mitteilen


----------



## AntiCampeR (21. Februar 2011)

dann musst du dir die position von jedem rechteck merken bzw wer wann wo was überfahren hat... scheint mir ziemlich aufwändig zu sein... wie hast du denn das "spielfeld" aufgebaut?

[EDIT]
eine möglichkeit ist für jeden spieler einen vector anzulegen wo du immer die rechtecke einfügst, und dann einfach alle rechtecke zeichnen, die in den vektoren vorhanden sind. dazu brauchst du noch nen boolean, ob das rechteck gezeichnet werden soll oder nicht (also falls die spur von jemand anders überfahren wurde) oder du löscht das entsprechende rechteck dann aus dem vector
[/EDIT]


----------



## jannik (21. Februar 2011)

Könntest du mir den Anfang kurz zeigen, ich hab keine Ahnung, wie ich da beginnen soll 
Wäre echt gut, danke


----------



## AntiCampeR (21. Februar 2011)

klar 


```
class SchleimspurPart {

     int x,y,width,height;

     public SchleimspurPart (int x,int y,int width,int height) {
        this.x=x;
        this.y=y;
        this.width=width;
        this.height=height;
     }
 }
```

die klasse verwendest du dann so:


```
Vector<SchleimspurPart> red=new Vector<SchleimspurPart>();
```

das machst du für jeden spieler

und dann nur noch in der paintComponent zeichnen:


```
public void paintComponent (Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.red);
      for (int i=0;i<red.size();i++) {
          SchleimspurPart sp=red.get(i);
          g.fillRect(sp.x,sp.y,sp.width,sp.height);
      }
  }
```

natürlich eine for-schleife für jeden vector und davor die farbe ändern

rechtecke fügst du so hinzu:


```
red.add(new SchleimspurPart(0,0,50,50));
```

dann noch n repaint() nach jedem add dann passt des

und wenn eine spur überfahren wird dann musst du im vector nach dem entsprechenden rechteck suchen und es aus dem vector löschen


----------



## jannik (21. Februar 2011)

Dankeschön  Ich werde es morgen ausprobieren  Wie ich das mit dem Löschen hinkriege ist allerdings fraglichlich, da es auch mal vorkommt, das ein Rechteck nur mal halb oder dreiviertel oder auch nur ein bisschen geschitten wird  Hmmm...

Ich hatte vorhin noch eine andere Idee, unzwar Folgendes:
-> Man nimmt einfach ein schwarzes Image als Hintergrund des Panels, sozusagen als "Buffer" und zeichnet da alles rauf. Man bewegt einen Spieler, zeichnet auf das Bild und packt es wieder als Hintergrundbild aufs Panels.

So müsste man das mit den Vektoren eigentlich auch umgehen können und auch dieses immer wieder neu zeichnen.

Was hälst du davon, würde das gehen? Wie sieht das mit der Rechenzeit/Performance aus?

Edit:\
Also laut eines Kollegen wäre meine alternative Überlegung schneller, aber ich bin da echt skeptisch, da es bestimmt nicht so schnell vonstatten geht, auf ein Bild zu zeichen, als auf einem JPanel. Oder?  Ach ich hab keine Ahnung, ob  das überhaupt geht, aber ich gucke einfach mal, was du so schreibst


----------



## AntiCampeR (22. Februar 2011)

klar so könnte man das natürlich auch machen  ich stimme auch deinem kolleg zu, dass diese methode schneller is, jedenfalls wenn die vectoren viele rechtecke enthalten


----------



## jannik (22. Februar 2011)

Okay, ich habe nun ein Buffered Image erstellt, welches auf ein extended JPanel geschoben wird, wo ich es als Hintergrund machen will.

Nun aber ein großes Problem: Warum sind meine Blobs nicht sichtbar auf dem JPanel, wenn ich diese nach dem Mausklick auf SinglePlayer geaddet habe, sondern nur das SingePlayer-JPanel ohne Blobs? Liegt es vielleicht daran das ich es irgendwo überschreibe? Wenn ja, wo tu ich das? Ich habe gerade keinen blassen Schimmer mehr, und morgen muss ich meinem Lehrer was zeigen, aber es funktioniert ja grad gar nix mehr:

Hier ist das Projekt, auch wenns schwer ist, bitte fummel dich mal dadurch und versuche, meinen Fehler auszuarbeiten 

```
solved
```

Die Stelle, wo ich das Bild zum JPanel hinzufüge:

```
solved
```


----------



## AntiCampeR (22. Februar 2011)

joar kann ich machen setz mich gleich ran 

//EDIT

ne compilierbare version wär schon besser gewesen^^


----------



## jannik (22. Februar 2011)

Ist kompilierbar, ich benutze das etwas seltener benutzte Tool namens Javaeditor 

Dankeschön, echt lieb, sag bescheid, wenn du was gefunden hast 

Edit:\\

Eventuell einfach import Variables.*; löschen in der Datei SinglePlayerPanel.java, war zu testzwecken, ich weiß nicht ob ich das mit hochgeladen hab 

Edit:\\

Oops, und einige pnlsingle. wurden auch noch nicht in pnlsinglearea. umgeschrieben 

Edit:\\

So, bei mir compiled es nun fehlerfrei:

```
solved
```


----------



## AntiCampeR (22. Februar 2011)

lösch ma aus SingelPlayerPanel


```
setLayout(null);
```

die größe von dem image stimmt auch noch net ;-)

und du hast da noch einige grafik bugs drinne xD


----------



## jannik (22. Februar 2011)

Danke, hat geklappt! <3

*Edit:*

Ich zeichne nun auf mein BufferedImage drauf mit 
Variables.pnlsinglearea.drawSchleim(new Color(0xF44E5D), Variables.redblob.getLocation().x, Variables.redblob.getLocation().y, Variables.redblob.getWidth(), 90);

Aber es entstehen "kleine schwarze ritzen", wie kriegt man die weg? Anderer BufferedImage Typ ?

Pic: 
	
	
	



```
solved
```


----------



## AntiCampeR (22. Februar 2011)

mach aus 

```
g2d.drawRect(x, y, hwidth, hheight);
```


```
g2d.fillRect(x, y, hwidth, hheight);
```


----------



## jannik (23. Februar 2011)

Danke, funktioniert  <3

Ich lasse nun die Blobs eine Minute auf dem Bild fahren und danach ist das Bild schön bunt.
Nun würde ich gerne wissen, wie ich berechnen kann, wer am meisten Farbe auf dem Bild gemacht hat.

*Nun zu meiner nächsten Frage:* Sollte ich Pixel für Pixel nachgucken, was für eine Farbe dort besteht und diese mit dem Schleim vergleichen (zum Beispiel If pxlcolor = new Color(0x6FEB60))?
Wenn ja, wie mach ich das? Mit zwei While-Schleifen kann man das recht gut realisieren und Reihe für Reihe durchgehen, aber wie kann ich die (Hex-)Farbe eines Pixels dann auslesen? 

Vllt gibt es ja noch andere Möglichkeiten (mit weniger Rechenaufwand), obwohl ich mir das schwer vorstellen kann gerade


----------



## AntiCampeR (24. Februar 2011)

```
int red=0,blue=0,green=0,yellow=0;
        int width=img.getWidth(); //img is dein BufferedImage
        int height=img.getHeight();
        for (int x=0;x<width;x++) {
            for (int y=0;y<height;y++) {
                switch (img.getRGB(x,y)) {
                    case 7334752 : red++; //dein farbcode als integer z.b 0x6FEB60==7334752
                        break;
                    case 7334753 : blue++; //7334753 != blau des is nur n beispiel
                        break;
                    case 7334754 : green++; //s.o.
                        break;
                    case 7334755 : yellow++; //s.o.
                        break;
                    default :
                        break;
                }
            }
        }
```


----------



## jannik (24. Februar 2011)

Danke 

Genauso hätte ich es auch gemacht, die Schleifen mein ich 

Wenn ich deinen Code nun nehme und ihn auszuführen versuche, gibt er mir mit..
JOptionPane.showMessageDialog(null, red, "Test", JOptionPane.OK_CANCEL_OPTION);
...0 aus.. Das heißt wohl, das ser nix in der Farbe findet. Ist die Farbe richtig umconvertiert von dir?

Oder liegt es an was anderem?

*Hier ist mein Projekt nochmal, das aktuelle:*

```
solved
```

*Du findest alles in der singleplayer.java unter:*

```
solved
```


*Edit:*
Wo ich schon grad dabei bin und du das Projekt so schön vor dir liegen hast: Wie greif ich auf getContentPane() aus der SinglePlayer Klasse zu ?  Wo sollte ich was am besten übergeben?


----------



## AntiCampeR (25. Februar 2011)

die integer werte sind nur beispiele...


> ```
> case 7334753 : blue++; //7334753 != blau des is nur n beispiel <<<-------
> ```


also musst du dir noch die richtigen werte ausrechnen z.b:  
	
	
	



```
new Color(0x6FEB60).getRGB();
```

zum rest heut abend mehr ich schreib gleich ne wichtige klausur deswegen hab ich jetzt leider keine zeit...


----------



## jannik (25. Februar 2011)

Edit 4:\\

Aktuelles Projekt:

```
solved
```

Und außerdem: Wieso wird mein Timer (d.h. also mein Counter obenrechts) schneller, sobald ich meinen Blob bewege? Ist mein Thread.sleep da nicht optimal, sondern ein Datums Objekt mehr sinnvoll? Aufjedenfall gehts auf schnellen PCs, auf langsamen nicht.


----------

