Lesson 6 - Arena with warriors in VB.NET

Visual Basic .NET OOP Arena with warriors in VB.NET

In the previous lesson, Warrior for the arena in VB.NET, we created the Warrior class. In today's tutorial, we're going to put it all together and create a fully functioning arena. The tutorial is going to be simple and will help you get some more practice working with objects.

We'll need to write some code that will manage our warriors and the messages being printed to the user. To keep things organized, we'll create an Arena object where our fight will take place. Module1.vb will only provide the necessary objects, and the Arena object will take care of the rest. Let's add the last class to the project - Arena.vb.

The class will be rather simple, it'll include three needed instances as the fields: the 2 warriors and the rolling die. These fields will be initialized from the constructor parameters. The class code will be as following (add comments accordingly):

Public Class Arena

        Private warrior1 As Warrior
        Private warrior2 As Warrior
        Private die As RollingDie

        Public Sub New(warrior1 As Warrior, warrior2 As Warrior, die As RollingDie)
                Me.warrior1 = warrior1
                Me.warrior2 = warrior2
                Me.die = die
        End Sub

End Class

We'll make the program output nice and allow the Arena class to access the console directly. We've decided that the printing would be done by the Arena class since it makes sense to do it here. If the printing was performed by warriors, the design would be flawed since the warriors would not be universal. We need a method that prints information about the round and the warriors' health to the console. The damage and defense messages will be printed with a dramatic pause so as to make the battle more intense. For this, we'd have to create a helper method. Let's start with the method that renders the information to the screen:

Private Sub Render()
        Console.Clear()
        Console.WriteLine("-------------- Arena -------------- " & vbCrLf)
        Console.WriteLine("Warriors health: " & vbCrLf)
        Console.WriteLine("{0} {1}", warrior1, warrior1.HealthBar())
        Console.WriteLine("{0} {1}", warrior2, warrior2.HealthBar())
End Sub

There's nothing to say here, you can also decorate the screen with colors if you want. Thanks to the Clear() method, which clears the console screen, we can create a nice visual layout instead of scrolling the text down all the time. The method is Private, it'll be used only within the class.

Let's create another Private method that will print messages with a dramatic pause:

Private Sub PrintMessage(message As String)
        Console.WriteLine(message)
        Thread.Sleep(500)
End Sub

The Thread class allows us to work with threads, which we will need access to in order to add the dramatic pause. We'll use the Sleep() method which puts the thread of the program to sleep for a given number of milliseconds. We'll go over threads in detail in the last couple of courses. In order for it to work, we'll have to add Imports System.Threading at the beginning of the Arena.vb file.

Now, let's move on to the battle part. The Fight() method will be parameterless and won't return anything. There will be a loop inside calling the warriors' attacks in turns and printing the information screen with the messages. The method would look something like this:

Public Sub Fight()
        Console.WriteLine("Welcome to the Arena!")
        Console.WriteLine("Today {0} will battle against {1}!{2}", warrior1, warrior2, vbCrLf)
        Console.WriteLine("Let the battle begin...")
        Console.ReadKey()
        ' fight loop
        While warrior1.Alive() And warrior2.Alive()
                warrior1.Attack(warrior2)
                Render()
                PrintMessage(warrior1.GetLastMessage()) ' attack message
                PrintMessage(warrior2.GetLastMessage()) ' defense message
                warrior2.Attack(warrior1)
                Render()
                PrintMessage(warrior2.GetLastMessage()) ' attack message
                PrintMessage(warrior1.GetLastMessage()) ' defense message
                Console.WriteLine()
        End While
End Sub

The code prints an introductory line and executes the fighting loop after the user presses any key. Then, the program enters a while loop that repeats as long as both warriors are alive. The first warrior attacks its opponent and his attack internally calls the other warrior's defense. After the attack, we render the information screen. The messages about the attack and defense will be printed by our PrintMessage() method which makes a dramatic pause after the printing. The same thing will happen with the other warrior.

Let's move back to Module1.vb. We create'll the needed instances and call the Fight() method on the arena:

' creating objects
Dim die As RollingDie = New RollingDie(10)
Dim zalgoren As Warrior = New Warrior("Zalgoren", 100, 20, 10, die)
Dim shadow As Warrior = New Warrior("Shadow", 60, 18, 15, die)
Dim arena As Arena = New Arena(zalgoren, shadow, die)
' fight
arena.Fight()
Console.ReadKey()

