Tipp 0308 2D mit Direct3D darstellen (rendern)
Autor/Einsender:
Datum:
  Alexander Csadek
29.01.2003
Entwicklungsumgebung:
DirectX-Version:
  VB 6
DirectX 7
Es gibt zwar keine zwingenden Gründe Direct3D für sein 2D-Spiel zu verwenden. Wer sich gut mit DirectDraw auskennt und nicht mehr benötigt, braucht sein Spiel auch nicht auf Direct3D umzustellen. 
Allerdings bietet Direct3D gegenüber DirectDraw einige Vorteile, wie das Alpha-Blending und die Geschwindigkeit der Grafikkarte, da heute fast jede Grafikkarte über einen 3D-Chip verfügt. Der Nachteil ist aber, dass bei jedem noch so kleinen Effekt geprüft werden muss, ob die Grafikkarte diesen auch unterstützt.
Um sein 2D-Spiel mit Direct3D-Möglichkeiten und -Effekte auszustatten, muss man sich nicht unbedingt mit Vertexe und Matrixe rumschlagen, und man braucht auch keine Angst zu haben, dass die Perspektive alles verzerrt. Denn man kann Direct3D auch ohne der Perspektive (World-, Objekt-View etc.) verwenden.
Des weiteren ist DirectDraw ja nach wie vor da (allerdings nur bei DirectX 7). Es kann also z.B. das Hintergrundbild oder die Vordergrundbilder (z.B. Cockpit) mit DirectDraw gezeichnet und die Sprites mit Direct3D gerendert werden.
Der folgende Code zeigt im Gegensatz zum Download-Projekt nur die wesentlichen Änderungen bzw. Erweiterungen eines normalen DirectDraw-Programmes.
 
Sub Initialization()
  Set DD7 = DX7.DirectDrawCreate("")

  DD7.SetCooperativeLevel Me.hWnd, DDSCL_EXCLUSIVE Or _
    DDSCL_FULLSCREEN Or DDSCL_ALLOWREBOOT

  DD7.SetDisplayMode 800, 600, 16, 0, DDSDM_DEFAULT

  With SurfaceDesc
    .lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
    .ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or _
      DDSCAPS_FLIP Or DDSCAPS_COMPLEX Or DDSCAPS_3DDEVICE
    .lBackBufferCount = 1
  End With
  Set PrimarySurface = DD7.CreateSurface(SurfaceDesc)
  SurfaceDesc.ddsCaps.lCaps = DDSCAPS_BACKBUFFER

  Set BackBuffer = PrimarySurface.GetAttachedSurface( _
        SurfaceDesc.ddsCaps)
  Set D3D7 = DD7.GetDirect3D
  Set D3DDev = D3D7.CreateDevice("IID_IDirect3DHALDevice", _
        BackBuffer)
End Sub

