Parallaxe - Tiefeneindruck bewegter Objekte

Wie ein scrollender Hintergrund realisiert wird, ist beim Hintergrund-Scrolling beschrieben, und bei Transparente Farben ist erklärt, wie man eine Szene in DirectDraw zusammenstellen kann.

Die Simulation der Überlappung von Objekten ist aber leider nur das halbe Bild. Andere Effekte kommen noch ins Spiel, die besonders deutlich werden, wenn die Szene in Bewegung gesetzt wird.

Wenn wir uns bewegen, scheinen sich nahegelegene Objekte in die entgegengesetzte Richtung zu bewegen. Dieses Phänomen wird als relative Bewegung bezeichnet. Nicht die Objekte bewegen sich, sondern wir. Wenn wir aber Objekte betrachten, die weiter weg sind, passiert etwas Interessantes - diese scheinen sich nicht so schnell zu bewegen. Betrachten Sie das folgende Abbildung, die die gleiche Szene aus verschiedenen Blickwinkeln zeigt.

Beachten Sie, dass sich der Baum deutlich weiter bewegt hat als das Haus im Hintergrund. Dieser Effekt wird als Parallaxe bezeichnet und ist der Schlüssel zu unserer Wahrnehmung von Tiefe in einer bewegten Szene.

Um dies in einem Programm einsetzen zu können, wird für jede Ebene ein Fließkommawert verwendet, der mit der Bewegung der Szene multipliziert wird. Höhere Werte werden für die Ebenen näher am Betrachter verwendet, wodurch diese sich schneller bewegen, als die Objekte im Hintergrund.

Das Parallaxe-Beispiel basiert auf dem Beispiel aus dem Hintergrund-Scrolling. Wieder ist es eine Stadtszene, nun jedoch in mehrere Ebenen für einen 3D-Effekt aufgeteilt. Zusätzlich gibt es noch ein Taxi, das sich unabhängig von der Position des Betrachtes durch die Szene bewegt.

Das Beispiel benutzt ein Array für die Ebenen mit folgender Struktur.

'Struktur für Ebenen definieren
Type strcLAYER
  surf As DirectDrawSurface7
  blit_flags As Long
  start_x As Long
  start_y As Long
  interval As Long
  parallax As Double
  lwidth As Long
  lheight As Long
End Type
Public Layers(3) As strcLAYER

surf - Enthält die Oberfläche mit dem Bild für diese Ebene.
 
blit_flags
- Enthält die Bits für BltFast() einschließlich der Flags für die Farbmaskierung, falls erforderlich.
 
start_x
- Definiert die linke Startposition des Bildes auf dieser Ebene. Bilder werden alle interval Pixel
nach rechts wiederholt.
 
start_y
- Bestimmt die Y-Koordinate für alle Kopien des Bildes.
 
interval
- Definiert den Abstand auf der X-Achse zwischen den Kopien dieses Bildes.
 
parallax
- Definiert den Parallaxfaktor für diese Ebene. Dies ist ein Multiplikator für die Scrollrate, die über die Tastatur eingestellt wird.
 
lwidth
- Definiert die Oberflächenbreite des Quellbildes.
 
lheight
- Definiert die Oberflächenhöhe des Quellbildes.
 

Dieses Array wird beim Laden der Bilder zum Programmstart gefüllt und beim Durchlauf der Ebenen in der Darstellungsschleife verwendet. Die Ebenen bekommen unterschiedlich Parallaxe-Werte, so bewegt sich der Hintergrund langsamer und der Vordergrund schneller.

Wie Sie Bitmaps in DirectDraw laden können, wird bei Bitmaps laden und anzeigen ausführlich beschrieben, wobei das Beispiel auch die Farbmaskierung aus Transparente Farben verwendet.

Nun kommt aber endlich die 3D-Magie! Das Tastaturereignis legt die Scrollingposition in x_pos (siehe Code-Beispiel) fest, die Position der einzelnen Ebenen wird jedoch über deren Parallaxefaktor bestimmt.

Zur Bestimmung der Position einer Ebene wird die normale Scrollingposition mit dem Parallaxefaktor der Ebene multipliziert (siehe Code-Beispiel). Als nächstes wird die Position der ersten Instanz des Objekts in der Ebene bestimmt und alle Kopien durchlaufen, bis alle gefunden wurden, die innerhalb des sichtbaren Bereichs liegen. Wie unter Bitmaps zu- und ausschneiden, Animation gezeigt, wird das Objekt ggf. geclippt.