You can change the values to whatever you'd like. Here's what the program looks like at runtime:

Console application
-------------- Arena --------------

Warriors health:

Zalgoren [##                  ]
Shadow [                    ]
Shadow attacks with a hit worth 19 hp
Zalgoren blocked the hit

The result is quite impressive. Objects communicate with each other, the health bar decreases as expected, the experience is enhanced by a dramatic pause. However, our arena still has two issues:

  • In the fight loop, the first warrior attacks the other one. Then, the second warrior attacks the first one, even if he has already been killed by the first warrior. Look at the screenshot above, at the end, Shadow attacked even though he was dead. The while loop terminated just after that. There are no issues with the first warrior, but we have to check whether the second warrior is alive before letting him attack.
  • The second problem is that the warriors always fight in the same order so "Zalgoren" has an unfair advantage. Let's leave the turn order up to chance by using the rolling die. Since there will always only be two warriors, we could tell the program to set the warriors' turns based off of whether the rolled number is less or equal to half of the number of die sides. Meaning that if it rolls a number less than 5 on a ten-sided die, the second warrior goes first, otherwise, the first one does.

We still have to add a way to swap the warriors places depending on which one goes next. Since we know about references in VB.NET, let's just create 2 variables that will contain warrior instances. We'll assign warrior1 and warrior2 to these variables. If the rolling die condition mentioned above applies, we'll assign warrior2 to w1 and vice versa, then the second warrior will begin. This way, we won't have to change the loop code and it all remains nice and clear.

Updated version preventing the second warrior from attacking if he's dead and letting the warriors turns be chosen at random:

Public Sub Fight()
        ' The original order
        Dim w1 As Warrior = warrior1
        Dim w2 As Warrior = warrior2
        Console.WriteLine("Welcome to the Arena!")
        Console.WriteLine("Today {0} will battle against {1}!{2}", warrior1, warrior2, vbCrLf)
        ' swapping the warriors
        Dim warrior2Starts As Boolean = (die.Roll() <= die.GetSidesCount() / 2)
        If warrior2Starts Then
                w1 = warrior2
                w2 = warrior1
        End If
        Console.WriteLine("{0} goes first!{1}Let the battle begin...", w1, vbCrLf)
        Console.ReadKey()
        ' fight loop
        While w1.Alive() And w2.Alive()
                w1.Attack(w2)
                Render()
                PrintMessage(w1.GetLastMessage()) ' attack message
                PrintMessage(w2.GetLastMessage()) ' defense message
                If w2.Alive() Then
                        w2.Attack(w1)
                        Render()
                        PrintMessage(w2.GetLastMessage()) ' attack message
                        PrintMessage(w1.GetLastMessage()) ' defense message
                End If
                Console.WriteLine()
        End While
End Sub

Now, let's take her for a spin!

Console application
-------------- Arena --------------

Warriors health:

Zalgoren [###########         ]
Shadow [                    ]
Zalgoren attacks with a hit worth 27 hp
Shadow defended against the attack but still lost 9 hp, and died

Congratulations! If you've gotten this far and have actually read through, you have the basis of object-oriented programming and should be able to create reasonable applications :)

In the next lesson, Inheritance and polymorphism in VB.NET, we'll explain object-oriented programming in further detail. We mentioned that OOP is based on three concepts - encapsulation, inheritance, and polymorphism. We're already familiar with the encapsulation, the other two await you in the next lesson...


 

 

Article has been written for you by Michal Zurek
Avatar
Do you like this article?
1 votes
Activities (8)

 

 

Comments

Avatar
Chen 琛
Member
Avatar
Chen 琛:24. April 9:27

Have been read the tutorials before register. Love those! Though the arena app are not running. Errors return

 
Reply 24. April 9:27
Avatar
David Capka
ICT.social team
Avatar
Replies to Chen 琛
David Capka:24. April 10:15

Hi Chen, we're glad you like it :) Thanks for reporting the issue, we'll fix it.

Reply 24. April 10:15
You can walk through a storm and feel the wind but you know you are not the wind.
To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

2 messages from 2 displayed.