Greetings,
i've been programming with Bitblt (VB6) for a while and i'm trying to learn DirectDraw7.
I'm trying to use BltFast to convert this background into a tiled map.
actually, i was sucessfull of making tiles, but when the sprites run over the background i get visual errors,
so it seems i'm having problems with refreshing the background.
here's the unedited code i started with.
my question is, what do i have to change to make this a tiled map in BltFast?
Option Explicit
Option Base 0
'Windows API functions and structures
Private Declare Function GetTickCount _
Lib "kernel32" () As Long
'program constants
Const SCREENWIDTH As Long = 640
Const SCREENHEIGHT As Long = 480
Const MAXFRAMERATE As Long = 100
Const NUMSPRITES As Long = 30
'program controls
Dim WithEvents Picture1 As PictureBox
'DirectDraw variables
Dim objDX As DirectX7
Dim ddraw As DirectDraw7
Dim objDDClip As DirectDrawClipper
Private ddcKey As DDCOLORKEY
'primary display surface variables
Dim ddScreen As DirectDrawSurface7
Private ddsdScreen As DDSURFACEDESC2
Private rScreen As RECT
'double buffer variables
Dim ddBackBuffer As DirectDrawSurface7
Private ddsdBackBuffer As DDSURFACEDESC2
Dim rBackBuffer As RECT
'background image variables
Dim ddBackground As DirectDrawSurface7
Private ddsdBackground As DDSURFACEDESC2
Dim rBackground As RECT
'sprite variables
Dim ddSprites(NUMSPRITES) As DirectDrawSurface7
Dim SpriteX(NUMSPRITES) As Long
Dim SpriteY(NUMSPRITES) As Long
Dim SpeedX(NUMSPRITES) As Long
Dim SpeedY(NUMSPRITES) As Long
Private ddsdSprite As DDSURFACEDESC2
Dim rSprite As RECT
'program variables
Dim rTemp As RECT
Dim bRunning As Boolean
Dim n As Long
Private Sub Form_Load()
Static lStartTime As Long
Static lCounter As Long
Static lNewTime As Long
bRunning = True
Randomize GetTickCount
'set up the main form
With Form1
.Width = SCREENWIDTH * Screen.TwipsPerPixelX
.Height = SCREENHEIGHT * Screen.TwipsPerPixelY
.AutoRedraw = False
.ClipControls = False
.KeyPreview = True
.ScaleMode = 3
.BorderStyle = 1
.Show
End With
'create the PictureBox control
Set Picture1 = Controls.Add("VB.PictureBox", "Picture1")
With Picture1
.AutoRedraw = False
.BorderStyle = 1
.ClipControls = False
.ScaleMode = 3
.BackColor = RGB(0, 0, 0)
.Left = 0
.Top = 0
.Width = Form1.ScaleWidth
.Height = Form1.ScaleHeight
.Visible = True
End With
'create the DirectX object
Set objDX = New DirectX7
'create the DirectDraw object
Set ddraw = objDX.DirectDrawCreate("")
'set up primary display surface
ddraw.SetCooperativeLevel Picture1.hWnd, DDSCL_NORMAL
ddsdScreen.lFlags = DDSD_CAPS
ddsdScreen.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE
ddsdScreen.lWidth = SCREENWIDTH
ddsdScreen.lHeight = SCREENHEIGHT
Set ddScreen = ddraw.CreateSurface(ddsdScreen)
'set surface rectangle
rScreen.Bottom = ddsdScreen.lHeight
rScreen.Right = ddsdScreen.lWidth
'create the clipper object
Set objDDClip = ddraw.CreateClipper(0)
objDDClip.SetHWnd Picture1.hWnd
ddScreen.SetClipper objDDClip
'create the back buffer
ddsdBackBuffer.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdBackBuffer.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsdBackBuffer.lWidth = SCREENWIDTH
ddsdBackBuffer.lHeight = SCREENHEIGHT
Set ddBackBuffer = ddraw.CreateSurface(ddsdBackBuffer)
rBackBuffer.Bottom = ddsdBackBuffer.lHeight
rBackBuffer.Right = ddsdBackBuffer.lWidth
'load the background image
ddsdBackground.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdBackground.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsdBackground.lWidth = SCREENWIDTH
ddsdBackground.lHeight = SCREENHEIGHT
Set ddBackground = ddraw.CreateSurfaceFromFile(App.Path & _
"\blueyellow.bmp", ddsdBackground)
rBackground.Bottom = ddsdBackground.lHeight
rBackground.Right = ddsdBackground.lWidth
ddBackBuffer.BltFast 0, 0, ddBackground, rBackground, _
DDBLTFAST_WAIT
'set up the sprite information
ddsdSprite.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdSprite.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsdSprite.lWidth = 64
ddsdSprite.lHeight = 64
ddcKey.low = 0
ddcKey.high = 0
'load the sprites
For n = 0 To NUMSPRITES
Set ddSprites(n) = ddraw.CreateSurfaceFromFile(App.Path & _
"\directx.bmp", ddsdSprite)
rSprite.Bottom = ddsdSprite.lHeight
rSprite.Right = ddsdSprite.lWidth
SpriteX(n) = Random(SCREENWIDTH - ddsdSprite.lWidth)
SpriteY(n) = Random(SCREENHEIGHT - ddsdSprite.lHeight)
Do Until SpeedX(n) <> 0
SpeedX(n) = Random(6) - 3
Loop
Do Until SpeedY(n) <> 0
SpeedY(n) = Random(6) - 3
Loop
ddSprites(n).SetColorKey DDCKEY_SRCBLT, ddcKey
Next n
'main game loop
Do While bRunning
lCounter = GetTickCount - lStartTime
If lCounter > lNewTime Then
'update game display
Game_Update lCounter
'update frame count
lNewTime = lCounter + 1000 / MAXFRAMERATE
End If
DoEvents
Loop
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 27 Then Shutdown
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Shutdown
End Sub
Private Sub Form1_Click()
Shutdown
End Sub
Private Sub Picture1_Click()
Shutdown
End Sub
Private Sub Shutdown()
bRunning = False
Form1.Hide
ddraw.RestoreDisplayMode
ddraw.SetCooperativeLevel Picture1.hWnd, DDSCL_NORMAL
Set ddraw = Nothing
Set objDX = Nothing
End
End Sub
Public Function Random(ByVal lNum As Long) As Long
Random = CLng(lNum * Rnd)
End Function
Public Sub Game_Update(ByVal MS As Long)
Static lTimer As Long
Static lStart As Long
Static lCounter As Long
'start counting draw time
lStart = GetTickCount
'erase sprites
For n = 0 To NUMSPRITES
rTemp.Left = SpriteX(n)
rTemp.Top = SpriteY(n)
rTemp.Right = rTemp.Left + ddsdSprite.lWidth
rTemp.Bottom = rTemp.Top + ddsdSprite.lHeight
ddBackBuffer.BltFast SpriteX(n), SpriteY(n), ddBackground, _
rTemp, DDBLTFAST_WAIT
Next n
'move and draw the sprites
For n = 0 To NUMSPRITES
'update X position
SpriteX(n) = SpriteX(n) + SpeedX(n)
If SpriteX(n) < 1 Then
SpeedX(n) = -SpeedX(n)
SpriteX(n) = 1
ElseIf SpriteX(n) + ddsdSprite.lWidth > SCREENWIDTH Then
SpeedX(n) = -SpeedX(n)
SpriteX(n) = SCREENWIDTH - ddsdSprite.lWidth - 1
End If
'update Y position
SpriteY(n) = SpriteY(n) + SpeedY(n)
If SpriteY(n) < 1 Then
SpeedY(n) = -SpeedY(n)
SpriteY(n) = 1
ElseIf SpriteY(n) + ddsdSprite.lHeight > SCREENHEIGHT Then
SpeedY(n) = -SpeedY(n)
SpriteY(n) = SCREENHEIGHT - ddsdSprite.lHeight - 1
End If
'draw the sprite
rTemp.Left = SpriteX(n)
rTemp.Top = SpriteY(n)
rTemp.Right = SpriteX(n) + ddsdSprite.lWidth
rTemp.Bottom = SpriteY(n) + ddsdSprite.lHeight
ddBackBuffer.Blt rTemp, ddSprites(n), rSprite, _
DDBLT_WAIT Or DDBLT_KEYSRC
Next n
'copy double buffer to the screen
objDX.GetWindowRect Picture1.hWnd, rScreen
ddScreen.Blt rScreen, ddBackBuffer, rBackBuffer, DDBLT_WAIT
'count the frames per second
If MS > lTimer + 1000 Then
lStart = GetTickCount - lStart
Form1.Caption = "FPS = " & lCounter & ", MS = " & lStart
lTimer = MS
lCounter = 0
Else
lCounter = lCounter + 1
End If
End Sub