Machaira's Blog

Jim Perry's Blog at vbCity

vbCity Blogs moved to:
http://cs.vbcity.com/blogs
  Home :: Syndication  :: Login

AprMay 2013Jun
SMTWTFS
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

Articles

Archives

.NET Development Links

Game Development Links

Miscellaneous Links

One of the cool new features in .NET 2.0 is Generics. Any game with a lot of sets of items might make good use of Generics. For an RPG, one of the most item based genres IMO, generics can come in very handy. We'll take a quick look at one way.

One of the “goals” in many RPGs is finding “phat lewt” :) A character has to have a way of carrying around all the stuff they find in the dungeons they may raid. From a programming standpoint, a Collection of objects is an easy way to do this. Unfortunately, most Collection classes don't allow you to specify the types of items that can be put in them. For instance, the following is perfectly legal:

Public Class CollectionEntity

 

    Private _inventory As ArrayList

 

    Public Sub New()

        _inventory = New ArrayList

    End Sub

 

    Public Property Inventory() As ArrayList

        Get

            Return _inventory

        End Get

        Set(ByVal value As ArrayList)

            'read only

        End Set

    End Property

 

End Class

 

While this is perfectly legal, it means that you never know what kind of item you're getting back from the inventory. It also means that you'd have to write code to allow only certain items to be added to the inventory. Generics make both of these a little easier. Consider the following:

Public Class Entity

 

    Private _inventory As List(Of BaseItem)

 

    Public Sub New()

        _inventory = New List(Of BaseItem)

    End Sub

 

    Public Property Inventory() As List(Of BaseItem)

        Get

            Return _inventory

        End Get

        Set(ByVal value As List(Of BaseItem))

            'read only

        End Set

    End Property

 

End Class

 

With a Generic List, we know that we’ll always be getting back a BaseItem class object (or a object of a class that derives from BaseItem, as we’ll see shortly). Also, any attempt to add an object that isn’t a BaseItem object (or one that derives from BaseItem) will result in an exception being thrown (as we’ll also see). We get this functionality with only a couple of characters of extra code being written.

 

We’ll define BaseItem as:

 

Public Enum ItemType

    Armor

    Potion

    Scroll

    Weapon

    Money

End Enum

 

Public MustInherit Class BaseItem

 

    Inherits Object

 

    Private _ID As Guid

 

    Private _type As ItemType

 

    Private _name As String

    Private _description As String

 

    'property statements here

 

    Public Sub New()

        _ID = Guid.NewGuid

    End Sub

End Class

 

We’ll also derive an Item class from it (you’ll see why in a moment):

Public MustInherit Class Item

 

    Inherits BaseItem

 

    Protected _cost As Integer

    Protected _magical As Boolean

 

    Public MustOverride Function Use(ByRef target As Object, ByRef wielder As Entity) As Boolean

 

End Class

 

Why do we have an additional class? We use the two classes for different types of items. In the case of money, it doesn’t have a cost or magical property (normally) so we derive it from BaseItem. The other items we’ll derive from Item. Note the Use function which we’ve declared MustOverride. Since each item is used differently, we don’t have the implementation in the base class (we could, but it would be very messy ;) ), but we want to make sure the derived classes have a function that allows the items to be used. Let’s take a look at adding items to an entity:

 

Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click

 

Dim obj As Object

 

      Select Case lstItems.SelectedItem.ToString.ToLower

 

            Case "armor"

                obj = New Armor

            Case "potion"

                obj = New Potion

            Case "weapon"

                obj = New Weapon

            Case "scroll"

                obj = New Scroll

            Case "money"

                obj = New Money

      End Select

 

      _entity.Inventory.Add(obj)

 

End Sub

 

So what would happen if we were to try to add something to the inventory that didn’t derive from one of the parent classes? Let’s add a Spell class:

 

Public Class Spell

 

    Private _ID As Integer

    Private _name As String

    Private _description As String

 

    'property statements here

 

End Class

 

and then try to add an instance of the class to our inventory:

 

Private Sub btnBadAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBadAdd.Click

 

    Dim obj As Object

 

    obj = New Spell

 

    _entity.Inventory.Add(obj)

 

End Sub

 

The error we get would be:

 

 

 

The other benefit from using a Generic List is the auto-casting:

 

Private Sub btnShowID_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShowID.Click

 

    MessageBox.Show(_entity.Inventory.Item(lstAddedItems.SelectedIndex).ID.ToString)

 

End Sub

 

Note that the item’s ID property is available to us without having to cast the inventory item to a BaseItem. To me, this is a pretty cool thing.

 

 

Summary

 

Generics can be very useful in certain situations, making your coding life easier and more organized. If you have a game (or any application) that will be dealing with a lot of groups of different types of objects, look into Generics.

 

If you want to check out the full source for this article, you can grab it from here - http://home.comcast.net/~machaira/GenericItems.zip

posted on Monday, January 16, 2006 11:33 AM