# Lösungsansatz in 2D Welt über die Border hinaus



## c_sidi90 (7. Jul 2011)

Hallo leute, ich befass mich momentan nebenbei ein wenig mit Spieleprogrammierung in Java. Nachdem ich schon einige Spiele a la SpaceInvaders, CarRacing etc programmiert hab, möchte ich nun eine Art Abklatsch von Zeldra programmieren. Wie ihr alle wisst, läuft Link durch eine riesige Welt. Ich denk mal diese Welten setzen sich aus mehreren Bilder zusammen und werden beim Überlauf zur Framegrenze neu geladen.

Doch was ist der beste Lösungsansatz, wenn z.B. der Spieler über den Rand hinaus läuft, und die map (das Bild) sich quasi verschieben soll, sodass der Spieler eine neue Area betritt? Geht das überhaupt wenn der Frame ca 800,600 ist und das Bild 3000,3000 oder muss ich die Welt in mehrere Teile zerschneiden die genauso groß sind wie der GameFrame?

Lg


----------



## Evil-Devil (7. Jul 2011)

Du könntest deine Spielwelt ja scrollen. Selbst wenn deine Spielwelt 3000x3000 Bildpunkte groß ist, zeigst du letzten Endes nur einen Ausschnitt aus dieser an. Deine Darstellung der Welt muss also immer wissen wo sie sich auf deiner 3k*3k großen Welt befindet und was sie zeigt.

Bei diesem Seiten Blättern Effekt kannst du entweder das jeweilige Bild vorher neu laden oder im Speicher vorhalten.
Wenn man sich Glitch Vids zu Zelda anschaut kann man sehr schön sehen wie die einzelnen Bereiche miteinander verbunden sind ^^
YouTube - ‪Zelda: A Link to the Past glitch run in 3 minutes 10 seconds‬&rlm;


----------



## Cola_Colin (7. Jul 2011)

Auf deinem 800*600 Frame wirst du deine 3000*3000 Welt wohl kaum darstellen können, ohne sie zu verkleinern und auch das Seitenverhältnis zu stretchen.


----------



## Marco13 (7. Jul 2011)

Unabhängig davon klingt ein 3000x3000-Bild (bzw. die Notwendigkeit, die Welt in EINEM Riesen-Bild speichern zu müssen) nicht besonders sinnvoll.


----------



## c_sidi90 (7. Jul 2011)

Darstellen kann ich sie schon bei 3k x 3k nur wird nicht alles sichtbar. So wie Evil-Devil das verstanden, war schon richtig. Kann ich n Scrollpane nehmen und die Bar visible(false) setzen oder wie koennte man das lösen.


----------



## Evil-Devil (7. Jul 2011)

Am besten direkt den Ausschnitt painten. Ich weiß nicht wie genau ein Panel das in einem Scrollpane liegt optimiert ist, da ich mit sowas in der Richtung noch nichts gemacht habe, aber ich bezweifel das es performant ist.

Besser direkt auf das Canvas malen


----------



## Marco13 (7. Jul 2011)

Ein Scrollpane trickst da schon gewaltig rum. Genaugenommen könnte es sogar sein, dass ein Scrollpane beim reinen Scrollen und "neuzeichnen" des dann sichtbaren Bereiches schneller ist, als "per Hand" einen neuen Bildausschnitt zu malen: Wenn im JViewport der blit scroll mode gesetzt ist (AFAIR ist das default) dann blittet er, was im Idealfall heißt dass das alles sehr hardwarenah gemacht wird und nicht mal mehr irgendwelcher Speicher hin- und her geschaufelt werden muss. Aber erstens sollte man sich da nicht drauf verlassen, und zweitens wird die Größe der Welt duch ein einzelnes Bild ja schon beschränkt. Wenn 3000x3000 garantiert nie überschritten wird, mag es vielleicht OK sein, aber trotzdem sind so große Bilder unhandlich...


----------



## c_sidi90 (8. Jul 2011)

Also sollte ich lieber die levelabschnitte splitten und in ein array fuellen undiese bilder bei grenzueberschreitung zeichnen lassen? Sorry fuer re htschreibfehler poste grad vom handy


----------



## Kr0e (8. Jul 2011)

Das stimmt. Man kann es ähnlich performant machen, wenn man diesen effekt von Hand nachahmt, wäre dann allerdings die Frage wieso man das tun sollte...

Einfach Graphics2D.copyArea verwenden, um den bereits gerenderten Teil zu kopieren und nur den Teil neuzeichnen, der sichtbar wird.

Aber ich vermute auch, dass das Scrollpane da 1. handlicher ist un 2. vlt sogar noch weitergehend optimiert ist...

Ansich würde ich auch ein Blocksystem vorschlagen. Also z.b. immer 1024*1024 Pixel bilder und davon dann soviel wie du willst aneinander heften.


----------



## Volvagia (8. Jul 2011)

Warum überhaupt Bilder? Das ist wahrscheinlich sehr viel schwerer zu bearbeiten, und hat rein garnichts mit OOP zu tun. Zumindest in A Link to the Past (seit jeher das Beste Zelda) hat jedes Objekt außer der reine Boden und Blümchen irgend eine Aktion mit Link. Gras "wackelt" beim durchlaufen, Büsche halten auf und können zerhackt werden, zusammenhängende Bäume halten auf, freistehende Bäume können angerempelt werden wodurch bei bestimmten Items spawnen, freistehende Bäume mit Augen in der Schattenwelt werfen beim Berühren der "Nase" Bomben und sprechen, freistehende Klippen können herunter gesprungen werden usw.

Deshalb würde ich alle Dinge außer den in der Oberwelt typischen grünen oder braunen Boden als Objekte definieren.

Die Welt würde ich auf jeden Fall aufteilen. Dabei würde ich angrenzende Gebiete im Hintergrund per Thread laden. Die Maps in ALttP sind nicht alle gleich groß. Deshalb wird beim Bewegen geprüft, ob sich der sichtbare Bereich in der Mitte der Karte aufhält. Wenn ja, werden einfach alle Objekte in die Scrollgegenrichtung bewegt, wenn nicht bewegt sich eben Link. Zum Scrollen wird danach einfach das Repaint-Kommando mit der neuen und der alten Position abgefeuert, der Repaintmanager kann das ja zusammenfassen. Wenn Link gegen den Rand läuft, würde ich einfach die nächste Karte daran darstellen, und beide zusammen gegen die Scrollrichtung bewegen. Dazu Link noch ein paar Schritte laufen lassen, damit er am Ende auch auf der nächsten Karte steht. Danach die Alte einfach raushauen und alle Entilities starten etc.

Ich kann mir nicht vorstellen, dass dafür irgendwelche Spezialmethoden gebraucht werden. Ein JScrollPane ist eine interessante Idee, aber ich schätze vollkommen unnötig.


btw. was macht copyArea? Laut Javadoc kopiert es einen Bereich, was ja schon der Name sagt. Aber ich verstehe nicht wozu dx/y gebraucht wird, die Distanz wird ja per width/height angegeben. Und wo landet der kopierte Bereich dann?


----------



## Kr0e (8. Jul 2011)

-> Graphics g = b.getGraphics();
g.copyArea(x,y,w,h,dx,dy); ? 

dx und dy bilden zusammen den Verschiebungsvektor...

Du definierst also quasi nen Berecih im bild und sagst dann, um wieviel der verschoben wird. Das ist eine verdammt schnelle Funktion, auch bei riesigen bildern, da hier hardware-beschleunigt gearbeitet wird.


----------

