As in the basic tutorial I'll show you the whole code first and discuss each part later. So let's have a look at the new Draw function:
Public Sub Draw() Dim X as Long Dim Y as Long Dim Index as Long Dim TileIndex as Long Dim TempX as Single Dim TempY as Single With Map 'Get map position TempX = ( Camera.X / TileSize ) TempY = ( Camera.Y / TileSize ) 'Calculate index of this positon Index = Int( TempY ) * .w + Int( TempX ) 'Calculate smooth scrolling TempX = TempX - Int( TempX ) TempY = TempY - Int( TempY ) 'Draw the map For Y = 0 To Camera.TilesY For X = 0 To Camera.TilesX 'Check index If Index > ( Map.w * Map.h ) Then: Exit Sub 'Get tile index TileIndex = .Data( Index ) 'Draw tile BitBlt Camera.FrontDC, _ ( X - TempX ) * TileSize, ( Y - TempY ) * TileSize, _ TileSize, TileSize, _ Bitmap( Tile( TileIndex ).Bitmap ).Picture.DC, _ Tile( TileIndex ).ActFrame * TileSize, 0, _ vbSrcCopy 'Next tile Index = Index + 1 Next 'Get next line start Index = Index + .w - Camera.TilesX - 1 Next End With End Sub
You can see lots of math now and the function has grown a little. Well you know, don't be scared it's just code.
Public Sub Draw() Dim X as Long Dim Y as Long Dim Index as Long Dim TileIndex as Long Dim TempX as Single Dim TempY as Single
The newly declared values TempX and TempY will be used to get the tile-based position first and later they will represent the pixel-offset the camera has (to the next exact tile position). We'll get right to this.
With Map 'Get map position TempX = ( Camera.X / TileSize ) TempY = ( Camera.Y / TileSize )
Since the camera position is in pixels now we have to divide it by the TileSize to get the tile-based position. Note that this returns floating-point numbers, we'll need this in the next line:
'Calculate index of this positon Index = Int( TempY ) * .w + Int( TempX )
By rounding the position we get the tile-based position in the map. Example: The camera position is (34, 20) in pixel, this is near (32, 16) where the next exact tile coordinates are. TempX would be 2.125 and TileY would be 1.25. Now take the integer values and you get (2, 1) which is exactly the next valid map position. The result we transform from 2D coordinates to the 1D index position and that's where we have to start drawing from.
'Calculate offset TempX = TempX - Int( TempX ) TempY = TempY - Int( TempY )
Now that we have the index position we don't care about the map position anymore so we subtract it from the original TempX and TempY. The remaining part is everything after the point, so 0.125 and 0.25 in our example. Note that these are still tile-based positions and we have to multiplicate them by the TileSize to get back the offset in pixels!
'Draw the map For Y = 0 To Camera.TilesY For X = 0 To Camera.TilesX 'Check index If Index > ( Map.w * Map.h ) Then: Exit Sub 'Get tile index TileIndex = .Data( Index )
Until here everything stayed as it was before. Nope. The loops now go from 0 to Camera.TilesX and Camera.TilesY, before they went from 0 to (Camera.TilesX - 1) and (Camera.TilesY - 1). So why did that change? Imagine moving the whole display 8 pixel (half a tile) to the left. The last draw function exactly filled up the screen, so there would be 8 untouched pixels at the very right of the screen. Therefore we have to draw 1 extra line in both directions, X and Y, to still fill the whole screen. This is also where the index check comes handy, without it we'd produce a overflow whenever the camera reaches the very bottom of the map (because of the non-existing position where both extra lines are crossing).
'Draw tile BitBlt Camera.FrontDC, _( X - TempX ) * TileSize, ( Y - TempY ) * TileSize, _TileSize, TileSize, _ Bitmap( Tile( TileIndex ).Bitmap ).Picture.DC, _ Tile( TileIndex ).ActFrame * TileSize, 0, _ vbSrcCopy
This is already the last part that changes, as usual I marked the changed line for you. What we do here is subtracting the offset from the current (tile-based) position and multiplicate the result by the TileSize to get this position in pixels. Hope you're getting familiar with these transformations.
'Next tile Index = Index + 1 Next 'Get next line start Index = Index + .w - Camera.TilesX - 1 Next End With End Sub
Well that's it, the function now handles pixel-based camera positions! Feel free to extend the other tutorials with smooth scrolling if you like, shouldn't bee too hard now. As always you can download the sample project here: