ECS Datenfluss
1. Systemübersicht & Sequenzieller Datenfluss Die Verarbeitung im Game Loop erfolgt strikt sequenziell in jedem Frame: InbutSystem -> MovementSystem -> CameraSystem -> RenderSystem - InputSystem Prüft Tastatureingaben (über KeyHandler) und setzt die Richtungsvektoren dx und dy in der VelocityComponent der Entität. - MovementSystem Liest VelocityComponent, normalisiert diagonale Bewegungen und aktualisiert die Welt-Koordinaten (worldX, worldY) in der PositionComponent unter Berücksichtigung von speed und deltaTime. - CameraSystem Liest die PositionComponent des Fokus-Objekts (Spieler). Berechnet die Soll-Position der oberen linken Kamera-Ecke in der Welt (cameraWorldX, cameraWorldY). Wichtig: Erreichen diese Werte die Map-Ränder, greift das Clamping und friert die Koordinaten auf die Grenzen ein (0 bis \text{maxWorld} - \text{screenSize}). - RenderSystem Liest die PositionComponent aller zu zeichnenden Entitäten sowie die geklemmte CameraComponent. Transformiert die Welt-Koordinaten in Bildschirm-Koordinaten (\text{screenX} = \text{worldX} - \text{cameraWorldX}) und rendert Map-Tiles und Entitäten auf das JPanel. 2. Mathematisches Modell (Kamera & Clamping) Allgemeine Formeln - Soll-Kameraposition (Top-Left-Origin): cameraWorldX = playerWorldX - (screenWidth/2) + (tileSize/2) cameraWorldY = playerWorldY - (screenHeight/2) + (tileSize/2) - geklemmte Kameraposition (Clamping): cameraWorldX = Math.max(0, Math.min(cameraWorldX, worldWidth-screenWidth)) cameraWorldY = Math.max(0, Math.min(cameraWorldY, worldHeight-screenHeight)) - Transformation in Bildschirmkoordinaten (Screen Space): playerScreenX = playerWorldX - cameraWorldX playerScreenY = playerWorldY - cameraWorldY
Lumina: Fate of the Fallen
Beispielszenarien
- Rahmenbedingungen:
- Map-Größe: 2000 x 1000 px
- Bildschirm-Größe: 800 x 600 px
Szenario A: Spieler in der Map-Mitte
- Spieler-Position: (1000, 500) px
- Kamera-Soll:
cameraWorldX = 1000 - 400 = 600 px
cameraWorldY = 500 - 300 = 200 px
- Clamping: Werte liegen innerhalb der Grenzen [0, 1200] bzw. [0, 400] -> keine Korrektur.
- Screen-Position:
playerScreenX = 1000 - 600 = 400 px
playerScreenY = 500 - 200 = 300 px
- Ergebnis: Spieler ist exakt in der Bildschirmmitte.
Szenario B: Bewegung in der Map-Mitte
- Spieler-Position verändert sich auf: (500, 500) px
- Kamera-Soll:
cameraWorldX = 500 - 400 = 100 px
cameraWorldY} = 500 - 300 = 200 px
- Clamping: Keine Korrektur nötig.
- Screen-Position:
playerScreenX = 500 - 100 = 400 px
playerScreenY} = 500 - 200 = 300 px
- Ergebnis: Welt bewegt sich unter dem Spieler durch, Spieler bleibt visuell zentriert.
Szenario C: Erreichen des linken oberen Randes (Clamping aktiv)
- Spieler-Position verändert sich auf: (50, 100) px
Kamera-Soll:
cameraWorldX = 50 - 400 = -350 px
cameraWorldY} = 100 - 300 = -200 px
- Clamping greift ein: Da Werte < 0 sind, wird die Kamera bei
cameraWorldX_clamped = 0 und
cameraWorldY_clamped = 0 fixiert.
- Screen-Position:
playerScreenX = 50 - 0 = 50 px
playerScreenY = 100 - 0 = 100 px
- Ergebnis: Die Kamera hält am Rand der Welt an. Der Spieler löst sich visuell aus der Bildschirmmitte und wandert an den linken oberen Rand des Fensters.