# Zugriff auf den Spieler



## Sogomn (29. Nov 2014)

Ich bin momentan an einem kleinen Projekt dran. Es ist (bzw. soll werden) ein top-down-shooter, bei dem man gegen Horden von Zombies spielt.
Jetzt bin ich gerade bei den Zombies und hab' dazu eine kleine Stilfrage. Was ist die beste möglichkeit, der Zombie-Klasse zugriff auf den Spieler (also die Position) zu geben?
Ich habe eine Klasse, die mir die Spielobjekte "managed" - also updaten, zeichnen, hinzufügen, entfernen. Auf diese haben alle Klassen Zugriff, weil statisch.
Ich könnte also in der Zombie-Klasse durch alle Objekte laufen und den Spieler 'rauspicken; ich weiß nur nicht, ob das wirklich die beste Lösung ist.
Hinzugefügt werden die Spielobjekte durch eine Klasse, die Pixel aus einem Bild liest und die Objekte aus den Farben "parst" (sehr provisorisch, ich weiß).

MFG


----------



## Gucky (29. Nov 2014)

Du hast wahrscheinlich eine zentrale Klasse, in der alle Fäden zusammenlaufen. Dann erstellst du in der Zombieklasse eine statische Methode setSpielerPosition(WIE AUCH IMMER DU DIE POSITION SPEICHERST), die die Position des Spielers in eine statische Variable schreibt, auf die alle Zombies zugreifen.
Die Position bekommt die Hauptklasse vom Spieler. Z.B. spieler.getPos();

oder wie speicherst du den Spieler?


Die Methode, das du erst alles zeichnest und danach parst halte ich für zu umständlich. Oder habe ich dich falsch verstanden?


----------



## Ruzmanz (29. Nov 2014)

Ich möchte dir da nicht zu viel rein reden ... das statische Zeug ist ein nogo. Das führt dazu, dass du immer und immer mehr statistische Methoden reinpackst. (Diese Aussage bezieht sich übrigens nur auf diese Situation, da static nicht prinzipell immer falsch ist)