Sub SetD3DVertex(Verts() As D3DTLVERTEX, Src As RECT, _
      Dest As RECT, R As Single, G As Single, B As Single, _
      A As Single, Angle As Single)

  Dim SpriteWidth As Single
  Dim SpriteHeight As Single
  Dim XCenter As Single
  Dim YCenter As Single
  Dim Radius As Single
  Dim XCor As Single
  Dim YCor As Single

  SpriteWidth = 64: SpriteHeight = 64

  XCenter = Dest.Left + (Dest.Right - Dest.Left - 1) / 2
  YCenter = Dest.Top + (Dest.Bottom - Dest.Top - 1) / 2

  If Angle = 0 Then
    XCor = Dest.Left
    YCor = Dest.Bottom
  Else
    XCor = XCenter + (Dest.Left - XCenter) * _
      Sin(Angle) + (Dest.Bottom - YCenter) * Cos(Angle)
    YCor = YCenter + (Dest.Bottom - YCenter) * _
      Sin(Angle) - (Dest.Left - XCenter) * Cos(Angle)
  End If

  DX7.CreateD3DTLVertex XCor, YCor, 0, 1, _
    DX7.CreateColorRGBA(R, G, B, A), _
    0, Src.Left / SpriteWidth, (Src.Bottom + 1) / SpriteHeight, _
    Verts(0)

  If Angle = 0 Then
    XCor = Dest.Left
    YCor = Dest.Top
  Else
    XCor = XCenter + (Dest.Left - XCenter) * _
      Sin(Angle) + (Dest.Top - YCenter) * Cos(Angle)
    YCor = YCenter + (Dest.Top - YCenter) * _
      Sin(Angle) - (Dest.Left - XCenter) * Cos(Angle)
  End If

  DX7.CreateD3DTLVertex XCor, YCor, 0, 1, _
    DX7.CreateColorRGBA(R, G, B, A), _
    0, Src.Left / SpriteWidth, Src.Top / SpriteHeight, _
    Verts(1)

  If Angle = 0 Then
    XCor = Dest.Right
    YCor = Dest.Bottom
  Else
    XCor = XCenter + (Dest.Right - XCenter) * _
      Sin(Angle) + (Dest.Bottom - YCenter) * Cos(Angle)
    YCor = YCenter + (Dest.Bottom - YCenter) * _
      Sin(Angle) - (Dest.Right - XCenter) * Cos(Angle)
  End If

  DX7.CreateD3DTLVertex XCor, YCor, 0, 1, _
        DX7.CreateColorRGBA(R, G, B, A), 0, _
        (Src.Right + 1) / SpriteWidth, _
        (Src.Bottom + 1) / SpriteHeight, _
        Verts(2)

  If Angle = 0 Then
    XCor = Dest.Right
    YCor = Dest.Top
  Else
    XCor = XCenter + (Dest.Right - XCenter) * _
      Sin(Angle) + (Dest.Top - YCenter) * Cos(Angle)
    YCor = YCenter + (Dest.Top - YCenter) * _
      Sin(Angle) - (Dest.Right - XCenter) * Cos(Angle)
  End If

  DX7.CreateD3DTLVertex XCor, YCor, 0, 1, _
        DX7.CreateColorRGBA(R, G, B, A), 0, _
        (Src.Right + 1) / SpriteWidth, _
        Src.Top / SpriteHeight, _
        Verts(3)
End Sub

Sub CalculateSprites()
  Dim i As Integer

  D3DDev.BeginScene
  For i = 0 To UBound(Sprites)
    If Sprites(i).Alive = True Then
      Sprites(i).X = Sprites(i).X + Sprites(i).XVel * TimeElapsed
      If Sprites(i).X > _
            800 - (Sprites(i).Width * Sprites(i).ScaleFactor) Then
        Sprites(i).X = _
              800 - (Sprites(i).Width * Sprites(i).ScaleFactor)
        Sprites(i).XVel = -Sprites(i).XVel
      ElseIf Sprites(i).X < 0 Then
        Sprites(i).X = 0
        Sprites(i).XVel = -Sprites(i).XVel
      End If

      Sprites(i).Y = Sprites(i).Y + Sprites(i).YVel * TimeElapsed
      If Sprites(i).Y > _
            600 - (Sprites(i).Height * Sprites(i).ScaleFactor) Then
        Sprites(i).Y = _
              600 - (Sprites(i).Height * Sprites(i).ScaleFactor)
        Sprites(i).YVel = -Sprites(i).YVel
      ElseIf Sprites(i).Y < 0 Then
        Sprites(i).Y = 0
        Sprites(i).YVel = -Sprites(i).YVel
      End If

      If bolRotation = True Then Sprites(i).Angle = _
            Sprites(i).Angle + Sprites(i).RotVel * TimeElapsed

      If bolSkalieren = True Then
        Sprites(i).ScaleFactor = Sprites(i).ScaleFactor + _
              (Sprites(i).ScaleInc * TimeElapsed)
        If Sprites(i).ScaleFactor >= 2.5 Then _
              Sprites(i).ScaleInc = -1
        If Sprites(i).ScaleFactor <= 0.4 Then _
              Sprites(i).ScaleInc = 1
      Else
        Sprites(i).ScaleFactor = 1
      End If

      If bolFading = True Then
        Sprites(i).Alpha = Sprites(i).Alpha + _
              (Sprites(i).FadeInc * TimeElapsed)
        If Sprites(i).Alpha >= 1 Then
          Sprites(i).Alpha = 1
          Sprites(i).FadeInc = -1
        End If
        If Sprites(i).Alpha <= 0 Then
          Sprites(i).Alpha = 0
          Sprites(i).FadeInc = 1
        End If
      Else
        Sprites(i).Alpha = 1
      End If
        DisplaySprite Sprites(i).X, Sprites(i).Y, _
              CSng(Sprites(i).Width), CSng(Sprites(i).Height), _
              , , Sprites(i).Width * Sprites(i).ScaleFactor, _
              Sprites(i).Height * Sprites(i).ScaleFactor, _
              Sprites(i).Alpha, Sprites(i).R, Sprites(i).G, _
              Sprites(i).B, Sprites(i).Angle
    End If
  Next

  D3DDev.EndScene