'Schleife über die Ebenen
For i = 0 To NUM_LAYERS
  'Parallaxe-Position der Ebene berechnen
  screen_pos = x_pos * Layers(i).parallax
  'Position des ersten Objekts setzen
  obj_pos = Layers(i).start_x
  'Schleife bis zum Rand des Bildes
  Do While (obj_pos < (screen_pos + 640))
    'Ist das Objekt auf dem Schirm?
    If (obj_pos + Layers(i).lwidth) >= screen_pos Then
      'Ja, Abstand zum linken Rand des Bildes berechnen
      screen_x = obj_pos - screen_pos
      'Objekt clippen wenn notwendig
      srcrect.Left = 0
      srcrect.Top = 0
      srcrect.Right = Layers(i).lwidth
      srcrect.Bottom = Layers(i).lheight
      If screen_x < 0 Then
        srcrect.Left = srcrect.Left - screen_x
        screen_x = 0
      ElseIf (screen_x + srcrect.Right) > 640 Then
        srcrect.Right = 640 - screen_x
      End If
      'Objekt auf den Bildschirm zeichnen
      BackBuffer.BltFast screen_x, Layers(i).start_y, _
          Layers(i).surf, srcrect, _
          Layers(i).blit_flags
    End If
    'Erhöhen zur nächsten Objektposition
    obj_pos = obj_pos + Layers(i).interval
  Loop
Next i

Zum Schluss wird noch das Taxi gezeichnet, und kommt deshalb erst jetzt, weil es das naheste Objekt in der Szene ist. Einen abschließenden Rahmen bildet noch eine Benutzeroberfläche, die über die Szene gezeichnet wird.

'Bildposition für Taxiparallaxe berechnen
screen_pos = x_pos * 3
'Ist das Taxi auf dem Bilschirm?
If (taxi_pos + Taxi_Width) > screen_pos And _
    taxi_pos < (screen_pos + 640) Then
  'Ja, berechne den Abstand zum linken Bildschirmrand
  screen_x = taxi_pos - screen_pos
  'Objekt clippen, wenn notwendig
  srcrect.Left = 0
  srcrect.Top = 0
  srcrect.Right = Taxi_Width
  srcrect.Bottom = Taxi_Height
  If screen_x < 0 Then
    srcrect.Left = srcrect.Left - screen_x
    screen_x = 0
  ElseIf (screen_x + srcrect.Right) > 640 Then
    srcrect.Right = 640 - screen_x
  End If
  'Taxi auf den Bildschirm zeichnen
  BackBuffer.BltFast screen_x, 220, _
      bmpTaxi, srcrect, _
      DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY
End If
'Taxiposition verringern, aber innerhalb eines
'Bereiches damit wir es oft sehen
taxi_pos = taxi_pos - 3.5
If taxi_pos < (screen_pos - 5000) Then
  taxi_pos = screen_pos + 5000
End If

'Benutzeroberfläche zeichnen
With srcrect
  .Top = 0: .Left = 0:
  .Right = 640: .Bottom = 480
End With
BackBuffer.BltFast 0, 0, bmpInterface, _
    srcrect, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY

Dies schließt die Darstellung der Szene ab. Diese Technik, auch als Seiten-Scrolling (Side Scrolling) bekannt, ergibt einen guten 3D-Eindruck ohne die Kosten der Erstellung und Darstellung einer 3D-Welt. Ein Beispiel für Parallaxe können Sie hier downloaden, und den ausführlichen Code finden Sie in unserer Tipp-Rubrik.

  Download BitmapBlt.zip Download
tip0182.zip
 (459 kB)
Downloadzeit: <1 Min. - 28.8k / <1 Min. - ISDN Downloads bisher: [ 2496 ]

Startseite | VB-/VBA-Tipps | Projekte | Tutorials | API-Referenz | Komponenten | Bücherecke | Gewinnspiele | VB-/VBA-Forum | DirectX-Forum | VB.Net | .Net-Forum | Foren-Archiv | Chat | Spielplatz | Links | Suchen | Stichwortverzeichnis | Feedback | Impressum

Seite empfehlen Bug-Report

Letzte Aktualisierung, Donnerstag, 03. Juni 2004