# Vererbbarer GameLoop für Engine



## Roovy (4. Sep 2016)

Hallo,
ich habe bereits recherchiert aber ich kann mir einfach nicht helfen. Ich finde nichts spezifisches was auf mein Problem zutrifft und nicht einmal bei anderen Engines abzuschauen hat mir nicht geholfen zu einer Lösung zu kommen (die ich verstehe und so unterstütze).
Ich möchte eine Java-Datei (ich schätzte Interface?) für eine Engine erzeugen, die einige Methoden enthält. Bsp.: Update. Diese Methode soll dann via. extends in ein eigenes Programm eingefügt werden können. Dabei übergibt man beispielsweise noch die Updatefrequenz an Update und schreibt alles in diesen Update block, während der GameLoop in der Superklasse den Rest erledigt (in der Frequenz zu bleiben etc.).

Ich bin sehr verbunden für jegliche Hilfe. (Bitte versucht es zu erklären. Die Grundlagen freilich nicht.)


----------



## Java20134 (5. Sep 2016)

Also an deiner Stelle würde ich eine Klasse machen, die abstract ist. Und dann kannst du auch die Vererbung (extends) anwenden. Aber Interfaces implementierst du mit dem Schlüsselwort implements.
Die Klasse könnte so aussehen:

```
public abstract class Figure {
 protected int x, y, width, height;

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

public Figure(int x, int y, int size){
  this(x, y, width, height);
}

 public abstract void update();
 public abstract void draw();
}
```
Denn Namen der Klasse kannst du noch ändern, da ich nicht genau weiß für was du die Klasse brauchst. Für Figuren würde ich die Klasse einfach "Figure" nennen oder für ein Spiel einfach "Game"?


----------



## Roovy (6. Sep 2016)

Okay. Danke.
Wie genau müsste ich denn jetzt update und draw in einer Schleife (Engine-intern, damit der User das nicht machen muss) aufrufen? (Nur kurzes Beispiel. Wie ich sinnvollen GameLoop hinkriege weiß ich.)


----------



## Bilal (6. Sep 2016)

Moin,
zu deiner letzten Frage:
Annahme: TestFigure ist eine Unterklasse von Figure, wobei die Methode draw bspw. einen Parameter vom Typ Graphics erwarten würde.:

```
public class TestFigure extends Figure{
protected int x, y, width, height;
protected Image image =  new Image(<"irgendein Bild">);


public Figure(int x, int y, int width, int height){
super(x,y,width,height);

}


public void update()
{
   //tun sie dinge
}
public void draw(Graphics g)
{
   g.draw(image,x,y)
}
}
```

In jedem Durchgang könnte der Aufruf in deiner App folgendermaßen aussehen:

```
// perform step
                if((float)deltaTime/1000000000f >= 0.01)
                {
                    engine.update();       
                }
```
In deiner Engine Klasse könnte es dann nach Java20134 folgendermaßen aussehen:

```
public class GameEngine{

//Attribute
private ArrayList<Figure> figures;
private Graphics g;
...
...
//Konstruktor
public GameEngine()
{
  //wichtiger Erstkram
  init();
  //nun, erzeuge deine gewollten Elemente
  figures = new ArrayList<Figure>();
  Figure fig1 = new TestFigure(0,0,10,20);
  figures.add(fig1);
}

/**
     * /** Updates the game
     *
     * @param deltaTime
     *            delta time
     **/
    public void update()
    {
        //hier bspw. eine update + draw nur für deine Figuren.
       for(Figure f: figures)      
         {   
              f.update();
              f.draw(g);
         }
    }

}
```

Bei Bedarf erzeugst du dir noch andere Elemente und delegierst deine Updates an diese.
Hoffe, konnte helfen.
LG Bilal


----------



## Roovy (8. Sep 2016)

Nun, ich verstehe den Ansatz aber er hilf mir immernoch nicht direkt weiter. Ich kann nicht auf die vererbte Methode zugreifen. Die Schleife soll ja engineintern sein, die Methoden draw/update vererbt, sodass der Endnutzer nur diese beiden hat.
Er startet bei mir mit der Erstellung eines JFrames (über eine Engine-Klasse, die es schneller macht mit weniger Befehlen ein JFrame aufzusetzen) und startet dann quasi den JFrame mit einer Methode, die den JFrame sichbar macht etc. An dieser Stelle möchte ich dann auch den GameLoop starten der dann erst init() aufruft, und dann immerwieder draw() und render(). Doch diese beiden sind ja in der vererbten Klasse, der Loop hingegen in der Parent-Klasse.


----------



## mrBrown (8. Sep 2016)

Wer soll da von wem erben?

Generell kann man schon auf vererbte Methoden zugreifen, warum sollte das nicht gehen?


----------



## Roovy (8. Sep 2016)

Man eine Klasse, nennen wir sie Window, diese erstellt ein JFrame. Eine zweite Klasse, GameLogic, enthält die abstrakten Methoden init, update, draw und eine Funktion, die den GameLoop beinhaltet. Von dieser erbt der Nutzer.
Hat der nutzer nun ein neues Window erstellt und aufgesetzt und ruft die custom Methode start() auf, wird der JFrame initialisiert und gleichzeitig auf die start-Methode in GameLogic zugegriffen. Der Loop soll dann auf update und draw in der Tochterklasse(?) zugreifen.


----------



## mrBrown (8. Sep 2016)

Das klappt problemlos, der Nutzer muss Window dann nur seine Instanz von GameLogic übergeben (wobei man da vllt noch über Trennung nach MVC nachdenken sollte).

In GameLogic kann man auch auf die als abstrakt deklarierten Methoden zugreifen, in der jeweiligen Instanz sind sie ja nicht mehr abstrakt.


----------



## Roovy (8. Sep 2016)

Also zum Beispiel so:

```
Window w = new Window()
//set-up
w.start(w)
```
?
Und GameLogic dann:

```
void startGameLogic(Window window) {
  w.init();
  while(true){ //kurz vereinfacht
    w.update();
    w.draw();
  }
}
```
?


----------



## mrBrown (8. Sep 2016)

Warum sollte man dem window noch mal sich selbst übergeben?
GameLogic soll doch die Funktionen nicht auf dem Fenster, sondern auf sich selbst aufrufen?


----------



## Roovy (8. Sep 2016)

Und wie tuhe ich das?


----------



## mrBrown (8. Sep 2016)

Funktionen auf sich selbst aufrufen?
Einfach die Funktion mit this aufrufen (oder die Referenz ganz weglassen)


----------



## Roovy (9. Sep 2016)

Nein nein. Ich meine die aus Engine vererbte Methode render() in der Methode startGameLogic() ind der Klasse Engine.


----------



## mrBrown (9. Sep 2016)

Wo kommt denn plötzlich die Klasse Engine und die Methode render her?


----------



## Sogomn (11. Sep 2016)

Ich hab' das in meiner Bibltiothek, die ich für Spiele benutze, so gelöst, dass man der "Screen"-Klasse Listener hinzufügen kann und der Aufruf von "draw" (oder "render" - wie auch immer) die gleichnamige Methode aller Listener aufruft. Die Listener werden durch ein Interface definiert.


```
final class Screen {

    //...

    void draw() {
        final Graphics2D g = createScreenGraphics();

        notifyListeners(listener -> {
            listener.draw(g);
        });
    }

}
```


```
interface Listener {

    void draw(final Graphics2D g);

}
```


----------