End Sub

Public Sub DisplaySprite(ByVal DestX As Single, _
      ByVal DestY As Single, ByVal SrcWidth As Integer, _
      ByVal SrcHeight As Integer, Optional ByVal SrcX As Single, _
      Optional ByVal SrcY As Single, Optional ByVal DestWidth _
      As Integer, Optional ByVal DestHeight As Integer, _
      Optional ByVal Alpha As Single, Optional ByVal R As Single, _
      Optional ByVal G As Single, Optional ByVal B As Single, _
      Optional ByVal Angle As Single)

  Dim SrcRect As RECT
  Dim DestRect As RECT
  Dim TempVertex(3) As D3DTLVERTEX

  If DestWidth = 0 Then DestWidth = SrcWidth
  If DestHeight = 0 Then DestHeight = SrcHeight

  With SrcRect
    .Bottom = SrcY + SrcHeight
    .Left = SrcX
    .Right = SrcX + SrcWidth
    .Top = SrcY
  End With

  With DestRect
    .Bottom = DestY + DestHeight
    .Left = DestX
    .Right = DestX + DestWidth
    .Top = DestY
  End With

  SetD3DVertex TempVertex, SrcRect, DestRect, R, G, B, Alpha, Angle

  If bolBlending = False And bolFading = False Then
    D3DDev.SetRenderState D3DRENDERSTATE_COLORKEYENABLE, True
  End If

  If bolBlending Then
    D3DDev.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, True
    D3DDev.SetRenderState D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE
    D3DDev.SetRenderState D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE
  End If

  If bolFading Then
    D3DDev.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, True
    D3DDev.SetRenderState D3DRENDERSTATE_SRCBLEND, _
          D3DBLEND_SRCALPHA
    D3DDev.SetRenderState D3DRENDERSTATE_DESTBLEND, _
          D3DBLEND_DESTALPHA

    D3DDev.SetRenderState D3DRENDERSTATE_TEXTUREFACTOR, _
      DX7.CreateColorRGBA(1, 1, 1, Alpha)
    D3DDev.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTA_TFACTOR
  End If

  D3DDev.SetTexture 0, bmpVBFun
  D3DDev.SetTextureStageState 0, D3DTSS_MIPFILTER, 3
  D3DDev.DrawPrimitive D3DPT_TRIANGLESTRIP, _
      D3DFVF_TLVERTEX, TempVertex(0), 4, D3DDP_DEFAULT
  D3DDev.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, False
  D3DDev.SetRenderState D3DRENDERSTATE_COLORKEYENABLE, False
End Sub
 
Weitere Links zum Thema
Direct3D-Engine
Bewegen im 3D-Raum
Hinweis
Um dieses Beispiel ausführen zu können, wird die DirectX 7 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  (42,9 kB) Downloads bisher: [ 1340 ]

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: Freitag, 29. Juli 2011