# 2D-Side-Scrolling-Game in Chunks splitten



## IWillTry (25. Mai 2015)

Hallo zusammen, 

Ich bin gerade neu hier im Forum, sollte ich also was falsch machen oder im falschen Bereich posten, merkt es einfach an.

Ich bin derzeit dabei, ein Side-Scrolling Spiel ähnlich zu Terraria zu programmieren.
Ich benutze dazu JavaFX.
Da die Spielwelt in der Breite unendlich sein soll, dachte ich, wäre es am sinnvollsten, sie in CHunks aufzuteilen, die dann nach Bedarf nachgeladen werden.
Die Chunks sind 2D-Arrays, welche mit ganzen Zahlen gefüllt werden und dann ausgelesen werden. DIe Zahlen entsprechen dann jeweils einem Blocktyp, welcher dann gezeichnet wird.
Der Spieler liegt auf einer Zeichenebene über der Weltebene und wird immer mittig gezeichnet.
Bewegt sich der Spieler, so rutscht also die Welt unter ihm weg.

Ein Chunk ist 256 Blöcke hoch und 50 Blöcke breit (ein Block = 16x16 Pixel). Das Anzeigefenster ist zunächst fix eingestellt auf 800x800 Pixel.

Jetzt hänge ich an der Frage fest, wie ich den Teil des Chunks berechne, der gezeichnet werden soll, also quasi ab welchem Index die Zeichenfunktion anfangen soll das Array auszulesen und zu zeichnen. 
Und wie lasse ich dann noch wenn ich mich bspw. 8px nach links bewege nur einen 8px breiten Teil des links neu generierten Chunks zeichnen?

Ich hoffe ihr versteht ungefähr, worauf ich hinausmöchte.

Vielen Dank schon mal im Voraus,

IWillTry


----------



## IWillTry (25. Mai 2015)

Hi,

mittlerweile habe ich es geschafft, dass die Chunks neu geladen werden.
Zwar crasht meine Gameloop immernoch beim Zeichnen, aber die ist erstmal Nebensache.

Nun zu meinem neuen Problem:
- die Chunks werden in Textdateien .txt gespeichert, in der Datei steht also das gesamte Int-Array, was das Chunk darstellt
- die Chunk-Dateien werden fortlaufend nummeriert, egal, ob ich links oder rechts nen neuen Chunk lade

=> wie prüfe ich nun vor dem Laden eines neuen CHunks nach, ob eine Datei mit dem gewünschten Namen bereits besteht?
==> wie lese ich die Datei zeilen/spaltenweise ein und speichere sie äquvalent in einem Array?


----------



## InfectedBytes (25. Mai 2015)

Es wäre einfacher, wenn die Namen der Chunks bereits sinnvolle Informationen enthalten würden. 
Du könntest z.B. die x-Koordinate des chunks im Namen speichern:
chunk_0.txt, chunk_-1.txt, chunk_42.txt, ...
Dadurch weißt du direkt ob der benötigte chunk bereits existiert oder nicht.
Außerdem könntest du dir überlegen, ob es vielleicht besser ist mehrere Chunks in einer Datei zu speichern, aber das muss nicht unbedingt besser sein.

Fürs laden kannst du dir ja mal den BufferedReader anschauen.


----------



## IWillTry (26. Mai 2015)

Hi InfectedBytes,

erstmal Danke für die Antwort 
Das mit den Namen habe ich gestern noch geändert. 
Die Namen werden jetzt theoretisch nach ihrem Abstand ihres Mittelpunktes zum absoluten Mittelpunkt benannt.
Allerdings wird beim zurückgehen noch nicht nach existierenden Chunks geprüft und ein falscher Name erzeugt.
Hier ein Beispiel der Bennennung:   ich gehe nach links    0 (Startchunk) -> -8 (erster linker Chunk) -> -16 (jetzt drehe ich rum und gehe nach rechts) -> 8
Da stimmt wohl was mit meiner Benennung nicht. ICh werde euch wohl im Laufe des Tages nochmal mit etwas Code zutexten, wo ich einfach nicht den logischen Fehler finde.

Aber wie finde ich nun abhängig von der Position des Spielers raus, welcher Teil welches Chunks gezeichnet werden soll, damit nicht alles gezeichnet wird?


----------



## InfectedBytes (26. Mai 2015)

Dein Fenster ist 800*800 groß und jeder Block ist 16*16 Pixel groß. Zuerst kannst du einmal berechnen aus wie vielen Blöcken das Fenster besteht: 800/16 = 50
Dein Fenster besteht also aus 50*50 Blöcken

