Tipp 0418 2D mit DirectX 8
Autor/Einsender:
Datum:
  Alexander Csadek
06.10.2004
Entwicklungsumgebung:
DirectX-Version:
  VB 6
DirectX 8
Wer direkt mit DirectX 8 begonnen hat, Spiele mit Visual Basic zu erstellen, dem ist es vielleicht gar nicht aufgefallen, aber diejenigen, die von DirectX 7 auf 8 umsteigen, fragen sich "Wo ist DirectDraw für meine Spiele in 2D?".
Nun, bei DirectX 8 gibt es die Komponente DirectDraw nicht mehr. Sie wurde von Microsoft unter dem Begriff DirectGraphics mit Direct3D zusammengefasst und in die Komponente Direct3D verschoben.
Möchte man nun ein Spiel in 2D erstellen, so ist es nicht unbedingt notwendig, dies ausschließlich über die Komponente Direct3D zu tun und sich mit Matrizen und Vertexe herumzuschlagen. Es geht auch einfacher und man kann trotzdem skalieren, rotieren und verfügt über Farb-Modulation und Blend-Effekte. Dazu stellt das D3DX8-Objekt mit dem D3DX8-Sprite-Objekt, ein Objekt speziell für 2D-Bilder (Sprites) zur Verfügung.
Das D3DX8-Objekt wird nicht wie die anderen DirectX-Komponenten über das DirectX8-Objekt erstellt, sondern als eigenes Objekt instanziert:
 
Set gD3DX8 = New D3DX8
 
Das D3DX8-Sprite-Objekt wird dann mit Hilfe des D3DX8 und einem gültigen 3DDevice erstellt.
 
Set gD3DX8Sprite = gD3DX8.CreateSprite(gD3DDevice8)
 
Jetzt steht einem Spiel in 2D nichts mehr im Wege. Man erstellt ein Direct3D-Objekt und einen 3DDevice, egal ob Vollbild (fullscreen mode) oder im Fenster (windowed mode).
Die Bitmaps werden über das D3DX8-Objekt als normale Texturen geladen, zum Beispiel:
 
Set texBild = gD3DX8.CreateTextureFromFileEx( _
    gD3DDevice8, App.Path & "\vbfun.bmp", _
    312, 208, 1, 0, D3DFMT_A8R8G8B8, _
    D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, _
    &HFF000000, ByVal 0, ByVal 0)
 
Das Zeichnen der Bilder in 2D erfolgt zwischen dem BeginScene und EndScene vom 3DDevice, und zwar mit dem D3DX8-Objekt. Das angenehme dabei ist, die Position des Bildes wird in Bildschirm-Koordinaten (x, y) angegeben.
 
gD3DDevice8.BeginScene
gD3DX8Sprite.Begin
gD3DX8Sprite.Draw(texBild, recSource, vecScaling, _
      vecRotationCenter, sngRotation, vecTranslation, lngColor)
gD3DX8Sprite.End
gD3DDevice8.EndScene
gD3DDevice8.Present ByVal 0, ByVal 0, 0, ByVal 0
 
Die D3DX8-Sprite-Objekt Methode Draw verlangt folgende Parameter und bietet zudem ein paar interessante Möglichkeiten.
Color Farbe und Alpha-Kanal des Bildes kann hiermit verändert werden.
Bei &HFFFFFFFF werden die Farben und der Alpha-Kanal vom Originalbild genommen.
Rotation Angabe der Rotation in Radians entgegen dem Uhrzeigersinn (counter-clockwise).
RotationCenter ein 2D-Vektor mit dem gewünschten Rotations-Zentrum.
x = 0 und y = 0 ist immer die linke obere Ecke des Bildes.
Scaling ein 2D-Vektor mit der gewünschten Skalierung des Bildes.
Bei x = 1 und y = 1 wird die Originalgröße verwendet.
SrcRect der gewünschte Bild-Ausschnitt.
ByVal 0 bedeutet, dass das gesamte Bild gezeichnet wird.
SrcTexture das Bild aus einem Direct3DTexture-Objekt.
Translation Angabe der x- und y-Position am Bildschirm mittels eines 2D-Vektors.
x = 0 und y = 0 ist die linke obere Bildschirmecke.
Vorbei ist die Trauer um DirectDraw. Spiele in 2D mit DirectX8 sind möglich, und noch dazu mit Skalieren, Rotieren, Farb-Modulation und Blend-Effekt.
Es folgt nun der für diesen Tipp relevante Code...
 
