Movement and Player Statistics in a VB.NET Text-Based Game

Now that we've drawn the map and the player on the screen, we need to work on movement. Movement involves a number of things. We'll also need to give our player some statistics, such as health, attack, and defense. Keep reading for the lowdown as the text game we're creating to learn VB.Net really starts taking shape.

Contributed by
Rating: 4 stars4 stars4 stars4 stars4 stars / 8
July 15, 2008
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Accepting User Input

First, we need to allow the user to press a key. Second, we need to check to see if this movement is valid. For example, we don't want the player to walk on top of a wall. Checking to see if the movement is valid only involves checking the Passable property of the destination tile. Third, we need to actually make the movement. This involves drawing the player on the new tile, but it also involves erasing the player on the old tile.

Finally, this all needs to be contained within a loop. After all, we want the user to be able to continue making movements, and each time, the game should go through the same steps to respond to the movement.

The first thing we need to do is set up the loop. For now, an infinite While loop will work, but later we'll want to check for certain situations—such as when the player is dead. In this loop, we'll want to accept a keypress from the user. The keypress will be stored in a variable, so we'll need to define this variable. Also, we need to make sure that the cursor is not visible, and that the pressed key is not displayed in the console. Put the game loop at the bottom of Main:

Console.CursorVisible = False

Dim input As ConsoleKeyInfo


While True

 input = Console.ReadKey(True)

End While

When you run the game, there will now be no cursor visible, and the console will not display anything you type (recall that this is accomplished by passing True to ReadKey). Now that we have the key stored, we need to check it against valid inputs. If the input is valid, then we need to perform the associated action. Otherwise, we need to go back and let the user try again. The checking will be done in a Select statement. Right now, let's put in a quit action, which will be escape. Pressing this key will exit the game immediately. Put this at the bottom of the loop:

Select Case input.Key

 Case ConsoleKey.Escape

 Exit While

 Case Else

 Continue While

End Select

Notice how, if the user has pressed the escape key, we exit the While loop. Otherwise, we use the Continue statement. The Continue statement immediately moves to the next iteration of the loop. In this case, we use it to allow the user to press another key.

Adding Movement

Now it's time to add movement. We need to first set up a function, TryMove, that will try to move an Entity (not necessarily the player) a certain number of spaces. This function will accept the entity to be moved, the change in the entity's X value, and the change in the entity's Y value. It will then check to see if the move is valid. If it is valid, then the movement will be made, and True will be returned. If the movement cannot be made, then False will be returned. We need TryMove to return these values because we don't want to end the player's turn if he tries to make an invalid move. Rather, we want him to be able to try again before the other entities get their turns.

So far, we've never actually worked with functions before. They're very simple, however. A Func, as it is termed in the language, is similar to a Sub, only we must return a value, and we can explicitly specify what type that value will be.

We're also going to need to create yet another method called RedrawTile. DrawTile will draw a tile, but since it was originally built to be used to draw the entire map, it assumes that the cursor is already in the correct position. RedrawTile will manually set the cursor in the proper position and then call DrawTile. First, though, here is TryMove, which calls RedrawTile:

Function TryMove(ByVal toBeMoved As Entity, ByVal xChange As Integer, ByVal ychange As Integer) As Boolean

 Dim x As Integer = toBeMoved.X + xChange

 Dim y As Integer = toBeMoved.Y + ychange

 If map(x, y).Passable = True Then

RedrawTile(toBeMoved.X, toBeMoved.Y)

toBeMoved.X = x

toBeMoved.Y = y

DrawEntity(toBeMoved)

 Return True

 End If

 Return False

End Function

The function accepts, as I said before, the change in the entity's X value and the change in the entity's Y value. So, if the entity is trying to move right, then the change in the X value is 1, and the change in the Y value is 0. If the entity is trying to move up, then the change in the X value is 0, and the change in the Y value is -1. The changes are added to the player's current location to determine the destination tile. The tile is then checked to see if the player can walk on it, and if the player can, then the player's old location is redrawn, and the player is drawn on the new location.

Now let's write RedrawTile, which is very simple, as was already noted:

Sub RedrawTile(ByVal x As Integer, ByVal y As Integer)

Console.SetCursorPosition(x, y)

DrawTile(x, y)

End Sub

Great. Now the methods required for movement are in place, and we can wire them up to our loop. Recall how I said that the player's turn will only be used up if the player has made a move. This is determined by what TryMove returned. We're going to need a Boolean variable to store the value returned by TryMove. Add this definition before the Select statement:

Dim playerMoved As Boolean = False