Im Grunde sollten also links/rechts/oben/unten vom Spieler je 25 Blöcke sein. 
Wenn du nun die globalen positionen vom Spieler und chunk voneinander abziehst, kennst du den Abstand der beiden voneinander und kannst entsprechend zeichnen.
Wenn der Spieler also z.B. auf dem 10. Block eines Chunks steht, müssen noch 15 Blöcke des linken Chunks gezeichnet werden und die Blöcke 0 bis 35 vom aktuellen Chunk.


----------



## IWillTry (26. Mai 2015)

Danke für die neue Antwort!
Ja so ungefähr habe ich mir das auch gedacht, die berechneten Werte von dir sind auch bereits schon alle als Variablen bzw. Konstanten gespeichert und finden schon Anwendung woanders. Ebenso wird die Spielerposition global korrekt berechnet. Allerdings funktioniert das Zusammenspiel noch nicht so ganz, da eine ganz andere Funktion nicht läuft und dadurch das Spiel zum abstürzen bringt.

Und zwar werden von Beginn an drei Chunks geladen: currentChunk (start und spawn-chunk, x-Wert der Mitte ist 0 und chunkNumber ist auch 0), leftChunk(chunkNumber = currentChunk.chunkNumer-1), rightChunk(entsprechend +1).
Dann sobald man über den Mittelpunkt des aktuellen Chunks hinausgeht (und so ein anderer Chunk sichtbar wird) wird im sichtbar werdenden Chunk die Variable drawable auf true gesetzt und die des auf der anderen Seite liegenden Chunks auf false (in deren Abhängigkeit wird gezeichnet oder nicht). Desweiteren wird sobald man einen Chunk z.B. nach links verlässt, der aktuelle Chunk auf den linken Chunk referenziert (die anderen rutschen entsprechend nach).
Hier der Code dazu:

```
[COLOR=#cc7832]
public void [/COLOR][COLOR=#ffc66d]checkChunks[/COLOR]() {

    [COLOR=#808080]// Player ist jetzt im linken Chunk
[/COLOR][COLOR=#cc7832]if[/COLOR]([COLOR=#9876aa]p[/COLOR].getPx() < [COLOR=#9876aa]currentChunk[/COLOR].getMiddlePX() - [COLOR=#6897bb]400[/COLOR]) {
        [COLOR=#9876aa]rightChunk [/COLOR]= [COLOR=#9876aa]currentChunk[/COLOR][COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]currentChunk [/COLOR]= [COLOR=#9876aa]leftChunk[/COLOR][COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]leftChunk [/COLOR]= [COLOR=#cc7832]new [/COLOR]Chunk([COLOR=#9876aa]currentChunk[/COLOR].getMiddlePX() - [COLOR=#6897bb]800[/COLOR][COLOR=#cc7832], [/COLOR][COLOR=#9876aa]currentChunk[/COLOR].getChunkNumber() - [COLOR=#6897bb]1[/COLOR][COLOR=#cc7832], [/COLOR][COLOR=#6897bb]999[/COLOR][COLOR=#cc7832], [/COLOR][COLOR=#9876aa]currentChunk[/COLOR].getChunkNumber()[COLOR=#cc7832], [/COLOR][COLOR=#9876aa]res[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]currentChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]rightChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR]}
    [COLOR=#808080]// Player geht in den rechten Chunk
[/COLOR][COLOR=#cc7832]else if[/COLOR]([COLOR=#9876aa]p[/COLOR].getPx() > [COLOR=#9876aa]currentChunk[/COLOR].getMiddlePX() + [COLOR=#6897bb]400[/COLOR]) {
        [COLOR=#9876aa]leftChunk [/COLOR]= [COLOR=#9876aa]currentChunk[/COLOR][COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]currentChunk [/COLOR]= [COLOR=#9876aa]rightChunk[/COLOR][COLOR=#cc7832];
[/COLOR][COLOR=#9876aa] leftChunk [/COLOR]= [COLOR=#cc7832]new [/COLOR]Chunk([COLOR=#9876aa]currentChunk[/COLOR].getMiddlePX() + [COLOR=#6897bb]800[/COLOR][COLOR=#cc7832], [/COLOR][COLOR=#9876aa]currentChunk[/COLOR].getChunkNumber() + [COLOR=#6897bb]1[/COLOR][COLOR=#cc7832], [/COLOR][COLOR=#9876aa]currentChunk[/COLOR].getChunkNumber()[COLOR=#cc7832], [/COLOR][COLOR=#6897bb]999[/COLOR][COLOR=#cc7832], [/COLOR][COLOR=#9876aa]res[/COLOR])[COLOR=#cc7832];[/COLOR][COLOR=#808080]
[/COLOR][COLOR=#9876aa]currentChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]leftChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR]}
    [COLOR=#808080]// linker Chunk wird sichtbar
[/COLOR][COLOR=#cc7832]else if[/COLOR]([COLOR=#9876aa]p[/COLOR].getPx() < [COLOR=#9876aa]currentChunk[/COLOR].getMiddlePX()) {
        [COLOR=#9876aa]leftChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]rightChunk[/COLOR].setDrawable([COLOR=#cc7832]false[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]currentChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR]}
    [COLOR=#808080]// rechter Chunk wird sichtbar
[/COLOR][COLOR=#cc7832]else if[/COLOR]([COLOR=#9876aa]p[/COLOR].getPx() > [COLOR=#9876aa]currentChunk[/COLOR].getMiddlePX()) {
        [COLOR=#9876aa]rightChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]leftChunk[/COLOR].setDrawable([COLOR=#cc7832]false[/COLOR])[COLOR=#cc7832];
[/COLOR][COLOR=#9876aa]currentChunk[/COLOR].setDrawable([COLOR=#cc7832]true[/COLOR])[COLOR=#cc7832];
[/COLOR]}
}
```