- "Game" hat eine "Map".
- Auf einer "Map" sind "SpielerAvatare" und "Zombies".
- "Zombies" werden von "Game" in der "Map" angelgegt. Jeder "Zombie" kennt die "Map". Somit haben Zombies aus alle Spielelemente (z.B. den SpielerAvatar", "Gebäude", usw. Zugriff).
- Neben der "Map" hat "Game" z.B. noch "GameMenue", "Inventar". Beim rendern werden diese in der Reihenfolge "Game", "Inventar", "GameMenue" aufgerufen ...
- Abgesehen davon gibt es einen "Spieler". Jedem "Spieler" ist ein "SpielerAvatar", "Inventar", usw. zugeordnet.

Sodass du so eine Verbindung hast:
Game.createZombie() ... new Zombie(map);
Game.updateZombie() ... map.getSpielerAvatar();

Sofern es mehrere Spieler sind, kannst du dir eine nette Datenstruktur überlegen (z.B. Tree), welche die Spieler nach X/Y-Koordinaten sotiert, sodass ein Zombie den am nahe gelegensten Spieler schneller findet.


----------



## Sogomn (29. Nov 2014)

Danke für die Antworten!

@Ruzmanz:
Ich denke, dass es schon sinn macht, die Klasse statisch zu machen, die sich um die Objekte kümmert. Ich bin mir ja sicher, dass ich im gesamten Programm nur maximal 1 Instanz brauche. Klar kann ich die Klasse einfach immer weiter übergeben, das läuft im Endeffekt doch aber auf dieselbe Struktur hinaus.


Dass ich die Position in der Zombieklasse speicher' ist eine gute Idee, daran hab' ich noch garnicht gedacht. Ich guck' mal, wie das funktioniert.


----------



## Ruzmanz (30. Nov 2014)

Jein. Wenn es auf das selbe Konzept rauslaufen würde, hättest du z.B. kein Problem.


```
public class Zombie {
  Map map = Map.getInstance();

  public void update() {
    Player player = map.getPlayer();
    // ... updateDirection ...
  }
}
```


----------



## Sogomn (30. Nov 2014)

Also ich habe eine abstrakte Klasse _Level_, von der ich verschiedene Level ableite. Mithilfe eines _LevelManagers_ kann ich das Level wechseln. Dabei werden alle Objekte aus dem _ObjectHandler_ entfernt.
Ich würde gerne deine Idee mit der Map auf mein Level übertragen, sodass ich jedem Spielobjekt, dass erzeugt wird, das Level übergebe und ihm so Zugriff auf alle Elemente des momentanen Levels gebe.
Jetzt bleibt nur noch die Frage, wie ich dann die Spielobjekte update und zeichne. Sollte ich das im jeweiligen Level machen oder die Extraklasse beibehalten?


----------



## Ruzmanz (30. Nov 2014)

Eine "Map" ist für mich nichts anderes als ein "Level". Packe in dein Level die Methoden update, render, etc. und alle Objekte, die nur in diesem Level zur Verfügung stehen ... wie gesagt, beim statischen Konzept packst du alles in einer Godlike-Klasse. Allein der Name "ObjectHandler" bestätigt die Annahme. Der ObjectHandler sollte vom Prinzip her nichts anderes machen als ein "GameClient". Wenn das "Level" fertig ist, kannst du das Object einfach wegwerfen. Informationen, die global Levelunabhängig sind kommen da sowieso nicht rein.


```
public class ObjectHandler {
  private Level level;
  private ProfileGlobal player;
  private Menu menu;

  public void update() {
    if(level.allZombiesDead()) { // nächstes Level
      level = new MyLevel();
      // Z.B. Spielername / Skills beibehalten; Waffen / Position / Aussehen / etc. neu initialisieren.
      level.init(player);
    }
    if(Key == ESC) {
      System.exit(0);
    }
    player.update();
    level.update();
  }

  public void render() {
    level.render();
    if(isPause) {
      menu.render();
    }
  }  
}

public class MyLevel extends Level {
  private Zombie zombie;
  private PlayerInagame player;

  private void initLevel(Player player) {
    zombie = new Zombie(this);
    player.setAvatar(this.player);
  }

  public void update() {
    zombie.update();
    player.update();
  }

  public void render() {
    zombie.render;
  }
}

public class Zombie {
  private Level level;

  public Zombie(Level level) {
    this.level = level;
  }

  public void update() {
    PlayerInGame player = level.getPlayer();
    if(player.getPosition()== zombie.getPosition()) {
      player.isDead(true);
    } if(player.getPosition()) {
      diretion = player.getPosition()-zombie.getPosition();
    }
  }
}

public class ProfileGlobal {
  private PlayerInagame playerInGame = null;
  private int SkillLevel;
}

public class PlayerInGame {
  private int posX;
  private int posY;
  private Weapon weapon;
  private color color;
  private int hp;

  private void update() {
    if(Key == UP) {
      setDirectionY(1);
    }
    if(Key == ENTER) {
      shoot();
    }
  }
}
```


----------



## Sogomn (30. Nov 2014)

Okay, danke! Dann lass' ich den _ObjectHandler_ ganz weg.
Nochmal eine ganz andere Frage, nur um sicher zu sein: Wenn es keine Referenz mehr auf ein Objekt gibt, dann holt es der GarbageCollector ab, oder? Ich muss das nicht erst auf "null" setzen?


----------



## Gucky (30. Nov 2014)

Auch in sich geschlossene "Referenzenkomplexe" werden vom GC freigegeben.
Wenn du also A->B->C->D hast, wobei -> für "referenziert" steht und du A->B zu A->null änderst, werden B, C und D freigegeben, so es nicht anderweitig Referenzen gibt.


----------



## Sogomn (30. Nov 2014)

Okay, super, danke!


----------



## Tobse (11. Jan 2015)

Um nochmal was von meinem Senf hierzu dazulassen:



			
				Sogomn hat gesagt.:
			
		

> @Ruzmanz:
> Ich denke, dass es schon sinn macht, die Klasse statisch zu machen, die sich um die Objekte kümmert. Ich bin mir ja sicher, dass ich im gesamten Programm nur maximal 1 Instanz brauche. Klar kann ich die Klasse einfach immer weiter übergeben, das läuft im Endeffekt doch aber auf dieselbe Struktur hinaus.



Das ist richtig. Aber in so einem Fall macht man nicht alles Static sondern man macht ein Singleton:


```
class Singleton
{
    private static Singleton instance;

    public static Singleton getInstance()
    {
        if (instance == null)
        {
            instance = new Singleton();
        }
        return instance;
    }
    private Singelton() {...}
}
```

bzw. noch einfacher


```
class Singleton
{
     public static final Singleton INSTANCE = new Singleton();
     private Singleton() {...}
}
```

Im restlichen Code schreibst du dann auch *nicht* Game.getInstance().??? anstatt Game.??? sondern jedes Objekt erält zugriff auf sein Game (z.B: über Map#getGame) und du schreibst dann (z.B: im Zombie) this.map.getGame().??? oder this.game.???

Wenn du dann nämlich mehr als ein Spiel pro JVM rechnen willst, brauchst du nur die Singleton-Eigenschaft zu entfernen.


----------

