# Wand platzieren



## Lukases2 (5. Sep 2016)

Guten Abend zusammen,

ich versuche gerade eine Methode für ein Spiel zu schreiben, die ich aufrufen möchte, um an eine bestimmte Stelle meiner Welt eine Wand zu platzieren. Das hier habe ich dazu geschrieben:


```
public static void pWall(Rectangle r, int x, int y){ // Place Wall an der Stelle x, y
    r = new Rectangle();
    r.setBounds(x, y, width, height);
}
```

Ich bekomme hier aber jedes Mal eine NullPointerException.

Ich habe schon versucht, einfach jedes Mal eine neue Methode zu verwenden, also:

```
public static void pWall(int x, int y){
    rTest = new Rectangle();
    rTest.setBounds(x, y, 32, 32);
}
```


Das funktioniert zwar, verfehlt aber seinen Zweck...
Wo ist mein Denkfehler?


----------



## Bilal (5. Sep 2016)

Moin,
habe ich das richtig verstanden:
Du übergibst deiner Methode quasi eine  (bereits instanzierte) Rectangle, die nur an einer bestimmten Stelle gesetzt werden soll? 
Wenn ja, dann probier mal bitte die Methode pwall ohne die Zeile" r =newRectangle();" aus.
Kannst du auch mal den Code aus deiner main zeigen (da wo du die Methode aufrufst), danke.
LG Bilal


----------



## Lukases2 (5. Sep 2016)

> Du übergibst deiner Methode quasi eine (bereits instanzierte) Rectangle, die nur an einer bestimmten Stelle gesetzt werden soll?


Ja, hier schon. Aber nur, weil ich nicht verstehe, wie es anders gehen soll. Ich möchte eigentlich mit der Methode eine neue Wand an der Stelle platzieren. 

Meine main sieht derzeit so aus:

```
public static void main(String[] args) {

        new Player();
        new Wall();
        new Label();
        new Gui();
        new Boden();
        new Door();
        new Collision();
       
    }
```

Die Methode rufe ich derzeit noch in der Player-Klasse auf:

```
t = new Timer();
        t.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
               
                Wall.pWall(256, 256);
               
             }
        }, 0, 5);
```
Das muss sicherlich später ausgelagert werden und wäre auch jetzt schön, habe ich aber noch nicht gemacht.


----------



## Bilal (5. Sep 2016)

Wenn du eine neue Wand erzeugen willst, musst du sie stets in einer neuen Variable speichern. Ich kann jetzt die Attribute der Player Klasse nicht einsehen, aber vermute mal, dass rTest zu seinen Attributen gehört. Sonst würde der Codeabschnitt

```
public void run() {
             
                Wall.pWall(256, 256);
             
             }
```
einen Fehler ausgeben.
Mit jedem Aufruf solltest du vlt. daher eine lokale Variable einrichten und nicht auf die Attribute der Klasse zugreifen. Also:

```
public static void pWall(int x, int y){
   Rectangle  rLocal= new Rectangle();
    rLocal.setBounds(x, y, 32, 32);
}
```
Damit wird bei jedem Aufruf eine neue Rectangle erzeugt. Willst du sie aber speichern, so musst du eine Collection wie eine ArrayList<Rectangle> verwenden. Damit bleiben sie dir enthalten. Z.B.:

```
//Klassenattribute
ArrayList<Rectangle> myRectangles;

//Konstruktor
public Player()
{
  myRectangles = new ArrayList<Rectangle>();
}
...
...
public static void pWall(int x, int y){
   Rectangle  rLocal= new Rectangle();
    rLocal.setBounds(x, y, 32, 32);
    myRectangles.add(rLocal);
}
```
Hoffe, konnte helfen.

edit:
Bei der Visualisierung solltest du laut deinem Code aber nur 1 sehen, da dein Timer immer an derselben Stelle (256,256) platziert. Nimm dir mal zwei Random werte in jedem Timeraufruf, um eine Instanzierung festzustellen.


----------



## Lukases2 (6. Sep 2016)

Danke, du hast mir schon sehr geholfen!

Ich habe es genau so gemacht, wie du es hier gezeight hast und zwei Wände direkt in der Klasse Wall platziert. (Eine richtige Struktur habe ich nicht in meinen Code bringen können, stattdessen rufe ich Methoden mehr oder weniger sinnlos aus anderen Klassen heraus auf. Also nicht verwirren lassen.)


```
Player.pWall(256, 256); // Wand 1
Player.pWall(256, 288); // Wand 2
```

Eins wunder mich allerdings jetzt noch: Ich habe die beiden Wände so zeichenen müssen:

```
protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

g.drawImage(Wall.wall, Player.mr.get(0).x, Player.mr.get(0).y, 32, 32, null);
g.drawImage(Wall.wall, Player.mr.get(2).x, Player.mr.get(2).y, 32, 32, null); // mr ist die ArrayList
}
```

Wieso ist in mr.get(1) das gleiche gespeichert, wie in mr.get(0)?


----------



## Bilal (6. Sep 2016)

Ich denke mal, dass liegt daran, dass du eine static Methode aufrufst und auch keine Playerinsatz besitzt. Mir ist aufgefallen, dass du bei diesem Codeabschnitt:

```
public static void main(String[] args) {

        new Player();
        new Wall();
        new Label();
        new Gui();
        new Boden();
        new Door();
        new Collision();
   
    }
```
keine Variabeln benutzt um diese zu speichern. Also mein Vorschlag:



```
//Attribute deiner Main
Player player;
Wall wall;
...
//bis zum Rest

public static void main(String[] args) {

        //Dann hier die Instanzen speichern in Zeigern
       player =  new Player();
       wall = new Wall();
       label = new Label();
       gui =  new Gui();
       boden =  new Boden();
       door =  new Door();
       collision =  new Collision();
    }
```

Damit hast du schonmal Referenzen/Zeiger. Dir gehen damit die Elemente nicht verloren, andernfalls erzeugt sie so im Freien. Anschließend zu deiner Frage:
Nun da du keine Playerinstanz besitzt mach dein Code folgendes denke ich:
Beim Aufruf von Player.mr.get(x) erzeugt der eine neue Playerinstanz und erzeugt damit auch eine neue mr.
D.h. nach dem Abschnitt:

```
Player.pWall(256, 256); // Wand 1
Player.pWall(256, 288); // Wand 2
```

würde der zwei Playerinstanzen erzeugen und somit zwei unterschiedliche mrs. Meine Empfehlung/Vorschlag:
1) Mach das static weg
2) rufe die Methode pwall aus deiner Instanz hervor

Also deine Player Klasse:

```
public class Player {
//Klassenattribute
ArrayList<Rectangle> myRectangles;

//Konstruktor
public Player()
{
  myRectangles = new ArrayList<Rectangle>();
}
...
...
public void pWall(int x, int y){
   Rectangle  rLocal= new Rectangle();
    rLocal.setBounds(x, y, 32, 32);
    myRectangles.add(rLocal);
}
}
```

Nun der entfernter Methodenaufruf aus der main oder sonstwo:

```
player.pWall(256, 256); // Wand 1
// hier kleines "p", da ich die Instanz nehme
player.pWall(256, 288); // Wand 2
```
Somit ist sichergestellt, dass du dich auf das gleiche Element beziehst. Damit wird deine mr richtig aufgefüllt.


----------

