Difficulty: Medium 3/5
This tutorial will show you how to modify a vanilla copy of Mirage Source 3.0.3/3.0.7 to put in scrolling maps. This has only been tested on vanilla Mirage Source 3.0.3/3.0.7, and is not guaranteed to work with your code.
With my version of scrolling maps, the player will always be in the center tile of the screen. (Or 1 left/1 up from center, depending on how big you make your maps. x = 8, y = 6 on standard vanilla 3.0.3/3.0.7) Any tile that is off the map will be filled with black.
Files to Modify
Each portion of this tutorial is broken up by file, which is how I intend to break down every tutorial I post on this forum, even in cases such as this one that we only modify one file. If enough people want to see this in action before making changes, I may put up a temporary (vanilla) server/client.. Anyways.. Let's begin.
[size=18px]modGameLogic.bas ModGameLogic is where the game handles all of the imagery that you see in the game. I'm going to show you from the top of the file to the bottom.
In Sub GameLoop() Replace this code:
' Release DC Call DD_BackBuffer.ReleaseDC(TexthDC) ' Get the rect for the back buffer to blit from rec.Top = 0 rec.Bottom = (MAX_MAPY + 1) * PIC_Y rec.Left = 0 rec.Right = (MAX_MAPX + 1) * PIC_X ' Get the rect to blit to Call DX.GetWindowRect(frmMirage.picScreen.hWnd, rec_pos) rec_pos.Bottom = rec_pos.Top + ((MAX_MAPY + 1) * PIC_Y) rec_pos.Right = rec_pos.Left + ((MAX_MAPX + 1) * PIC_X) ' Blit the backbuffer Call DD_PrimarySurf.Blt(rec_pos, DD_BackBuffer, rec, DDBLT_WAIT) with this code:
' Release DC Call DD_BackBuffer.ReleaseDC(TexthDC) Dim MapXOffset As Integer, MapYOffset As Integer Dim PXOffset As Long, PYOffset As Long Dim bRec As RECT, tRec As RECT MapXOffset = Int(MAX_MAPX / 2) - GetPlayerX(MyIndex) MapYOffset = Int(MAX_MAPY / 2) - GetPlayerY(MyIndex) PXOffset = Player(MyIndex).XOffset PYOffset = Player(MyIndex).YOffset ' Get the rect for the back buffer to blit from If MapYOffset < 0 Then rec.top = Abs(MapYOffset) * PIC_Y rec.Bottom = (MAX_MAPY + 1) * PIC_Y Else rec.top = 0 rec.Bottom = PIC_Y * ((MAX_MAPY + 1) - MapYOffset) End If If MapXOffset < 0 Then rec.Left = Abs(MapXOffset) * PIC_X rec.Right = (MAX_MAPX + 1) * PIC_X Else rec.Left = 0 rec.Right = PIC_X * ((MAX_MAPX + 1) - MapXOffset) End If ' Get the rect to blit to Call DX.GetWindowRect(frmMirage.picScreen.hWnd, tRec) If MapYOffset < 0 Then rec_pos.top = tRec.top Else rec_pos.top = tRec.top + MapYOffset * PIC_Y End If rec_pos.Bottom = rec_pos.top + (rec.Bottom - rec.top) If MapXOffset < 0 Then rec_pos.Left = tRec.Left Else rec_pos.Left = tRec.Left + MapXOffset * PIC_X End If rec_pos.Right = rec_pos.Left + (rec.Right - rec.Left) ' Handle player movement offsets. If GetPlayerY(MyIndex) = Int(MAX_MAPY / 2) And PYOffset > 0 Then rec.top = rec.top + PYOffset rec_pos.Bottom = rec_pos.Bottom - PYOffset ElseIf GetPlayerX(MyIndex) = Int(MAX_MAPX / 2) And PXOffset > 0 Then rec.Left = rec.Left + PXOffset rec_pos.Right = rec_pos.Right - PXOffset Else If rec.Left = 0 Then rec_pos.Left = rec_pos.Left - PXOffset rec.Right = rec.Right + PXOffset End If If rec.Right = PIC_X * (MAX_MAPX + 1) Then rec_pos.Right = rec_pos.Right - PXOffset rec.Left = rec.Left + PXOffset End If If rec.top = 0 Then rec_pos.top = rec_pos.top - PYOffset rec.Bottom = rec.Bottom + PYOffset End If If rec.Bottom = PIC_Y * (MAX_MAPY + 1) Then rec_pos.Bottom = rec_pos.Bottom - PYOffset rec.top = rec.top + PYOffset End If End If 'Fill in unfilled horizontal portions of the map with black. If MapYOffset < 0 Then bRec.top = rec_pos.Bottom bRec.Bottom = tRec.Bottom Else bRec.Bottom = rec_pos.top bRec.top = tRec.top End If bRec.Left = tRec.Left bRec.Right = bRec.Left + (PIC_X * (MAX_MAPX + 1)) Call DD_PrimarySurf.BltColorFill(bRec, 0) 'Fill in unfilled vertical portions of the map with black. bRec.top = tRec.top bRec.Bottom = tRec.top + (PIC_Y * (MAX_MAPY + 1)) If MapXOffset < 0 Then bRec.Left = rec_pos.Right bRec.Right = tRec.Right Else bRec.Right = rec_pos.Left bRec.Left = tRec.Left End If Call DD_PrimarySurf.BltColorFill(bRec, 0) ' Blit the backbuffer Call DD_PrimarySurf.Blt(rec_pos, DD_BackBuffer, rec, DDBLT_WAIT) In Sub EditorMouseDown Replace this code:
Public Sub EditorMouseDown(Button As Integer, Shift As Integer, x As Single, y As Single) Dim x1, y1 As Long
If InEditor Then x1 = Int(x / PIC_X) y1 = Int(y / PIC_Y) with this code:
Public Sub EditorMouseDown(Button As Integer, Shift As Integer, x As Single, y As Single) Dim x1, y1 As Long
If InEditor Then x1 = Int(x / PIC_X) + (Player(MyIndex).x - Int(MAX_MAPX / 2)) y1 = Int(y / PIC_Y) + (Player(MyIndex).y - Int(MAX_MAPY / 2)) In Sub PlayerSearch Replace this code:
Sub PlayerSearch(Button As Integer, Shift As Integer, x As Single, y As Single) Dim x1 As Long, y1 As Long
x1 = Int(x / PIC_X) y1 = Int(y / PIC_Y) with this code:
Sub PlayerSearch(Button As Integer, Shift As Integer, x As Single, y As Single) Dim x1 As Long, y1 As Long
x1 = Int(x / PIC_X) + (Player(MyIndex).x - Int(MAX_MAPX / 2)) y1 = Int(y / PIC_Y) + (Player(MyIndex).y - Int(MAX_MAPY / 2)) This section added on April 4th Delete this code:
' Blit the text they are putting in Call DrawText(TexthDC, 0, (MAX_MAPY + 1) * PIC_Y - 20, MyText, RGB(255, 255, 255)) ' Draw map name If Map.Moral = MAP_MORAL_NONE Then Call DrawText(TexthDC, Int((MAX_MAPX + 1) * PIC_X / 2) - (Int(Len(Trim(Map.Name)) / 2) * 8), 1, Trim(Map.Name), QBColor(BrightRed)) Else Call DrawText(TexthDC, Int((MAX_MAPX + 1) * PIC_X / 2) - (Int(Len(Trim(Map.Name)) / 2) * 8), 1, Trim(Map.Name), QBColor(White)) End If ' Check if we are getting a map, and if we are tell them so 'If GettingMap = True Then ' Call DrawText(TexthDC, 50, 50, "Receiving Map...", QBColor(BrightCyan)) 'End If Under this code:
' Blit the backbuffer Call DD_PrimarySurf.Blt(rec_pos, DD_BackBuffer, rec, DDBLT_WAIT) Add this code:
' Blit the text they are putting in TexthDC = frmMirage.picScreen.hdc Call DrawText(TexthDC, 0, (MAX_MAPY + 1) * PIC_Y - 20, MyText, RGB(255, 255, 255)) ' Draw map name If Map.Moral = MAP_MORAL_NONE Then Call DrawText(TexthDC, Int((MAX_MAPX + 1) * PIC_X / 2) - (Int(Len(Trim(Map.Name)) / 2) * 8), 1, Trim(Map.Name), QBColor(BrightRed)) Else Call DrawText(TexthDC, Int((MAX_MAPX + 1) * PIC_X / 2) - (Int(Len(Trim(Map.Name)) / 2) * 8), 1, Trim(Map.Name), QBColor(White)) End If ' Check if we are getting a map, and if we are tell them so 'If GettingMap = True Then ' Call DrawText(TexthDC, 50, 50, "Receiving Map...", QBColor(BrightCyan)) 'End If This tutorial has been tested in vanilla 3.0.3/3.0.7, and works great. I'm sure there are other ways to do this, and maybe even cleaner ways, but it works great for me. :) Feel free to post any suggestions/questions/gripes.
Remember that this was made for vanilla 3.0.3/3.0.7, so make sure you remember that if you apply this to your already modified client.. You may need to add/change this code a bit to work with a modified client.
[Edit] I redid this code from scratch today. You don't have to mess with any of the blt subroutines anymore. As you can see, the code has shrunk quite a bit, and I added some more comments... It's a little more simple than the last code I had, but you will still need to make changes to it to match your source. The description of what the code does still applies, so I didn't change any of that. Pretty much all I changed was the code, and this message. :P
Enjoy!
[Edit Again] Modified some of the description, and confirmed that this code works in 3.0.7 as well.
Also noticed a "bug" with on-screen display of typed text (It scrolls, too).. Something for you to fix on your own. :) (I'm going to use a text box :P)
[Modified Difficulty] Edited post to show actual difficulty, which I forgot to change with the new code. I chose medium because it isn't hard at all, but some people want to scroll larger maps than the picscreen, which is going to take more coding. Others want to have it stop scrolling when you reach the edge, which is more coding as well. So medium seemed right to me. :)
[Edited on 4/4/05] Added the changes required to print the map name and the text a user is typing in the proper position, rather than having it scroll with the map.
|