microsoft visual basic game programming for teens phần 5 docx

40 426 0
microsoft visual basic game programming for teens phần 5 docx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Filling the Screen with Tiles The DrawTiles subroutine copies tiles from the tile palette image (think of a painter’s paint palette as the source of color in this analogy) onto the scroll buffer, a surface image that is just slightly larger than the screen resolution. It does this to take into account the tile over- lap that may occur at some resolutions. Public Sub DrawTiles() Dim tilex As Integer Dim tiley As Integer Dim columns As Integer Dim rows As Integer Dim X As Integer Dim Y As Integer Dim tilenum As Integer ‘calculate starting tile position ‘integer division drops the remainder tilex = ScrollX \ TILEWIDTH tiley = ScrollY \ TILEHEIGHT ‘calculate the number of columns and rows ‘integer division drops the remainder columns = WINDOWWIDTH \ TILEWIDTH rows = WINDOWHEIGHT \ TILEHEIGHT ‘draw tiles onto the scroll buffer surface For Y = 0 To rows For X = 0 To columns ‘*** This condition shouldn’t be necessary. I will try to ‘*** resolve this problem and make the change during AR. If tiley + Y = mapheight Then tiley = tiley - 1 tilenum = mapdata((tiley + Y) * mapwidth + (tilex + X)) DrawTile tiles, tilenum, TILEWIDTH, TILEHEIGHT, 16, scrollbuffer, _ X * TILEWIDTH, Y * TILEHEIGHT Next X Next Y End Sub For the sake of consistency, let me show you the DrawTile subroutine here because it is called by the preceding subroutine to draw each tile. There is an interesting way to opti- mize this code that you may consider down the road when you are working on your own Chapter 8 ■ Advanced Scrolling Techniques140 complete game. The CopyRects function will draw as many images as you specify in the rec- tangle and point arrays. While the DrawTiles subroutine calls DrawTile for every single tile, a good optimization would be to utilize this advanced capability in CopyRects to draw all of the tiles with a single call. I recommend you only keep this in mind for later, as there is no point thinking about optimization this early. Public Sub DrawTile( _ ByRef source As Direct3DSurface8, _ ByVal tilenum As Long, _ ByVal width As Long, _ ByVal height As Long, _ ByVal columns As Long, _ ByVal dest As Direct3DSurface8, _ ByVal destx As Long, _ ByVal desty As Long) ‘create a RECT to describe the source image Dim r As DxVBLibA.RECT ‘set the upper left corner of the source image r.Left = (tilenum Mod columns) * width r.Top = (tilenum \ columns) * height ‘set the bottom right corner of the source image r.Right = r.Left + width r.Bottom = r.Top + height ‘create a POINT to define the destination Dim point As DxVBLibA.point ‘set the upper left corner of where to draw the image point.X = destx point.Y = desty ‘draw the source bitmap tile image d3ddev.CopyRects source, r, 1, dest, point End Sub Drawing the Scroll Window After you have filled the scroll buffer with tiles for the current scroll position within the game world, the next thing you must do is actually draw the scroll buffer to the screen. Direct Partial-Tile Scrolling 141 This is where things get a little interesting. The scroll buffer is filled only with complete tiles, but it is from here that the partial tiles are taken into account. This is interesting because the whole tiles were drawn onto the scroll buffer, but the partial tiles are handled when drawing the scroll buffer to the screen. The partialx and partialy variables are given the result of the modulus calculation, and these values are then used as the upper-left cor- ner of the scroll buffer that is copied to the screen. I don’t usually like to use global variables in a subroutine, because good coding practice produces subroutines that are independent and reusable from one project to the next. The DrawTile subroutine is much more independent than DrawScrollWindow , but it also uses the global mapdata array. In the final analysis, some of this can’t be helped if you want the game to run at a fast frame rate, because passing variables to subroutines is a very time- consuming process, and you want the game to run as fast as possible. Remember, the scrolling window is just the beginning. The rest of the game still has to be developed, and that includes a lot of animated sprites for the player’s character, non- player characters (NPCs), plus buildings, animals, and any other objects that appear in the game. The bottom line is that the scroller needs to be as efficient as possible. (Yes, even with today’s fast PCs, the scroller needs to be fast—never use the argument that PCs are fast to excuse poorly written code!) Therefore, the DrawScrollWindow subroutine uses the global variables for the map data, tile source bitmap, the scroll buffer, and the back buffer. To pass these values to the subroutine every time consumes too many processor cycles, slowing down the game. Public Sub DrawScrollWindow() Dim r As DxVBLibA.RECT Dim point As DxVBLibA.point Dim partialx As Integer Dim partialy As Integer ‘calculate the partial sub-tile lines to draw partialx = ScrollX Mod TILEWIDTH partialy = ScrollY Mod TILEHEIGHT ‘set dimensions of the source image r.Left = partialx r.Top = partialy r.Right = partialx + WINDOWWIDTH r.Bottom = partialy + WINDOWHEIGHT ‘set the destination point point.X = 0 point.Y = 0 Chapter 8 ■ Advanced Scrolling Techniques142 ‘draw the scroll window d3ddev.CopyRects scrollbuffer, r, 1, backbuffer, point End Sub Loading an Exported Mappy File In the last chapter you learned a trick for importing Mappy data files into a Visual Basic program. That trick was to paste the map data into a Visual Basic source code file and then convert it to one big string constant. You then learned how to parse the string and convert the comma-separated map data values into an integer array. You can still use that method if you wish, although it is much more convenient to let the program load a map file directly from disk rather than going through all the trouble of formatting and stuffing the data into a string constant in the source code file. The code that loads a text file exported by Mappy is fairly simple because it mimics the process used in the previous chapter, which converts a large string into an integer array. The only difference is that this time the data values are read from a text file; otherwise the code is similar to the parsing code from the previous chapter. In fact, you may recognize most of the code in LoadMap because the parsing code is the same. There is just one thing that you must do first! You have to edit the text file and insert two values at the very beginning of the file, specifying the width and height of the map, in number of tiles. Figure 8.5 shows an example file exported from Mappy, and I have added two comma-separated values to the very beginning of the file: 25,18, (be sure to include the trailing comma as well). This text is picked up by the LoadMap subroutine when it opens the file, so that it can automatically read the size of the map instead of you having to spec- ify the size in source code. The code that reads these two values is shown here: tip In Chapter 12, “Walking Around in the Game World,” I will show you how to load a binary map file that loads at least 10 times faster than the text file used in this chapter. But it’s best to take this process one step at a time, as it is natural to start with a text format and then graduate up to the faster binary format as you come to learn how tiling works. Input #num, mapwidth, mapheight Here is the complete source code for the LoadMap subroutine (which loads a text file filled with comma-separated tile values): Public Sub LoadMap(ByVal filename As String) Dim num As Integer Dim line As String Dim buffer As String Loading an Exported Mappy File 143 Dim s As String Dim value As String Dim index As Long Dim pos As Long Dim buflen As Long ‘open the map file num = FreeFile() Open filename For Input As num ‘read the width and height Input #num, mapwidth, mapheight ‘read the map data While Not EOF(num) Line Input #num, line buffer = buffer & line Wend Chapter 8 ■ Advanced Scrolling Techniques144 Figure 8.5 Saving the new Visual Basic source code (module) file. ‘close the file Close num ‘prepare the array for the map data ReDim mapdata(mapwidth * mapheight) index = 0 buflen = Len(buffer) ‘convert the text data to an array For pos = 1 To buflen ‘get next character s = Mid$(buffer, pos, 1) ‘tiles are separated by commas If s = “,” Then If Len(value) > 0 Then ‘store tile # in array mapdata(index) = CInt(value - 1) index = index + 1 End If ‘get ready for next # value = “” s = “” Else value = value & s End If Next pos ‘save last item to array mapdata(index) = CInt(value - 1) End Sub The ScrollWorld Program Let’s put all this code together into a complete program to see how this scrolling technique works in the real world. Create a new project called “ScrollWorld” and add the “DirectX 8 for Visual Basic Type Library” reference to the project using the Project, References menu option. Next, I’d like to do something a little differently in this program from what you have done in previous chapters. The ScrollWorld Program 145 Aligning Tiles to the Scroll Buffer There is one factor that you must take into consideration while designing the screen layout of your game with a scrolling window. The size of the scrolling window must be evenly divisible by the size of the tiles, or you end up with a floating overlap at the uneven edge. This is an issue that I considered solving in the scrolling code itself. I decided that it would require too much extra logic to fix up the right and bottom edges of the scrolling window when it is not evenly divisible by the tile width and height. The scroller works with tiles other than 64 × 64; the important thing is that the widths and heights are evenly divisible. If using a screen resolution of 640 × 480 with 64 × 64 tiles, your width is fine, but height is a problem. Cut off the bottom of the scroll window at 448 (which is 7 tiles high), leav- ing the remaining 32 pixels unused at the bottom. This shouldn’t be a problem because you can use that screen real estate for things like an in-game menu system, player status information, or perhaps in-game dialog. (Don’t confuse this with the discussion earlier about partial tiles, because the partial tile drawing is different than the overall alignment of tiles on the scroll buffer surface.) Figure 8.6 illustrates how you could position the scroll window, leaving a small portion at the bottom of the screen, which might be used for other things. I recommend limiting the scrolling window to a portion of the screen anyway, as it makes more sense than displaying game information over the top of the scrolling window. This Chapter 8 ■ Advanced Scrolling Techniques146 Figure 8.6 The scrolling window should be evenly divisible by the tile size. holds true unless you are doing something cool, like drawing transparent windows over the top of the background (which is possible using Direct3D textures and is discussed in the next chapter). Figure 8.7 shows the ScrollWorld program running at 800 × 600, with some blank space showing at the right and bottom edges of the scroll window. This is intentional, keeping the scroller code as efficient as possible (without too many conditions placed upon it). By simply making the scroll window evenly divisible by the tiles, there is no special-case code required to keep the scrolling tiles in view beyond the scroll window. The next screenshot of ScrollWorld, in Figure 8.8, shows the program running at a reso- lution of 640 × 480. As you can see, the screen was evenly divisible with the 64 × 64 tiles, so the right edge is flush with the screen, while the bottom edge (in which 480 is not evenly divisible by 64) leaves a portion of the screen unused. Finally, the screenshot in Figure 8.9 shows the program running at 1024 × 768, with an even distribution of tiles from left to right and top to bottom, completely filling in the screen. Although this particular resolution does work well with this tile size, that shouldn’t be your goal with a scrolling game; a portion of the screen is used for other aspects of the game, anyway (such as status information or the score). Once you have the main screen The ScrollWorld Program 147 Figure 8.7 The ScrollWindow program cannot uniformly fill the 800 × 600 screen. Chapter 8 ■ Advanced Scrolling Techniques148 Figure 8.8 The ScrollWindow program fills most of the screen at 640 × 480. Figure 8.9 At 1024 × 768, the scroller fills the entire screen evenly. designed for your game, you have a better idea about how large of a scroll window you need. The ScrollWorld Source Code At this point, it is becoming somewhat tedious to type in the common reusable code from one project to the next, so I’d like to show you how to add another source code file to your project for those reused subroutines. Not only does this make the code more reusable, but it also organizes your game’s source code. There will be four files in the project overall by the time you’re done putting it together: ■ Form1.frm ■ Globals.bas ■ Direct3D.bas ■ TileScroller.bas Adding the Globals.bas File First of all, I need to explain a little bit about how Visual Basic projects work. You can share a constant, variable, or subroutine with the source code files in your project as long as those sharable items are located inside a Module file. You can’t share items in a Form, because forms are treated like classes (or objects), which can’t share code. Therefore, any- thing you want to make reusable has to be stored in a .BAS module file. Let’s start with the most obvious code that should be shared with the entire project: the constants. 1. Add a new file to the project by opening the Project menu and selecting Add Module. You see a blank source code window with a new file added to your project. The new file is called Module1. 2. Looking over at the Properties window (press F4 if it is not visible), change the name of Module1 using the Properties window. 3. Change the name of the file to Globals and click Save from the File menu. You see the dialog box shown in Figure 8.10, with the option to change the file- name. 4. Go ahead and accept the filename Globals.BAS. 5. Save the file. As is always the case when restructuring and organizing a project, extra work up front results in more code listings than you may be used to. The real benefit is this: After you have put together this project, you can just copy these source code files to your new Visual The ScrollWorld Program 149 [...]... code moved out of Form1, the source code for ScrollWorld is really short! ‘ ‘ Visual Basic Game Programming for Teens ‘ Chapter 8 - ScrollWorld program ‘ ‘ Requires: Globals.bas, Direct3D.bas, TileScroller.bas ‘ Option Explicit Option Base 0 Private Sub Form_Load() ‘set up the main form Form1.Caption = “ScrollWorld” Form1.ScaleMode = 3 Form1.width = Screen.TwipsPerPixelX... 150 Chapter 8 ■ Advanced Scrolling Techniques Figure 8.10 Saving the new Visual Basic source code (module) file Basic games in the future and reuse the files, without having to type or even copy-paste any of the code again It is all available for immediate use in these files Incidentally, after you have created a sharable Visual Basic module (.BAS) file, you can add... sprites in a role-playing game, although you might find this useful in a space-based shooter or other type of arcade game note I used sprite rotation to draw the tanks in my game Tank War in Game Programming All In One, 2nd Edition Since each tank had 8 frames of animation and used 8 directions for movement, that would have required 64 images for each tank By using sprite rotation, the game only needed the... the sprite handler developed in this chapter Here are the first few lines of code for Sprite.bas Note that I have inserted comments specifying that you should type in the subroutines already covered earlier in this chapter (so I won’t have to list them again) ‘ ‘ Visual Basic Game Programming for Teens ‘ Sprite Support File ‘ Option Explicit Option Base... a sharable Visual Basic module (.BAS) file, you can add it to a new project by selecting Project, Add File Now type the following code into Globals.BAS: ‘ ‘ Visual Basic Game Programming for Teens ‘ Globals File ‘ Option Explicit Option Base 0 ‘Windows API functions Public Declare Function GetTickCount Lib “kernel32” () As Long ‘colors Public Const... SpriteTest project: 1 Open Visual Basic and create a new project If necessary, open the File menu and select New Project 2 Add a reference to DirectX 8 for Visual Basic Type Library using the Project, References menu option 3 Save the project, giving it the name SpriteTest Don’t skip the following important step! 173 174 Chapter 9 ■ Core Technique: Drawing Sprites Figure 9 .5 The DrawSprite program demonstrates... sprite source file to the project: 1 Open Visual Basic and create a new project 2 Add a reference to DirectX 8 for Visual Basic Type Library using the Project, References menu option The SpriteTest Program 3 After you have a new project waiting, open the Project menu again and select Add Module This module is named Sprite.bas and contains the source code for the sprite handler developed in this chapter... way to do graphics: using Direct3D Direct3D is a highperformance 3D rendering library that powers most of the games created today for the Windows platform But how suited is Direct3D for handling 2D sprites? You learned in previous chapters that Direct3D lets you use surfaces to draw tiles on the screen, and thus create a tile-based scrolling game world But what about drawing sprites, which must be... without having to open up several files to make changes to the globals Adding the Direct3D.bas File Next, I show you how to move the common Direct3D code into a Visual Basic module file to get it out of your main code listing in Form1 1 In Visual Basic, open the Project menu and select the Add Module option 2 After the new module file has been added to your project, rename it to Direct3D using the Properties... is like a custom data type that you can create yourself, consisting of other minor data types (like Integer, Long, String, and so on) Visual Basic uses the Type keyword to define a structure (which is called struct in the C language) A custom data type in Visual Basic for handling sprites might look something like this: ‘sprite properties Public Type TSPRITE spriteObject As D3DXSprite x As Long y As . sharable Visual Basic module (.BAS) file, you can add it to a new project by selecting Project, Add File. Now type the following code into Globals.BAS: ‘ ‘ Visual Basic Game Programming for Teens ‘. shorter. In fact, with the support code moved out of Form1 , the source code for ScrollWorld is really short! ‘ ‘ Visual Basic Game Programming for Teens ‘ Chapter 8 - ScrollWorld program ‘ ‘ Requires:. = 8 game world size Public Const GAMEWORLDWIDTH As Long = 1600 Public Const GAMEWORLDHEIGHT As Long = 1 152 Chapter 8 ■ Advanced Scrolling Techniques 150 Figure 8.10 Saving the new Visual Basic

Ngày đăng: 13/08/2014, 22:21

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan