What I mean is, I want to know how to make DDraw 'clip' the graphics that overlap outside of the screen, not just destroy them.
This is very important as it is for a tile engine!!
Printable View
What I mean is, I want to know how to make DDraw 'clip' the graphics that overlap outside of the screen, not just destroy them.
This is very important as it is for a tile engine!!
Yup, nasty little problem :D
Assuming you're using Fullscreen Exclusive mode (otherwise you can just use the built-in DirectDraw Clipper object). Clip the graphics yourself, it's the only way:
(msBack = BackBuffer surface, msTile = Graphics surface, mrScreen = Screen sized rectangle)
It's not that hard, just draw it out on a piece of paper, that's how I got it. It's not tested though, so there might be some small errors in it...Code:Dim rSource As RECT
Dim lX As Long
Dim lY As Long
' Calculate the X And Y coordinates of the tile / sprite / graphic here
lX = -5
lY = -5
' Set up the source rectangle As normal
With rSource
.Left = 0
.Top = 0
.Right = 32
.Height = 32
' Now, perform the manual clipping
' Left side
If lX < 0 Then
.Left = Abs(lX)
lX = 0
End If
' Right side
If lX + 32 > mrScreen.Right Then
.Right = mrScreen.Right - lX
End If
' Top side
If lY < 0 Then
.Top = Abs(lY)
lY = 0
End If
' Bottom side
If lY + 32 > mrScreen.Bottom Then
.Bottom = mrScreen.Bottom - lY
End If
End With
' That's it, now just Blt the tile / sprite / graphic
msBack.BltFast lX, lY, msTile, rSouce, DDBLTFAST_WAIT
Hope this helps!
Err... can't you use hardware clipping? Maybe it's a VB thing, cos I'm pretty sure this doesn't pose a problem in C.
"Hardware Clipping", guess that relies on the hardware, or is it widely supported? Anyways, I never heard of hardware clipping in VB (actually, never even heard of hardware clipping in general :p), but if that's possible, be sure to let me know too :)
Well yeah, I just call it hardware clipping because if the card supports it then it will be done in the HAL (most cards do I think), but it's in the HEL too so you don't have to worry about it being available. In C at least, you have to define a list of clipping regions which is a bit of a pain in the arse data structure to work with, involving alittle dynamic memory allocation... actually it is an incredibly bizarre data structure and I have no idea why they chose it... well anyway I don't know how you'd do it in VB but I'm pretty sure it's possible. Probably a lot simpler too. You define a clip list and then make a call to DDraw->CreateClipper and DDSurface->AttachClipper if my memory serves me correctly.
Hardware clipping is probably the main reason to use Blt instead of BltFast, since BltFast doesn't take any notice of any DirectDraw clippers you have setup.
I don't think it's really possible in VB, the only clippers I know of only work in Windowed mode, so I'm just going to convert my code into a function which handles the clipping...
Hey, PsychoMark, I'm not sure that function will work if the Top/Left is greater than 0. Most DX engines have this problem because they don't need to blt from different parts of one source image, I had to find a really good one that supported it: go to http://www.planet-source-code.com and look for the Grenade Launcher in the VB section.
Oops, yeah, that's right, I got that same problem when programming MouseAttack DX (you can find it at my website, including source code)... here's the clipping code used in that game:
The FillRect is just a simple function which fill a RECT structure (but using Width and Height, so Right becomes Left + Width etc...)Code:Public Sub Draw(Viewport As RECT)
Dim rSrc As RECT
Dim lY As Long
Dim lX As Long
' Draw mouse
With Settings
rSrc = FillRect(.State * .Width, .AniFrame * .Height, .Width, .Height)
' Clip!
lX = .X
lY = .Y
If .Y < Viewport.Top Then
rSrc.Top = rSrc.Top + Abs(.Y - Viewport.Top)
lY = Viewport.Top
End If
If .X < Viewport.Left Then
rSrc.Left = rSrc.Left + Abs(.X - Viewport.Left)
lX = Viewport.Left
End If
If .Y + .Height > Viewport.Bottom Then
rSrc.Bottom = rSrc.Bottom - (.Height - (Viewport.Bottom - .Y))
End If
If .X + .Width > Viewport.Right Then
rSrc.Right = rSrc.Right - (.Width - (Viewport.Right - .X))
End If
msBack.BltFast lX, lY, msMouse, rSrc, DDBLTFAST_SRCCOLORKEY
End With
End Sub
Here's the tile-blitting code from a tile engine I wrote some time ago....
Code:Private Sub BlitTile(X As Integer, Y As Integer, TileNum As Integer, XOffset As Integer, YOffset As Integer)
Dim rSrc As RECT, rDest As RECT
If X = 0 Then
rSrc.Left = TileDesc(TileNum).X + XOffset
rSrc.Right = TileDesc(TileNum).X + TileSize
rDest.Left = 0
rDest.Right = TileSize - XOffset
ElseIf X >= frmScreen.ScaleWidth Then
rSrc.Left = TileDesc(TileNum).X
rSrc.Right = rSrc.Left + XOffset
rDest.Left = X - XOffset
rDest.Right = frmScreen.ScaleWidth
Else
rSrc.Left = TileDesc(TileNum).X
rSrc.Right = rSrc.Left + TileSize
rDest.Left = X - XOffset
rDest.Right = rDest.Left + TileSize
End If
If Y = 0 Then
rSrc.Top = TileDesc(TileNum).Y + YOffset
rSrc.Bottom = TileDesc(TileNum).Y + TileSize
rDest.Top = 0: rDest.Bottom = TileSize - YOffset
ElseIf Y >= frmScreen.ScaleHeight Then
rSrc.Top = TileDesc(TileNum).Y
rSrc.Bottom = TileDesc(TileNum).Y + YOffset
rDest.Top = Y - YOffset
rDest.Bottom = frmScreen.ScaleHeight
Else
rSrc.Top = TileDesc(TileNum).Y
rSrc.Bottom = TileDesc(TileNum).Y + TileSize
rDest.Top = Y - YOffset
rDest.Bottom = rDest.Top + TileSize
End If
srfBackBuf.Blt rDest, srfTiles, rSrc, DDBLT_WAIT
End Sub