home *** CD-ROM | disk | FTP | other *** search
/ Microsoft DirectX SDK 7.0 / Dx7.bin / DXF / samples / multimedia / vbsamples / ddraw / src / ddblend / ddblend.bas next >
Encoding:
BASIC Source File  |  1999-08-10  |  12.0 KB  |  344 lines

  1. Attribute VB_Name = "modDDBlend"
  2. Declare Function ShowCursor& Lib "user32" (ByVal bShow As Long)
  3.  
  4. Public Const NumParticles = 10000
  5. Public Const MaxParticles = 100000
  6.  
  7. Type ParticleType
  8.     X As Long
  9.     Y As Long
  10.     Angle As Single
  11.     Speed As Long
  12.     Decay As Single
  13.     HalfLife As Single
  14.     AngleAdjustment As Single
  15. End Type
  16. Type DisplayModeType
  17.     Width As Long
  18.     Height As Long
  19.     BPP As Long
  20. End Type
  21. Public DX As New DirectX7
  22. Public DDraw As DirectDraw7
  23. Public DDSFront As DirectDrawSurface7
  24. Public DDSFrontDesc As DDSURFACEDESC2
  25. Public DDSBack As DirectDrawSurface7
  26. Public DDSBackDesc As DDSURFACEDESC2
  27. Public DDSDisplayDesc As DDSURFACEDESC2
  28. Public DisplayModesEnum As DirectDrawEnumModes
  29.  
  30. Public ScreenWidth As Long, ScreenHeight As Long
  31. Public ExitLoop As Boolean
  32. Public MX As Long, MY As Long
  33. Public ParticleCount As Long
  34. Public BlurFactor As Long
  35. Public PaletteNum As Long
  36. Public CurrentDisplayMode As Long
  37. Public DisplayMode() As DisplayModeType
  38. Public Start As Boolean
  39.  
  40. Dim Pict() As Byte
  41. Dim AlphaRect As RECT
  42. Dim X As Long, Y As Long
  43. Dim Index As Long
  44. Dim Pal(255) As PALETTEENTRY
  45. Dim Pal2(255) As PALETTEENTRY
  46. Dim Palette As DirectDrawPalette
  47. Dim Accum As Long
  48. Dim Particle(MaxParticles) As ParticleType
  49. Dim PE1 As PALETTEENTRY
  50. Dim ModeIndex As Long
  51. Dim Mode As Boolean
  52. Dim bRestore As Boolean
  53.  
  54. Private Sub Main()
  55.         
  56.     Dim frmInstructions As Instructions
  57.     
  58.     Set frmInstructions = New Instructions
  59.     frmInstructions.Show
  60.     'Wait for the instructions to be read...
  61.     Do Until Start
  62.         DoEvents
  63.     Loop
  64.     Set frmInstructions = Nothing
  65.     
  66.     'Set our default number of particles and blur factor
  67.     ParticleCount = NumParticles
  68.     BlurFactor = 1
  69.     
  70.     'Win32 API call:
  71.     'Turn the mouse cursor off.  We'll turn it back on before leaving.
  72.     ShowCursor False
  73.     
  74.     'Do all of our basic DX initialization.  We'll call this again later
  75.     'when the user decides to change video modes.
  76.     InitializeDX
  77.     DDSBack.SetForeColor RGB(255, 255, 255)
  78.             
  79.     'Setup all of our particles.  We're going to setup more
  80.     'particles than we will initially use... 100,000 in all.
  81.     For Index = 0 To MaxParticles
  82.         With Particle(Index)
  83.             .Speed = 1 + CInt(Rnd * 3)
  84.             .Angle = Rnd * 6.28 ' 2 pi for a full range of directions
  85.             .X = Rnd * ((ScreenWidth) - 2) + 1 ' initial starting point
  86.             .Y = Rnd * ((ScreenHeight) - 2) + 1
  87.             .Decay = 1  ' the amount of hitpoints left in a particle
  88.             .HalfLife = Rnd / 20 ' will allow a particle to be recycled
  89.             .AngleAdjustment = Rnd / 20 ' will produce a spiraling particle
  90.         End With
  91.     Next
  92.     
  93.     ' setup the 8-bit 256c color palette
  94.     Pal(0).blue = 255
  95.     For Index = 1 To 32
  96.         Pal(Index).red = Index * 8 - 1
  97.         Pal(Index).green = Index * 8 - 1
  98.         Pal(Index).blue = 256 - Index * 8
  99.     
  100.         Pal(Index + 32).red = 255
  101.         Pal(Index + 32).green = 256 - Index * 8
  102.         Pal(Index + 32).blue = 0
  103.         
  104.         Pal(Index + 64).red = 256 - Index * 8
  105.         Pal(Index + 64).green = 0
  106.         Pal(Index + 64).blue = Index * 8 - 1
  107.     
  108.         Pal(Index + 96).red = Index * 8 - 1
  109.         Pal(Index + 96).green = Index * 8 - 1
  110.         Pal(Index + 96).blue = 255
  111.         
  112.         Pal(Index + 128).red = 256 - Index * 8
  113.         Pal(Index + 128).green = 256 - Index * 8
  114.         Pal(Index + 128).blue = 255
  115.             
  116.         Pal(Index + 160).red = Index * 8 - 1
  117.         Pal(Index + 160).green = Index * 8 - 1
  118.         Pal(Index + 160).blue = 256 - Index * 8
  119.     
  120.         Pal(Index + 192).red = 255
  121.         Pal(Index + 192).green = 255
  122.         Pal(Index + 192).blue = Index * 8 - 1
  123.         
  124.         Pal(Index + 223).red = 256 - Index * 8
  125.         Pal(Index + 223).green = 256 - Index * 8
  126.         Pal(Index + 223).blue = 255
  127.     Next
  128.     Set Palette = DDraw.CreatePalette(DDPCAPS_8BIT _
  129.         Or DDPCAPS_ALLOW256, Pal())
  130.     ' setup an alternative pallete here based on the original
  131.     ' every other color will be black to produce a trippy little effect
  132.     For Index = 0 To 255 Step 2
  133.         Pal2(Index).red = Pal(Index).red
  134.         Pal2(Index).green = Pal(Index).green
  135.         Pal2(Index).blue = Pal(Index).blue
  136.     Next
  137.     ' attaching the original pallete to the front surface...
  138.     ' in other words, activating it.
  139.     DDSFront.SetPalette Palette
  140.     
  141.     ' Setup a rectangle for use in our locks.
  142.     AlphaRect.Right = DDSBackDesc.lWidth - 1
  143.     AlphaRect.Bottom = DDSBackDesc.lHeight - 1
  144.     ' Clear the surface pixel by pixel
  145.     ' GetLockedArray offers direct access to surfaces.  For best
  146.     ' performance use it with surfaces stored in system memory, not
  147.     ' video memory.
  148.     DDSBack.Lock AlphaRect, DDSBackDesc, DDLOCK_WAIT, 0
  149.     DDSBack.GetLockedArray Pict()
  150.     For X = 0 To ScreenWidth - 1
  151.         For Y = 0 To ScreenHeight - 1
  152.             Pict(X, Y) = 0
  153.         Next
  154.     Next
  155.     DDSBack.Unlock AlphaRect
  156.     ' start our main loop
  157.     While Not ExitLoop
  158.         ' deal with the possibility that the user may switch out of
  159.         ' exclusive mode and back in again.  We will restore all
  160.         ' surfaces if this occurs.
  161.         Mode = ExModeActive
  162.         bRestore = False
  163.         Do Until ExModeActive
  164.             DoEvents
  165.             bRestore = True
  166.         Loop
  167.         DoEvents
  168.         If bRestore Then
  169.             bRestore = False
  170.             DDraw.RestoreAllSurfaces
  171.         End If
  172.         ' cycle whichever color pallete is currently active
  173.         Select Case PaletteNum
  174.             Case 0
  175.                 PE1 = Pal(0)
  176.                 For Index = 0 To 254
  177.                     Pal(Index) = Pal(Index + 1)
  178.                 Next
  179.                 Pal(255) = PE1
  180.                 Set Palette = DDraw.CreatePalette(DDPCAPS_8BIT _
  181.                 Or DDPCAPS_ALLOW256, Pal())
  182.             Case 1
  183.                 PE1 = Pal2(0)
  184.                 For Index = 0 To 254
  185.                     Pal2(Index) = Pal2(Index + 1)
  186.                 Next
  187.                 Pal2(255) = PE1
  188.                 Set Palette = DDraw.CreatePalette(DDPCAPS_8BIT _
  189.                 Or DDPCAPS_ALLOW256, Pal2())
  190.         End Select
  191.         ' implement the new pallete
  192.         DDSFront.SetPalette Palette
  193.         ' lock the surface to prepare the main effect
  194.         DDSBack.Lock AlphaRect, DDSBackDesc, DDLOCK_WAIT, 0
  195.         DDSBack.GetLockedArray Pict()
  196.         ' loop through the active particles (this number may change)
  197.         For Index = 0 To ParticleCount
  198.             With Particle(Index)
  199.                 .Decay = .Decay - .HalfLife ' recycle
  200.                 If .Decay <= 0 Then
  201.                     .Decay = 1
  202.                     .X = MX
  203.                     .Y = MY
  204.                 End If
  205.                 .Angle = .Angle + .AngleAdjustment ' spiral
  206.                 If .Angle >= 6.28 Then Angle = 0
  207.                 .X = .X + Cos(.Angle) * .Speed ' update position
  208.                 .Y = .Y + Sin(.Angle) * .Speed
  209.                 If (.X > ScreenWidth - 2) Or (.X < 2) Then ' recycle
  210.                     .X = MX
  211.                     .Y = MY
  212.                     .Angle = Rnd * 6.28
  213.                 ElseIf (.Y > ScreenHeight - 2) Or (.Y < 2) Then
  214.                     .X = MX
  215.                     .Y = MY
  216.                     .Angle = Rnd * 6.28
  217.                 End If
  218.                     Pict(.X, .Y) = .Speed * 16 + 186 ' plot pixel
  219.             End With
  220.         Next
  221.         ' create a blurring effect
  222.         For Index = 1 To BlurFactor
  223.             For X = 2 To ScreenWidth - 2
  224.                For Y = 2 To (ScreenHeight - 2)
  225.                     Accum = 0
  226.                     ' the "Accum = Accum + " allows VB to cast the bytes
  227.                     ' being added as longs... or something like that ;-)
  228.                     ' otherwise we'd end up with an overflow
  229.                     Accum = Accum + Pict(X, Y) _
  230.                         + Pict(X, Y + 1) _
  231.                         + Pict(X, Y - 1) _
  232.                         + Pict(X + 1, Y) _
  233.                         + Pict(X - 1, Y) _
  234.                         + Pict(X + 1, Y + 1) _
  235.                         + Pict(X - 1, Y - 1) _
  236.                         + Pict(X + 1, Y - 1) _
  237.                         + Pict(X - 1, Y + 1)
  238.                     
  239.                     Accum = Accum \ 9 ' average the pixels
  240.                     Pict(X, Y) = Accum
  241.                 Next
  242.             Next
  243.         Next
  244.         ' remove artifacts from the sides of the screen
  245.         For Index = 0 To ScreenWidth - 1
  246.             Pict(Index, 0) = 127
  247.             Pict(Index, ScreenHeight - 1) = 127
  248.             Pict(Index, 1) = 127
  249.             Pict(Index, ScreenHeight - 2) = 127
  250.         Next
  251.         For Index = 0 To ScreenHeight - 1
  252.             Pict(0, Index) = 127
  253.             Pict(ScreenWidth - 1, Index) = 127
  254.             Pict(1, Index) = 127
  255.             Pict(ScreenWidth - 2, Index) = 127
  256.         Next
  257.         DDSBack.Unlock AlphaRect
  258.         'update the display
  259.         MainForm.Form_Paint
  260.     Wend
  261.     TerminateDX ' remove most of DX
  262.     ShowCursor True
  263.     End
  264. End Sub
  265. ' tests to see if we are in exclusive mode
  266. Function ExModeActive() As Boolean
  267.     Dim TestCoopRes As Long
  268.     TestCoopRes = DDraw.TestCooperativeLevel
  269.     Select Case TestCoopRes
  270.         Case DDERR_NOEXCLUSIVEMODE
  271.             ExModeActive = False
  272.         Case DD_OK
  273.             ExModeActive = True
  274.     End Select
  275. End Function
  276. Public Sub InitializeDX()
  277.     MainForm.Left = 0
  278.     MainForm.Top = 0
  279.     MainForm.Height = ScreenWidth * Screen.TwipsPerPixelY
  280.     MainForm.Width = ScreenHeight * Screen.TwipsPerPixelX
  281.     MainForm.Show
  282.     DoEvents
  283.     ' create our directdraw object
  284.     Set DDraw = DX.DirectDrawCreate("")
  285.     ' set an initial cooperativelevel of normal
  286.     DDraw.SetCooperativeLevel MainForm.hWnd, DDSCL_NORMAL
  287.     ' query the display for a list of supported 8-bit modes
  288.     ' we'll put these modes into an array for later use.
  289.     If DisplayModesEnum Is Nothing Then
  290.         Set DisplayModesEnum = DDraw.GetDisplayModesEnum(0, DDSDisplayDesc)
  291.         ReDim DisplayMode(DisplayModesEnum.GetCount - 1)
  292.         ModeIndex = -1
  293.         For Index = 1 To DisplayModesEnum.GetCount
  294.             DisplayModesEnum.GetItem Index, DDSDisplayDesc
  295.             If DDSDisplayDesc.ddpfPixelFormat.lRGBBitCount = 8 Then
  296.                 ModeIndex = ModeIndex + 1
  297.                 With DisplayMode(ModeIndex)
  298.                     .Width = DDSDisplayDesc.lWidth
  299.                     .Height = DDSDisplayDesc.lHeight
  300.                     .BPP = DDSDisplayDesc.ddpfPixelFormat.lRGBBitCount
  301.                 End With
  302.             End If
  303.         Next
  304.         ReDim Preserve DisplayMode(ModeIndex)
  305.         ' if we can't find a display mode then we'll have to exit.
  306.         If ModeIndex = -1 Then GoTo DXErr
  307.     End If
  308.     ' switch the screen mode to whatever should be the current mode
  309.     ScreenWidth = DisplayMode(CurrentDisplayMode).Width
  310.     ScreenHeight = DisplayMode(CurrentDisplayMode).Height
  311.     DDraw.SetCooperativeLevel MainForm.hWnd, DDSCL_EXCLUSIVE Or DDSCL_FULLSCREEN
  312.     DDraw.SetDisplayMode ScreenWidth, ScreenHeight, 8, 0, DDSDM_DEFAULT
  313.     ' setup the surfaces
  314.     With DDSFrontDesc
  315.         .lFlags = DDSD_CAPS
  316.         .ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE
  317.     End With
  318.     With DDSBackDesc
  319.         .lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
  320.         .ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_SYSTEMMEMORY
  321.         .lWidth = ScreenWidth
  322.         .lHeight = ScreenHeight
  323.     End With
  324.     Set DDSFront = DDraw.CreateSurface(DDSFrontDesc)
  325.     Set DDSBack = DDraw.CreateSurface(DDSBackDesc)
  326.     DoEvents
  327.     Exit Sub
  328. DXErr:
  329.     TerminateDX
  330.     MsgBox "Cannot find an 8-bit display mode."
  331.     ShowCursor True
  332.     End
  333. End Sub
  334. ' terminate DX objects so we can recreate them again later.
  335. Public Sub TerminateDX()
  336.     DDraw.SetCooperativeLevel MainForm.hWnd, DDSCL_NORMAL
  337.     DoEvents
  338.     Set Clipper = Nothing
  339.     Set DDSBack = Nothing
  340.     Set DDSFront = Nothing
  341.     Set DDraw = Nothing
  342.     Set DX = Nothing
  343. End Sub
  344.