|
System.IO
This tutorial will focus on reading and writing from text files. Why is this important in games? Because you can store and load your game data from text files. The 2 classes that we're going to focus on are
System.IO.StreamReader and System.IO.StreamWriter - they allow us to read and write from textfiles, respectively.
Create a new program in VB.NET. At the very top (even before "Public Class Form1"), type this in:
Imports System.IO
Why are we doing this? Here's why: I told you that the StreamWriter was in System.IO. Without this Imports statement, we'd have to say
Dim SR as System.IO.StreamWriter
But since we imported it, we can just say (type this into your program)
Dim SR as StreamReader
Dim SW as StreamWriter
Declare both the variables becuase we're going to be working with both of them anyways.
StreamWriter
The first class that we're going to work with is the StreamWriter. Remember that you have to instantiate every class. So in form1_load type this in:
SW = New StreamWriter("textfile.txt")
This tells the StreamWriter that the text file that it's going to be working with is "textfile.txt"
After that line, type this in
SW.WriteLine("This is some text in a text file")
This writes the line to a text file. The next thing we have to do is save the file. It's done through a method called Flush (dont ask why its called that way :p)
SW.Flush()
Well, run your program, and exit. Now navigate to the BIN folder of your application, and you'll see a file called textfile.txt. Open the file (it'll open in notepad), and you'll see this
This is some text in a text file
Great! We've got this to work. (Simple enough huh? - we're going to deal with more of this later).
Be sure to close the file after you're done with it. Type this in:
SW.Close()
Hint: you don't really want the users of your game to edit the savegame file! (like for example, changing the enemy's health to 1 when its supposed to be 100). For this matter, just replace the instantiated ("new'd") streamreader line with this:
SW = New StreamWriter("textfile.sgm")
Use any extension you want (i think it might be limited to a certain number of charactrers). If you ever want to edit the file manually, double click it, and hit "Select a program to open this file from the list", and select notepad.
Yeah, i know this isn't much of a fix *shrug*. But there are file encryptors out there.
StreamReader
A StreamReader is a little more difficult to use than a StreamWriter when you're dealing with complex files. (Later in this tutorial, we're going to be reading from a textfile and using that to create a map(...you'll see)
For now, just type in the following 3 lines:
SR = New StreamReader("textfile.sgm")
MessageBox.Show(SR.ReadToEnd)
SR.Close()
You'll see that it works perfectly fine! Now let's get to the fun stuff!
Reading a Map File
I've created a sample map file for us to work with in this tutorial. Paste the contents of this into notepad
Paste everything below
22,16
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,2
1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,2
1,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2
1,1,1,1,2,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,2
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,2,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
Paste everything above
OK. Save that in your bin directory as test.map.
Now for an explanation of how this map file works. The first line "22,16" is the size of the map.
The 'random' numbers, seperated by commas, below it is the actual map itself.
I have various images, such as "1.jpg", "2.jpg" and "3.jpg". The program that we're going to create is going to read the data above and take the numbers, and 'convert them to images' and display them. Here's what I mean:
(These images were taken from RPG maker, they are not mine)
(1.jpg, 2.jpg, and 3.jpg)
  
Save these images (Right click & Save Target As) in your Bin folder. Create a new folder called tiles and place your images there (so they should be in bin/tiles).
The numbers up there represent the map for the game. The program will read these numbers, store these numbers into an string array called Tiles. (for example, the topleft tile "2.jpg" would be stored in Tiles(0,0) ).
OK, now let's get coding. Delete all your StreamWriter code.
Create a sub called Read. And in form1_load, type in Read().
Now let's create that sub.
Type in this line:
SR = New StreamReader("test.map")
The next thing we have to do is store the "22, 16" into a string.
Dim ln As String
ln = SR.ReadLine() 'This is where the "22,16" is
Well, we have "22,16", but how do we store that into 2 integers?
Well first we have to declare the integres to store this!
In the globals, type in
Dim NumColumns As Integer
Dim NumRows As Integer
Ok, now we have to somehow "split" the string (ln) in such a way that '22' gets stored in NumColumns, and '16' gets stored in NumRows.
The easiest way to do this is String.Split method.
Dim str() As String
str
= ln.Split(",")
Let me explain. First of all, why is str an array? Well, this is because String.Split requires it to be an array. Here's how String.Split works. It takes a charactger to split the string with (in our case, a comma) . It takes the first part of the string, and stores it in str(0) and the 2nd part of the string in str(1) and the third part of the string (there is none in our case) in str(2)..etc.
So here's how to store it:
NumColumns = str(0) - 1
NumRows = str(1) - 1
Well, im sure you understand everything except the "-1". Well, we're going to be working with an array very soon. Arrays start at 0, instead of 1. This is the reason why we have to subtract the length of the map -1 because we'd get an extra element if we don't. Don't worry if you dont understand yet - i'll show you how this works below.
Ok, we've read the map size. Now we just have to read the map itself. Remember I said that we were going to store it into an array of strings called Tiles. The Tiles array will be a 2 dimensional array
In your globals, type in the following line:
Dim Tiles(,) As String
Now go back to the Read() sub.
We're going to specify the size of the map by ReDimming the Tiles array (see Tips and Tricks tutorial if you're confused).
ReDim Tiles(NumColumns, NumRows)
Now - this is the reason why you need the "-1" for NumColums and NumRows: The Tiles array's topleft will be (0,0), not (1,1). Rather than 'wasting' 2 extra elements, we've redimmed Tiles like this:
ReDim Tiles(21,15), becuase (0,0) is considered an element, the actual size of Tiles is (22,16)
OK, go back to the Read sub, type in the following lines which store the Column and Row being read.
Dim CurrentRow As Integer
Dim CurrentColumn As Integer
Alright, now its time to actually start reading this huge monster. Remember that this 'block of text' is just a series of numbers seperated by commas.. wait, seperated by commas? That means we have to split the current line being read.
Let's pseudocode this:
ln = ReadTheLine
AString = ln.Split(",") 'Split the line being read
Tiles(currentcolumn,currentrow) = "tiles\" & AString(currentcolumn) & ".jpg" 'for example: "tiles\1.jpg"
Of course, its a little more complex. By the way, about the 3rd line. We have to use "AString(currentcolumn)" becuase AString is a split version of ln. If currentcolumn = 0 and currentrow = 0 then the code would look like this
Tiles(0,0) = AString(0) 'equivalent to "tiles\2.jpg" (see the test.map file). See how that works? - If not, just read again, or post on the forums if you really don't understand
The pseudocode above only read 1 line. We want our program to read all the lines. Here's the code below for doing so. We just simply use a loop.
Tutorial Edit:
Added Dim Line as String
Dim Line as STring
For CurrentRow = 0 To NumRows
'Read each Line
ln = SR.ReadLine()
Line = ln.Split(",")
For CurrentColumn = 0 To NumColumns
'Read each character (Go across the file)
Tiles(CurrentColumn, CurrentRow) = ("tiles\" & Line(CurrentColumn) & ".jpg")
Next
Next
Sort of hard to explain, but try plugging in numbers for current row and currentcolumn. Relate it to the pseudocode if you need help. If you need more help, post on the forums. I don't beleive that this is something that you can just read once and fully understand.
Wow you've got this far. Now.. its time to display the map! Go to form1_paint and type this in:
Dim x, y As Integer
For x = 0 To numcolumns
For y = 0 To numrows
e.Graphics.DrawImage(New Bitmap(Tiles(x, y)), x * 30, y * 30)
Next
Next
Explanation: Well first of all, im sure you understand up to the part where it says x*30 and y*30. This just simply draws all of your tiles. The x*30,y*30 are the position of each individual tile.The size of each tile is 30x30. Let's plug in numbers to demonstrate how this works:
Tile(0,0) would be drawn in position (0,0) <-- (0*30 , 0*30)
Tile(1,0) would be drawn in position (30,0) <-- (1*30,0*30)
Very similar (if not the same) to TileBased logic. A tile's Position its (tileX*tilewidth, tileY*tileheight), and a tile's TilePos is its (X/tilewidth, y/tileheight)
Run the program. It works! Now resize the form. See how there's a little bit of 'lag' (meaning it draws the tiles from left to right.. very slowly) and 'flicker' going on'
Note: the 'lag' effect could be a good "Transition" effect for a game when going from one level to another.
Well, go to form1_load and type in
setstyle(ControlStyles.DoubleBuffer, True) 'fixes the flicker
setstyle(ControlStyles.AllPaintingInWmPaint, True) 'fixes the lag, set this to false for a good transition effect
Thats about it for this tutorial (one thing i left out was reading gamedata, but the process is very similar)
Wait for the next tutorial (possibly Basic AI
for Tic Tac Toe, this will take me a while to figure out becuase I suck at AI)
The Source
Code for this tutorial is located here:
You can also locate this by
logging in to vbProgramming Forums and going to:
Tutorials
> Tutorial Source Code > Source Code
|
|