So... nun wird je weiter man nach links geht immer ein neuer CHunk benannt und dieser entsprechend benannt 0 -> -1 -> -2 ->... wenn ich nun aber zurückgehe, so wird der Chunk mit der Nummer 1 geladen und das ist ja falsch.... der Fehler muss eigentlich in obigen Code liegen... nur wo?
Außerdem lädt das Programm manchmal ganz plötzlich etliche Chunks und stürzt dann ab...

Hilfe :O

[EDIT:] Fehlermeldungen kommen keine (außer eine anderweitig auftretende BufferoverfloException)


----------



## InfectedBytes (26. Mai 2015)

füge deinen code bitte nochmal ein, ohne den ganzen markup quatsch


----------



## IWillTry (26. Mai 2015)

Hier nochmal der Code:


```
public void checkChunks() {

        // Player ist jetzt im linken Chunk
        if(p.getPx() < currentChunk.getMiddlePX() - 400) {
            rightChunk = currentChunk;
            currentChunk = leftChunk;
            leftChunk = new Chunk(currentChunk.getChunkNumber() - 1, 999, currentChunk.getChunkNumber(), res);
            currentChunk.setDrawable(true);
            rightChunk.setDrawable(true);
        }
        // Player geht in den rechten Chunk
        else if(p.getPx() > currentChunk.getMiddlePX() + 400) {
            leftChunk = currentChunk;
            currentChunk = rightChunk;
            leftChunk = new Chunk(currentChunk.getChunkNumber() + 1, currentChunk.getChunkNumber(), 999, res);
             currentChunk.setDrawable(true);
            leftChunk.setDrawable(true);
        }
        // linker Chunk wird sichtbar
        else if(p.getPx() < currentChunk.getMiddlePX()) {
            leftChunk.setDrawable(true);
            rightChunk.setDrawable(false);
            currentChunk.setDrawable(true);
        }
        // rechter Chunk wird sichtbar
        else if(p.getPx() > currentChunk.getMiddlePX()) {
            rightChunk.setDrawable(true);
            leftChunk.setDrawable(false);
            currentChunk.setDrawable(true);
        }
    }
```

Die Fehler:

1. geht man mehrere Chunks nach links, so werden alle neuen linken Chunks korrekt benannt. Geht man dann jedoch einen Chunk zurück nach rechts, so wird der Chunk mit der Ziffer um 3 weiter rechts geladen/benannt.
==> Beispiel: Ich bin in Chunk -2, gehe einen Chunk nach rechts und lande in Chunk 1

2. geht man nach rechts über Chunk 2 hinaus, so lädt er endlos den Chunk 2 neu

Was ist da los?
habe bei dem Code einen Knoten im Hirn gehabt glaube ich..


----------



## InfectedBytes (26. Mai 2015)

Ist nicht unbedingt der schönste code, aber das wird schon noch^^
Ansonsten könnte heir dein problem liegen:

```
leftChunk = currentChunk;
currentChunk = rightChunk;
leftChunk = new Chunk(currentChunk.getChunkNumber() + 1, currentChunk.getChunkNumber(), 999, res);
```
Anstatt den rechten Chunk zu erzeugen, überschreibst du nochmal den linken


----------



## IWillTry (27. Mai 2015)

Jop, den Fehler habe ich schon korrigiert, habe aber den Code aus der falschen Klasse gepostet -.- Sorry.
Leider hat das den Fehler auch nicht behoben :-/
Aber ich habe durch eine neue Gameloop die Abstürze behoben.
Der Fehler mit dem Laden der Chunks besteht aber leider immernoch..


----------