We assume that the player has not made a move. If the player does indeed made a move, then we can change this. This also eliminates the need for the Case Else block, so you can go ahead and delete it. It will be replaced by a conditional that checks to see whether or not the player has moved. If the player has not moved, then we'll need to immediately move to the next iteration, just like we did in the Case Else block. Put the conditional below End Select:

If Not playerMoved Then

 Continue While

End If

Now we can check for movement keys and respond accordingly. We'll use the numpad for movement. Here's what the entire Select block should now look like:

Select Case input.Key

 Case ConsoleKey.Escape

 Exit While

 Case ConsoleKey.NumPad8

playerMoved = TryMove(player, 0, -1)

 Case ConsoleKey.NumPad2

playerMoved = TryMove(player, 0, 1)

 Case ConsoleKey.NumPad4

playerMoved = TryMove(player, -1, 0)

 Case ConsoleKey.NumPad6

playerMoved = TryMove(player, 1, 0)

End Select

Above, we check for movement keys and then call TryMove, passing the appropriate values. The result of the move is stored in playerMoved. Run the program and press the directional keys on the numpad. The player should now move around the map.

Player Statistics

Now that the player can move, how about giving him some attributes such as health, attack and defense? Since these attributes are not specific to the player alone, let's add them to the Entity class as fields and properties. Attack and defense can be represented in a single field and a single property each, but health needs two fields and properties, one set for the current health, and another set for the maximum available health. Place all of this inside of the Entity class:

Private _health As Integer

Private _maxHealth As Integer

Private _attack As Integer

Private _defense As Integer

Public Property Health() As Integer

 Get

 Return _health

 End Get

 Set(ByVal value As Integer)

_health = value

 End Set

End Property

Public Property MaxHealth() As Integer

 Get

 Return _maxHealth

 End Get

 Set(ByVal value As Integer)

_maxHealth = value

 End Set

End Property

Public Property Attack() As Integer

 Get

 Return _attack

 End Get

 Set(ByVal value As Integer)

_attack = value

 End Set

End Property

Public Property Defense() As Integer

 Get

 Return _defense

 End Get

 Set(ByVal value As Integer)

_defense = value

 End Set

End Property

This also means that we have to modify Entity's constructor to accept values for each of the fields:

Public Sub New(ByVal name As String, ByVal symbol As Char, _

 ByVal color As ConsoleColor, _

 ByVal x As Integer, ByVal y As Integer, _

 ByVal health As Integer, _

 ByVal attack As Integer, _

 ByVal defense As Integer)

_name = name

_symbol = symbol

_color = color

_x = x

_y = y

_health = health

_maxHealth = health

_attack = attack

_defense = defense

End Sub

And then we have to modify Adventurer's constructor to pass default values to Entity's new constructor:

Public Sub New(ByVal name As String, ByVal x As Integer, _

 ByVal y As Integer)

 MyBase.New(name, "@", ConsoleColor.Cyan, x, y, 10, 1, 1)

End Sub

Displaying Properties


Now that we've added some properties to the player, it would be a good idea to display these somewhere on the screen so that the user can keep an eye on their values. We can wrap this user interface code into a new method, DrawStatBox. This method will, of course, go into the Game module. The player's statistics will be displayed to the right of the map, along with the player's name:

Sub DrawStatBox()

Console.SetCursorPosition(61, 1)

Console.Write(player.Name)

Console.SetCursorPosition(61, 3)

 Console.Write("Health: {0}/{1}", player.Health, _

player.MaxHealth)

Console.SetCursorPosition(61, 4)

 Console.Write("Attack: {0}", player.Attack)

Console.SetCursorPosition(61, 5)

 Console.Write("Defense: {0}", player.Defense)

End Sub

Above the game's While loop, around the call to DrawMap, place a call to the new DrawStatBox method:

DrawStatBox()

When you start the game up, a the player's name and statistics should display to the right of the map.

Next, we need to work on other entities besides the player. We'll cover that next week, in the last article of this series. You won't want to miss it!

blog comments powered by Disqus
VISUAL BASIC.NET ARTICLES

- Basic Form Properties and Modality in VB.NET
- Multiple Document Interfaces in Visual Basic
- Visual Basic for Beginners
- ASP.NET Image to PDF with VB.Net
- MySQL in ASP.NET: Mono using VB.NET
- AsyncFileUpload File Type and File Size Vali...
- Visual Studio: Adding Functionality and Style
- Clocks and Countdowns
- User-defined Functions using Visual Basic Ap...
- Understanding Object Binding in VBA
- Mastering the Message Box
- Testing a Windows Forms Application
- Using Visual Basic.NET Features to Code a Wi...
- Correcting Code in a Windows Forms Applicati...
- Write Readable Code and Comments for Windows...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 5 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials