Tile-based Rendering & Camera Transformation
1. Grundprinzip & Koordinaten-Transformation Um Kacheln (Tiles) und Entitäten auf dem Bildschirm korrekt darzustellen, müssen deren statische oder dynamische Koordinaten aus dem World Space (Weltkarte) in den Screen Space (Bildschirmfenster) umgerechnet werden. - World Space: Die tatsächliche Position auf der gesamten Map in Pixeln (z. B. 0 . . . 1056 px) - Screen Space: Die tatsächliche Zeichenposition auf dem JPanel/Fenster (z. B. 0 . . . 800 px) Die Transformationsformel Für alle Spielobjekte und Map-Kacheln gilt einheitlich: screenX = worldX} - cameraWorldX screenY = worldY - cameraWorldY (Hinweis: cameraWorldX/Y repräsentiert die obere linke Ecke des aktuellen Kamera-Sichtfelds). 2. Ablauf im TileManager Der TileManager liest das zweidimensionale Map-Array (tiles[col][row]) aus und berechnet die Zeichnungspositions-Koordinaten rasterbasiert. (Siehe Code-Beispiel) Iteration & Positionsberechnung: 1. Array-Durchlauf: Äußere Schleife für die Zeilen (row), innere Schleife für die Spalten (col). 2. Welt-Koordinate: - worldX = col x tileSize - worldY = row x tileSize 3. Bildschirm-Koordinate: Transformation durch Subtraktion der Kamera-Koordinaten. 4. Rendering: Zeichenbefehl über Graphics2D.fillRect(screenX, screenY, tileSize, tileSize). 3. Entkopplung im RenderSystem Das RenderSystem steuert den gesamten Zeichenprozess. Es holt sich die CameraComponent aus der World und stellt sicher, dass sowohl die Kacheln als auch alle sichtbaren Spielobjekte denselben Kamera-Offset nutzen. - Vermeidung von Doppel-Offsets: Es wird kein zusätzlicher Bildschirmmitte-Offset (screenCenterX/Y) in die Transformation eingerechnet, da die relative Ausrichtung bereits durch die Kamera-Clamping-Logik im CameraSystem abgedeckt ist. - Einheitlicher Zeichenbefehl: Auch Entitäten werden strikt an ihren berechneten Bildschirmkoordinaten (screenX, screenY) gerendert, nicht an ihren Weltkoordinaten.
Lumina: Fate of the Fallen
World Space (Map) Screen Space (JPanel) +-----------------------+ +------------------+ | (col * tileSize) | | (screenX,screenY)| | worldX / worldY | - cameraWorldX/Y = | fillRect() | +-----------------------+ +------------------+