Private Sub Render()
  Dim recSource   As RECT
  Dim hlpZeile    As Integer
  Dim sngRotation As Double
  Dim lngColor    As Long
  Dim i           As Integer

  If gD3DDevice8 Is Nothing Then Exit Sub

   'bereinigen des BackBuffers
  gD3DDevice8.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0

   'Szene beginnen
  gD3DDevice8.BeginScene

   'Wir teilen DirectX mit, dass wir nun 2D-Bilder zeichnen möchten
  gD3DX8Sprite.Begin

   'Mit der Draw-Methode des D3DX8Sprite-Objektes werden 
   'die Bilder gezeichnet
  For i = 0 To UBound(BILD())
     'prüfen ob wir aus den Screenbereich laufen
    If BILD(i).X < 5 Then
      BILD(i).DirX = BILD(i).DirX * -1
    End If
    If BILD(i).Y < 5 Then
      BILD(i).DirY = BILD(i).DirY * -1
    End If
    If BILD(i).X + 10 > (SCREENWIDTH - BildBreiteHoehe) Then
      BILD(i).DirX = BILD(i).DirX * -1
    End If
    If BILD(i).Y + 10 > (SCREENHEIGHT - BildBreiteHoehe) Then
      BILD(i).DirY = BILD(i).DirY * -1
    End If

     'Ausschnitt bewegen
    BILD(i).X = BILD(i).X + BILD(i).DirX
    BILD(i).Y = BILD(i).Y + BILD(i).DirY

     'Rotation
    sngRotation = 0
    If BILD(i).bolRotation Then
      BILD(i).Degree = BILD(i).Degree + BILD(i).Rotation
      If BILD(i).Degree > 360 Then BILD(i).Degree = 0
      If BILD(i).Degree < 0 Then BILD(i).Degree = 360
      sngRotation = DegToRad(BILD(i).Degree)
    End If

     'Color
    lngColor = D3DColorARGB(255, 255, 255, 255)
    If BILD(i).bolFade Then
      BILD(i).Color = BILD(i).Color + BILD(i).Fade
      If BILD(i).Color > 255 Then
        BILD(i).Fade = BILD(i).Fade * -1
        BILD(i).Color = 255
      End If
      If BILD(i).Color < 0 Then
        BILD(i).Fade = BILD(i).Fade * -1
        BILD(i).Color = 0
      End If
      Select Case BILD(i).xRGB
        Case 0: lngColor = D3DColorARGB( _
                     BILD(i).Color, 255, 255, 255)
        Case 1: lngColor = D3DColorARGB( _
                     255, 255, BILD(i).Color, BILD(i).Color)
        Case 2: lngColor = D3DColorARGB( _
                     255, BILD(i).Color, BILD(i).Color, 255)
        Case 3: lngColor = D3DColorARGB( _
                     255, BILD(i).Color, 255, BILD(i).Color)
      End Select
    End If

     'Scaling
    vecScaling.X = 1: vecScaling.Y = 1
    If BILD(i).bolScaling Then
      BILD(i).Scaling = BILD(i).Scaling + BILD(i).ScalingStep
      If BILD(i).Scaling > 1.5 Then
        BILD(i).Scaling = 1.5
        BILD(i).ScalingStep = BILD(i).ScalingStep * -1
      End If
      If BILD(i).Scaling < 0.5 Then
        BILD(i).Scaling = 0.5
        BILD(i).ScalingStep = BILD(i).ScalingStep * -1
      End If
      vecScaling.X = BILD(i).Scaling
      vecScaling.Y = BILD(i).Scaling
    End If

    'Festlegen welchen Bereich vom Bitmap wir kopieren
    'möchten ... in diesem Fall nur einen Teil
    hlpZeile = Int(BILD(i).AniCount) \ 6
    With recSource
      .Left = BildBreiteHoehe * (Int(BILD(i).AniCount) - _
                     (hlpZeile * 6))
      .Right = .Left + BildBreiteHoehe
      .Top = hlpZeile * BildBreiteHoehe
      .bottom = .Top + BildBreiteHoehe
    End With

     'Ausschnitte in den Backbuffer zeichnen
    vecTranslation.X = BILD(i).X: vecTranslation.Y = BILD(i).Y
    Call gD3DX8Sprite.Draw(texBild, recSource, vecScaling, _
      vecRotationCenter, sngRotation, vecTranslation, lngColor)
    BILD(i).AniCount = BILD(i).AniCount + 0.5
    If Int(BILD(i).AniCount) > 23 Then BILD(i).AniCount = 0
  Next i
  gD3DX8Sprite.End
  
   'Szene beenden
  gD3DDevice8.EndScene
   'kompletten BackBuffer zum FrontBuffer kopieren
  gD3DDevice8.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub
 
Hinweis
Um dieses Beispiel ausführen zu können, wird die DirectX 8 for Visual Basic Type Library benötigt (siehe dazu die Erläuterungen in der DirectX-Rubrik).

Windows-Version
95
98/SE
ME
NT
2000
XP
Vista
Win 7
VB-Version
VBA 5
VBA 6
VB 4/16
VB 4/32
VB 5
VB 6


Download  (116 kB) Downloads bisher: [ 1305 ]

Vorheriger Tipp Zum Seitenanfang Nächster Tipp

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

Seite empfehlen Bug-Report
Letzte Aktualisierung: Donnerstag, 25. August 2011