Object Oriented Inventory & Item Management in Heroic Adventure!

Like any good dungeon crawl, part of the fun is finding various items of treasure or equippable items such as armor or weaponry. This is how I do it in HA!

Keeping track of your stuff…
When a new dungeon level is initially generated, items are randomly generated and scattered throughout the level. Each of these items is an individual object with properties that define any special attributes the item may possess. These attributes may include magical bonuses, weight, effect duration, damage, etc.

Once an item is picked up by the player (or a monster, more on that later) it is added to the player’s inventory, at which point we check to see if the player already has one of that item. If so, then increment the quantity property of the existing object in inventory and destroy the other object, as it is no longer needed. This assumes they are identical items, such as two non-magical swords or potions of the same type (healing, for example). Special magic items with unique properties get handled differently.

Now that our hero has 2 or 3 swords in his inventory, he may decide to equip one of them. (Some heroic classes, such as a Ranger or Barbarian might even equip more than one, i.e. as a sword in each hand.) When removing an item from inventory, we simply decrement the quantity property of the object in inventory and then create a new object of the specific instance of the item, which get assigned to an equippable body slot.

Dropping an item works much like equipping it. When dropping an item just decrement the quantity and create a new object of the same type on the ground at your feet. In a case where we only have one of an item in inventory, we don’t need to alter the quantity, or create a new one. We just assign it to it’s new position (if equipped) or map location (if dropped).

Ok, so where does all this stuff actually get stored?
Your backpack is really nothing more complex than an arraylist. (For those of you not familiar with the term, an arraylist is a very cool object in .NET that acts as a container for other objects. It’s far superior to an array because all the objects can be of disparate types, and you don’t have to predefine how big it is. It grows as you add stuff to it.) Once you have your backpack (arraylist) created, dropping an item into it is as simple as: Backpack.add(sword) or Backpack.add(leatherboots)

For now, just assume these are the names of objects created elsewhere. Note that we aren’t using quotation marks around the item name, this isn’t a string description but the actual name of the object. It could just as easily be Backpack.add(FlamingSwordofDoom) if that’s the name of one of your item objects.

When leaving stuff on the ground (either at level creation or as the result of dropping something from inventory, we use a slightly different structure. The level map is essentially a giant array of type gridcell. Gridcell is a custom structure that contains info about each square of the map. (Remember roguelike games are essentially top-down, tile-based games…) Gridcell contains information such as tiletype {rock, wall, floor, door, etc} and items which is another arraylist, just like Backpack. This lets us add as many items as we want to any given square in the dungeon (provided it’s not a forbidden type like rock, wall or closed door). The most recently added item is the one we actually display on the map, since it’s “on top” of the pile. We could easily add code to limit the number of items added to a tile, causing the overflow to randomly spill over to another adjacent tile.

The code:

 

    Public Structure BodyLocations
        Dim Helmet As Object
        Dim Neck As Object
        Dim Cloak As Object
        Dim Girdle As Object
        Dim Armor As Object
        Dim LeftHand As Object
        Dim RightHand As Object
        Dim LeftRing As Object
        Dim RightRing As Object
        Dim Gloves As Object
        Dim Bracers As Object
        Dim Boots As Object
        Dim MissleWeapon As Object
        Dim Missles As Object
        Dim Tool As Object

        Dim BackPack As ArrayList
    End Structure


    ' This gets called when creating our Hero
    Public Equipment As BodyLocations
    Equipment.BackPack = New ArrayList

So then, to add an item to inventory… (.walkover is a string containing a description of what the Hero sees, items(0) assumes only 1 item exists in the square, there is other code for handling a pile of items, lastly m_arrLevel is the array containing the map info)

 

    Dim item As Object, AlreadyInBackpack As Boolean = False
    For Each item In m_Hero.Equipment.BackPack
       ' a match here means at least one of the item is already in our pack
       If item.walkover = m_arrLevel(intX, intY, intZ).items(0).walkover Then
          item.quantity += 1
          AlreadyInBackpack = True
       End If
    Next

    ' if the item we're picking up is NOT already in our pack, then add it
    If Not AlreadyInBackpack Then
       m_Hero.Equipment.BackPack.Add(m_arrLevel(intX, intY, intZ).items(0))
    End If

    m_arrLevel(intX, intY, intZ).items.RemoveAt(0)
    m_arrLevel(intX, intY, intZ).itemcount -= 1
    If m_arrLevel(intX, intY, intZ).itemcount = 0 Then m_arrLevel(intX, intY, intZ).itemcount = Nothing

In HA!, the equipped itms screen has a letter attached to each slot (A is for Head, B is for Neck, down through your cloak, armor, left and right hand, boots, etc…) If we want to move an item from inventory to the equippable neck slot, the code would look like this:

 

    ' show us ONLY the items in our backpack that can be equipped to this slot
    m_Hero.Equipment.Neck = ShowBackpack("", ItemType.Neck)

    
    ' inside the ShowBackpack function...
            Case ItemType.Neck
                Dim thing As Object
                WriteAt(0, yPos, "Amulets & Talismans:", ConsoleColor.DarkYellow)
                yPos += 1
                WriteAt(0, yPos, "--------------------", ConsoleColor.DarkYellow)
                yPos += 1

                WriteAt(1, yPos, "No items of this type.")
                For Each thing In m_Hero.Equipment.BackPack
                    If thing.type = ItemType.Neck Then
                        intQty = thing.quantity
                        Dim strItem As New StringBuilder

                        strItem.Append(startLetter & "] " & thing.Name)
                        If intQty > 1 Then strItem.Append(" (Qty: " & thing.quantity & ")")
                        strItem.Append("               ")
                        WriteAt(1, yPos, strItem.ToString)

                        yPos += 1
                        startLetter = Chr(Asc(startLetter) + 1)
                        itemArray.Add(thing)
                    End If
                Next
                yPos += 2

The above code will display all matches for the neck slot, with a different letter next to each item so you can press ‘a’ for the first one, ‘b’ for the second one, etc… then we pass the selected item (object) back to the proper slot in the code below:

 

     ShowBackpack = itemArray(intItemIndex)

So in the example above, m_Hero.Equipment.Neck = ShowBackpack(“”, ItemType.Neck), ShowBackpack returns the object of the item we selected, thereby assigning it to the equippable slot. All that is left is to destroy the item in inventory (or decrement the quantity if there’s more than one)

 

    If itemArray(intItemIndex).quantity = 1 Then
         m_Hero.Equipment.BackPack.Remove(itemArray(intItemIndex))
         itemArray.RemoveAt(intItemIndex)

    ElseIf itemArray(intItemIndex).quantity > 1 Then
         m_Hero.Equipment.BackPack.Remove(itemArray(intItemIndex))
         itemArray(intItemIndex).quantity -= 1
         m_Hero.Equipment.BackPack.Add(itemArray(intItemIndex))
    End If

So that’s pretty much it for inventory management. Certain cases require special coding, such as picking up items from piles and that sort of thing. Feel free to ask any questions.

Tinggalkan komentar