Inventory System and Equipment System for RPG Game
-
martes, 14 de agosto de 2012 19:35
Hey guys, I've been working on a RPG game in VB 2010 and I've gotten to the point where I am adding items and giving them properties but I'm a bit confused and stuck. I currently have a form with 28 picture boxes and 28 'inventory settings & amounts' (inv1, inv2, etc) and on loading the inventory form the pictures are updated accordingly to the setting and a number below it to show the amount you currently have of the item. Then I want to be able to click the items and it "equips" it which will then show up on a different form called the 'Character Screen'.
Here is some of my current coding for it:
Inventory updating on load
If My.Settings.inv4 = "fvisage" Then inv4.Image = My.Resources.fVisage inve4.Text = My.Settings.fvisage ElseIf My.Settings.inv4 = "draBody" Then inv4.Image = My.Resources.draBody inve4.Text = My.Settings.drabody ElseIf My.Settings.inv4 = "dralegs" Then inv4.Image = My.Resources.draLegs inve4.Text = My.Settings.dralegs ElseIf My.Settings.inv4 = "draboots" Then inv4.Image = My.Resources.draBoots inve4.Text = My.Settings.draboots ElseIf My.Settings.inv4 = "drahelm" Then inv4.Image = My.Resources.draHelm inve4.Text = My.Settings.drahelm ElseIf My.Settings.inv4 = "clothbody" Then inv4.Image = My.Resources.clothBody inve4.Text = My.Settings.clothbody ElseIf My.Settings.inv4 = "clothlegs" Then inv4.Image = My.Resources.clothLegs inve4.Text = My.Settings.clothlegs ElseIf My.Settings.inv4 = "clothboots" Then inv4.Image = My.Resources.clothBoots inve4.Text = My.Settings.clothboots ElseIf My.Settings.inv4 = "clothhat" Then inv4.Image = My.Resources.clothHelm inve4.Text = My.Settings.clothhat ElseIf My.Settings.inv4 = "plaBody" Then inv4.Image = My.Resources.plaBody inve4.Text = My.Settings.plabody ElseIf My.Settings.inv4 = "plalegs" Then inv4.Image = My.Resources.plaLegs inve4.Text = My.Settings.plalegs ElseIf My.Settings.inv4 = "plaboots" Then inv4.Image = My.Resources.plaBoots inve4.Text = My.Settings.plaboots ElseIf My.Settings.inv4 = "plahelm" Then inv4.Image = My.Resources.plaHelm inve4.Text = My.Settings.plahelm ElseIf My.Settings.inv4 = "maiBody" Then inv4.Image = My.Resources.maiBody inve4.Text = My.Settings.maibody ElseIf My.Settings.inv4 = "mailegs" Then inv4.Image = My.Resources.maiLegs inve4.Text = My.Settings.mailegs ElseIf My.Settings.inv4 = "maiboots" Then inv4.Image = My.Resources.maiBoots inve4.Text = My.Settings.maiboots ElseIf My.Settings.inv4 = "maihelm" Then inv4.Image = My.Resources.maiHelm inve4.Text = My.Settings.maihelm ElseIf My.Settings.inv4 = "leaBody" Then inv4.Image = My.Resources.leaBody inve4.Text = My.Settings.leabody ElseIf My.Settings.inv4 = "lealegs" Then inv4.Image = My.Resources.leaLegs inve4.Text = My.Settings.lealegs ElseIf My.Settings.inv4 = "leaboots" Then inv4.Image = My.Resources.leaBoots inve4.Text = My.Settings.leaboots ElseIf My.Settings.inv4 = "leahelm" Then inv4.Image = My.Resources.leaHelm inve4.Text = My.Settings.leahelm ElseIf My.Settings.inv4 = "fdraBody" Then inv4.Image = My.Resources.fdraBody inve4.Text = My.Settings.fdraBody ElseIf My.Settings.inv4 = "fdralegs" Then inv4.Image = My.Resources.fdraLegs inve4.Text = My.Settings.fdraLegs ElseIf My.Settings.inv4 = "fdraboots" Then inv4.Image = My.Resources.fdraBoots inve4.Text = My.Settings.fdraBoots ElseIf My.Settings.inv4 = "fdrahelm" Then inv4.Image = My.Resources.fdraHelm inve4.Text = My.Settings.fdraHelm ElseIf My.Settings.inv4 = "bAm" Then inv4.Image = My.Resources.bAm inve4.Text = My.Settings.bAm ElseIf My.Settings.inv4 = "fstaff" Then inv4.Image = My.Resources.fStaff inve4.Text = My.Settings.fStaff ElseIf My.Settings.inv4 = "gAm" Then inv4.Image = My.Resources.gAm inve4.Text = My.Settings.gAm ElseIf My.Settings.inv4 = "glbCape" Then inv4.Image = My.Resources.GlbCape inve4.Text = My.Settings.glbCape ElseIf My.Settings.inv4 = "legCape" Then inv4.Image = My.Resources.legCape inve4.Text = My.Settings.legCape ElseIf My.Settings.inv4 = "legAm" Then inv4.Image = My.Resources.legAm inve4.Text = My.Settings.legAm ElseIf My.Settings.inv4 = "gring" Then inv4.Image = My.Resources.gRing inve4.Text = My.Settings.gRing ElseIf My.Settings.inv4 = "legring" Then inv4.Image = My.Resources.legRing inve4.Text = My.Settings.legRing ElseIf My.Settings.inv4 = "legstaff" Then inv4.Image = My.Resources.legStaff inve4.Text = My.Settings.legStaff ElseIf My.Settings.inv4 = "oring" Then inv4.Image = My.Resources.oRing inve4.Text = My.Settings.oRing ElseIf My.Settings.inv4 = "pring" Then inv4.Image = My.Resources.pRing inve4.Text = My.Settings.pRing ElseIf My.Settings.inv4 = "yam" Then inv4.Image = My.Resources.yAm inve4.Text = My.Settings.yAm ElseIf My.Settings.inv4 = "pam" Then inv4.Image = My.Resources.pAm inve4.Text = My.Settings.pAm ElseIf My.Settings.inv4 = "lstaff" Then inv4.Image = My.Resources.lStaff inve4.Text = My.Settings.lStaff ElseIf My.Settings.inv4 = "pstaff" Then inv4.Image = My.Resources.pStaff inve4.Text = My.Settings.pStaff ElseIf My.Settings.inv4 = "wstaff" Then inv4.Image = My.Resources.wStaff inve4.Text = My.Settings.wStaff ElseIf My.Settings.inv4 = "rpcape" Then inv4.Image = My.Resources.rpCape inve4.Text = My.Settings.rpCape ElseIf My.Settings.inv4 = "tbcape" Then inv4.Image = My.Resources.tBCape inve4.Text = My.Settings.tbCape ElseIf My.Settings.inv4 = "legdagger" Then inv4.Image = My.Resources.legDagger inve4.Text = My.Settings.legDagger ElseIf My.Settings.inv4 = "legsword" Then inv4.Image = My.Resources.legSword inve4.Text = My.Settings.legSword ElseIf My.Settings.inv4 = "gdagger" Then inv4.Image = My.Resources.gDagger inve4.Text = My.Settings.gdagger ElseIf My.Settings.inv4 = "odagger" Then inv4.Image = My.Resources.oDagger inve4.Text = My.Settings.odagger ElseIf My.Settings.inv4 = "rdagger" Then inv4.Image = My.Resources.rDagger inve4.Text = My.Settings.rdagger ElseIf My.Settings.inv4 = "gsword" Then inv4.Image = My.Resources.gSword inve4.Text = My.Settings.gsword ElseIf My.Settings.inv4 = "psword" Then inv4.Image = My.Resources.pSword inve4.Text = My.Settings.psword ElseIf My.Settings.inv4 = "rsword" Then inv4.Image = My.Resources.rSword inve4.Text = My.Settings.rsword ElseIf My.Settings.inv4 = "cpbadge" Then inv4.Image = My.Resources.cpPoint inve4.Text = My.Settings.cpPoints ElseIf My.Settings.inv4 = "hp25" Then inv4.Image = My.Resources.hp25 inve4.Text = My.Settings.hp25 ElseIf My.Settings.inv4 = "hp50" Then inv4.Image = My.Resources.hp50 inve4.Text = My.Settings.hp50 ElseIf My.Settings.inv4 = "hp100" Then inv4.Image = My.Resources.hp100 inve4.Text = My.Settings.hp100 ElseIf My.Settings.inv4 = "en25" Then inv4.Image = My.Resources.pow25 inve4.Text = My.Settings.en25 ElseIf My.Settings.inv4 = "en50" Then inv4.Image = My.Resources.pow50 inve4.Text = My.Settings.en50 ElseIf My.Settings.inv4 = "en100" Then inv4.Image = My.Resources.pow100 inve4.Text = My.Settings.en100 ElseIf My.Settings.inv4 = "poke" Then inv4.Image = My.Resources.poke inve4.Text = My.Settings.Poke End If
Gaining item loot from a fight and it being stored in the first open inventory slot
If My.Settings.inv2 = "" Or My.Settings.inv2 = "fvisage" Then My.Settings.inv2 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv3 = "" Or My.Settings.inv3 = "fvisage" Then My.Settings.inv3 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv4 = "" Or My.Settings.inv4 = "fvisage" Then My.Settings.inv4 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv5 = "" Or My.Settings.inv5 = "fvisage" Then My.Settings.inv5 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv6 = "" Or My.Settings.inv6 = "fvisage" Then My.Settings.inv6 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv7 = "" Or My.Settings.inv7 = "fvisage" Then My.Settings.inv7 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv8 = "" Or My.Settings.inv8 = "fvisage" Then My.Settings.inv8 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv9 = "" Or My.Settings.inv9 = "fvisage" Then My.Settings.inv9 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv10 = "" Or My.Settings.inv10 = "fvisage" Then My.Settings.inv10 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv11 = "" Or My.Settings.inv11 = "fvisage" Then My.Settings.inv11 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv12 = "" Or My.Settings.inv12 = "fvisage" Then My.Settings.inv12 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv13 = "" Or My.Settings.inv13 = "fvisage" Then My.Settings.inv13 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv14 = "" Or My.Settings.inv14 = "fvisage" Then My.Settings.inv14 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv15 = "" Or My.Settings.inv15 = "fvisage" Then My.Settings.inv15 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv16 = "" Or My.Settings.inv16 = "fvisage" Then My.Settings.inv16 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv17 = "" Or My.Settings.inv17 = "fvisage" Then My.Settings.inv17 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv18 = "" Or My.Settings.inv18 = "fvisage" Then My.Settings.inv18 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv19 = "" Or My.Settings.inv19 = "fvisage" Then My.Settings.inv19 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") ElseIf My.Settings.inv20 = "" Or My.Settings.inv2 = "fvisage" Then My.Settings.inv20 = "fvisage" My.Settings.fvisage = My.Settings.fvisage + 1 MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "You've also found a Flaming Visage!", vbOKOnly, "Loot") Else MsgBox("You gained: " + fgold.ToString + " gold" & vbNewLine & "You gained: " + fExp.ToString + " experience." & vbNewLine & "Due to lack of inventory space, you had to leave the Flaming visage behind.", vbOKOnly, "Better than nothing!") End If
This is my "equip" method that occurs when clicking one of the picture boxes
it is in a switch case that switches to, in this perticular case, what is stored in my.settings.inv2
Case clothbody If My.Settings.clothbody - 1 = 0 Then If My.Settings.body = "" Then inv2.Image = My.Resources.nothng My.Settings.inv2 = "" inve2.Text = "-" chrScreen.body.Image = My.Resources.clothBody My.Settings.armor = My.Settings.armor + 30 My.Settings.body = "clothbody" My.Settings.clothbody = My.Settings.clothbody - 1 ElseIf My.Settings.body = "clothbody" Then Else Dim x As String Dim mre As String x = My.Settings.body mre = "my.resources." & x My.Settings.body = "clothbody" If My.Settings.inv2 = x Then inv2.Image = My.Resources.nothng inve2.Text = "-" ElseIf My.Settings.inv3 = x Then inv3.Image.Tag = mre inv3.Image = inv3.Image.Tag inve3.Text = "-" ElseIf My.Settings.inv4 = x Then inv4.Image = My.Resources.nothng inve4.Text = "-" ElseIf My.Settings.inv5 = x Then inv5.Image = My.Resources.nothng inve5.Text = "-" ElseIf My.Settings.inv6 = x Then inv6.Image = My.Resources.nothng inve6.Text = "-" ElseIf My.Settings.inv7 = x Then inv7.Image = My.Resources.nothng inve7.Text = "-" ElseIf My.Settings.inv8 = x Then inv8.Image = My.Resources.nothng inve8.Text = "-" ElseIf My.Settings.inv9 = x Then inv9.Image = My.Resources.nothng inve9.Text = "-" ElseIf My.Settings.inv10 = x Then inv10.Image = My.Resources.nothng inve10.Text = "-" ElseIf My.Settings.inv11 = x Then inv11.Image = My.Resources.nothng inve11.Text = "-" ElseIf My.Settings.inv12 = "" Then inv12.Image = My.Resources.nothng inve12.Text = "-" ElseIf My.Settings.inv13 = x Then inv13.Image = My.Resources.nothng inve13.Text = "-" ElseIf My.Settings.inv14 = x Then inv14.Image = My.Resources.nothng inve14.Text = "-" ElseIf My.Settings.inv15 = x Then inv15.Image = My.Resources.nothng inve15.Text = "-" ElseIf My.Settings.inv16 = x Then inv16.Image = My.Resources.nothng inve16.Text = "-" ElseIf My.Settings.inv17 = x Then inv17.Image = My.Resources.nothng inve17.Text = "-" ElseIf My.Settings.inv18 = x Then inv18.Image = My.Resources.nothng inve18.Text = "-" ElseIf My.Settings.inv19 = x Then inv19.Image = My.Resources.nothng inve19.Text = "-" ElseIf My.Settings.inv20 = x Then inv20.Image = My.Resources.nothng inve20.Text = "-" End If End If ElseIf My.Settings.clothbody = 0 Then inv2.Image = My.Resources.nothng My.Settings.inv2 = "" inve2.Text = "-" Else chrScreen.body.Image = My.Resources.clothBody My.Settings.armor = My.Settings.armor + 30 My.Settings.clothbody = My.Settings.clothbody - 1 inve2.Text = My.Settings.clothbody My.Settings.body = "clothbody" End If Case clothlegs If My.Settings.clothlegs - 1 = 0 Then inv2.Image = My.Resources.nothng My.Settings.inv2 = "" inve2.Text = "-" chrScreen.legs.Image = My.Resources.clothLegs My.Settings.armor = My.Settings.armor + 25 My.Settings.legs = "clothlegs" My.Settings.clothlegs = My.Settings.clothlegs - 1 ElseIf My.Settings.clothlegs = 0 Then inv2.Image = My.Resources.nothng My.Settings.inv2 = "" inve2.Text = "-" Else chrScreen.legs.Image = My.Resources.clothLegs My.Settings.armor = My.Settings.armor + 25 My.Settings.clothlegs = My.Settings.clothlegs - 1 inve2.Text = My.Settings.clothlegs My.Settings.legs = "clothlegs" End If
The whole 'Elseif my.settings.inv2 = x then' thing was suppossed to be for in cases where you already have a item equipped in that slot but that seems to not work and I can't seem to grab the 'item' from the character screen and bring it back to the inventory screen without causing a problem.
Now, I know my code is very inefficient and long and probably overall unnecessary but I'm stuck and confused and have no idea what I should be doing. By looking at this could anyone please be able to teach me a more efficient and easier method of doing this? I tried creating a new class and making a function, that I'd be able to call on in a different, to find the next available slot starting with inv2 (inv1 always has gold in it no matter what, even if you have 0 gold) but that didn't work cause I again didn't even know where to start.
I need to know how to do this the right and most efficient way possible. I read other threads where people said to make a new class define the item and blah blah blah like this:
Public Class Item Private itemName As String Private Const itemStrength as int = 100 Property Line() As String Get Return itemName End Get Set(ByVal Value As String) mstrLine = Value End Set End Property ReadOnly Property strength() As Integer Get Return itemStrength End Get End Property End Classthen using this to populate the array list:
inherits System.Collections; ... dim ar as new Arraylist() dim Itm as new Item() itm.Type = "Armor" itm.Damage = itm.itemStrength ar.Add(itm);
Can someone show me how to do this because I am lost.
Thank you in advance and I hope you all have a great day. :)
Todas las respuestas
-
martes, 14 de agosto de 2012 20:56Moderador
The good news: You worked hard to figure out that what you have won't work, but you are willing to change it if necessary.
The bad new: You will probably need to change everything you've done so far. =P
Let me begin by saying that there is no single best way to do this. There are a number of approaches which could all be valid. Much depends on the overall design of the game engine.
The best way to explain this is probably with a small exmaple. However, "small" is still going to be several classes and code to make them work together. You could probably find existing examples in the XNA examples on AppHub, but many of them are in C# (I'm not sure if the example RPG was translated to VB or not - you should check though). Even if you aren't going to use XNA, you may still learn a lot by looking at how they structure their classes.
I'll see if I can whip you up a small example without getting too complicated. It may take some thought though, so please be patient.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
-
martes, 14 de agosto de 2012 21:16Haha That's alright if I have to change everything. I head on over to XNA and check out what they have, and an example would be nice. Thank you, I'll be patient as ever. :)
-
martes, 14 de agosto de 2012 21:55Moderador
Ok, here's a really short and simple example - to simple really as I'm sure you'll want more in your game, but lets take a look at it first:
Public Class Form1 Private Hero As New RpgCharacter Private SwordPlus1 As New RpgEquipment With {.Name = "+1 Sword", .Slot = RpgEquipmentSlot.Hand} Private SwordPlus2 As New RpgEquipment With {.Name = "+2 Sword", .Slot = RpgEquipmentSlot.Hand} Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Hero.Inventory.AddItem(SwordPlus1) Hero.Inventory.AddItem(SwordPlus2) Debug.Print("Inv Count = " & Hero.Inventory.InventoryCount) Hero.Equip(SwordPlus1) Debug.Print("Inv Count = " & Hero.Inventory.InventoryCount) Debug.Print(Hero.Equipment(RpgEquipmentSlot.Hand).Name) Hero.Equip(SwordPlus2) Debug.Print("Inv Count = " & Hero.Inventory.InventoryCount) Debug.Print(Hero.Equipment(RpgEquipmentSlot.Hand).Name) End Sub End Class Public Class RpgCharacter Public Property Equipment As New Dictionary(Of RpgEquipmentSlot, RpgEquipment) Public Property Inventory As New RpgInventory Public Function Equip(item As RpgEquipment) As Boolean If Inventory.ItemCount(item) = 0 Then Return False Inventory.RemoveItem(item) If Equipment.ContainsKey(item.Slot) Then Dim currentEquipment As RpgEquipment = Equipment(item.Slot) If Not Inventory.AddItem(currentEquipment) Then 'Inventory is full and previous equipment could not be added to inventory... 'drop or discard or overflow as required End If End If Equipment(item.Slot) = item Return True End Function End Class Public Class RpgItem Public Property Name As String Public Property Usable As Boolean Public Property Charges As Integer Public Property Stackable As Boolean End Class Public Class RpgEquipment Inherits RpgItem Public Property Slot As RpgEquipmentSlot End Class Public Class RpgInventory Public Property InventorySlots As Integer = 40 Private _ItemList As New Dictionary(Of RpgItem, Integer) Public Function AddItem(item As RpgItem) As Boolean If _ItemList.ContainsKey(item) AndAlso item.Stackable Then _ItemList(item) += 1 Return True End If If _ItemList.Count < InventorySlots Then _ItemList(item) = 1 Return True End If Return False End Function Public ReadOnly Property InventoryCount As Integer Get Return _ItemList.Count End Get End Property Public Function ItemCount(item As RpgItem) As Integer If _ItemList.ContainsKey(item) Then Return _ItemList(item) End If Return 0 End Function Public Function RemoveItem(item As RpgItem) As Boolean If _ItemList.ContainsKey(item) Then If _ItemList(item) > 1 Then _ItemList(item) -= 1 Return True Else _ItemList.Remove(item) Return True End If End If Return False End Function End Class Public Enum RpgEquipmentSlot Head Body Hand Feet End EnumSo starting at the bottom, we define the available equipment slots in an Enum. Note that this simple example assumes that a given piece of gear only goes into one slot. But your real game may want an "MainHand" and "OffHand" for instance, and some weapons may go in either while others only go in one or the other. That can certainly be done, and the enum would probably be changed to flags to support multiple possible slots per item, but the equipping code gets too complex so the example is using just one slot per item to keep things simple.
In the middle we define an RpgItem which is anything the player can pickup. The item has a few example properties to show that it may be consumable and may have multiple charges (uses) before it runs out. There is also an example property for saying whether or not we can stack multiple items of the same kind in a single inventory slot.
After the RpgItem, we define a RpgEquipment object. Equipment is really just a item that the user can wear. So it can have charges or be consumable, but it also designates the slot that it equips to.
Below the Equipment we create an RpgInventory to represent the user inventory. Note that this class may actually want to implement IList or a dictionary interface, but to keep the example small this was excluded. I just added a few minimum methods to manipulate the inventory. We can add an item to the inventory which will stack items if they are stackable or add them if there is still space left. The method returns true or false to indicate if the addition was successful or not. We can get a count of all items in the inventory (not counting stack size, just consumed inventory slots) and we can get a count for a particular item (1 for non stackable, and the stack count for stackable items). Finally we can remove an item from the inventory by either reducing the stack count or completely removing the item if it is the last in the stack or not stackable.
Finally back up toward the top we define the RpgCharacter. The character holds its Inventory and Equipment collections (again, Inventory is not a real collection at this point, but could and probably should be expanded into one). We provide a simple Equip method that takes an item from inventory and equips it on the appropriate slot while removing any existing equipment in that slot already and returning it to the inventory (if there is space - you would have to replace the comments with logic to do whatever you want should the inventory be full).
This is a VERY oversimplified example. But hopefully it gives you a rough idea and also makes apparent the places where your game design determine the code functionality. Everything ultimately depends on how the game works. Will you have items that fit more than one slot? If not this logic is a good start, if so, it needs considerable expansion. And thats just one example...
So it will be very important to determine all of the desired game functionality ahead of time. Once you get started on designing these supporting classes, you don't want to decide to do something different in the game-play... it could quickly turn into a major rewrite.
Hope that helps, but let me know if its all still very confusing!
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
-
martes, 14 de agosto de 2012 22:37
Thank you so very much this will help me a lot in the future and give me something to look off of and to learn from. :) Although it has come to my attention that I'm going to have to start from scratch just to implement something like this. Haha. There are a few things that are still confusing, mainly cause I have never used nor heard of them before:
I have never heard of Dictionarys before, mind explaing what those are used for? I get the general idea of the code you provided but better ask and know for sure now then have to come back. Along with your statements, "Note that this class may actually want to implement IList or a dictionary interface IList or a dictionary interface" && "collections (again, Inventory is not a real collection at this point, but could and probably should be expanded into one" mind elaborating, how to do so, what they are? :D
Private _ItemList As New Dictionary(Of RpgItem, Integer)
Also when you defined this dictionary you have integer, why ineteger?
You defined the +1 Sword and +2 Sword at the top, would it be possible to define ALL my items in a completely different class then import them into this one? Just so I'm not overcrowding this one.
You've been mroe help in this hour and half then I've gotten since 9 this morning trying to figure this out and for that I thank you so very much for taking your time to make me that example!
-
miércoles, 15 de agosto de 2012 15:59Moderador
Well, it looks like you are asking all the right questions and already getting the right ideas about moving forward. I think you're going to make an excellent programmer. :)
I'll try to give you some simple answers to your questions, but also keep in mind that the F1 key is your best friend! If you put your cursor on Dictionary in the code and press F1 it will take you to the online documentation for the class. There is a ton of information in the MSDN library and you'll be able to get in-depth information on many standard classes.
A Dictionary is a list of key-value pairs of information. The key is constrained to be unique within the dictionary and the value can be any other data (it does not have to be unique). So in the previous example, a Dictionary(Of RpgItem, Integer) gives us a list of unique RpgItem objects each associated with an Integer value. The reason for choosing integer is that we want to keep a count of how many of a particular item we have in the inventory. This is to support "stacking" items. So when we add a new RpgItem to the inventory, it is added with a quantity of 1 unless it is stackable and we already have some of the item - then we just increment the count.
Having just talked though this, I realize there is a weakness in the design in that you could not carry two of the same item if it is not stackable. This is probably not desired so we'd need a different design for the Inventory class. LOL Like I said, this is too simple of a solution for a real game. =P
Rather than use an existing collection object (such as the generic List(Of T) or Dictionary(Of TKey, TValue), you can create your own custom lists by implementing the ICollection, IList, IDictionary, etc. interfaces. This is getting into some general class design detail that would be better covered by reading up on custom collections in MSDN (it would be a lot to try and cover in a simple forum post). Here are a few links to get you started:
http://msdn.microsoft.com/en-us/library/7y3x785f
http://msdn.microsoft.com/en-us/library/ms172192
http://msdn.microsoft.com/en-us/library/bb762916.aspx
http://msdn.microsoft.com/en-us/library/bb762928.aspx
Now then, onto defining your items... you've got the right idea! You would likely create a class whose primary purpose is to generate a series of RpgItem instances based on some list of data that you provide with your game. A simple example would be a text file that provides all of the details for each item. The "RpgItem Factory" class would be able to read and parse this text file and then use the data to generate a series of RpgItems. From that point on the rest of the game code would just access instances of these RpgItem objects and use them as needed (or make copies of them if needed). This part is determined mostly by the resource managment scheme you choose for your game (again, no real single answer for this - there are a number of acceptable ways of storing and loading game data). And you wouldn't necessarily pre-load every possible item; you might have the item definitions in a database file of some sort and the factory class would just create a single new instance of an RpgItem as needed.
At this point I think your next step is to outline all of the intended functionality of the game. Decide what kinds of items you'll have and how the player will store them in their inventory, use them, or equip them. You probably don't need a strict definition of the entire game, but a rough idea of most of it would be good to have before you start to code.
Feel free to ask any other questions or seek advice!
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
-
miércoles, 15 de agosto de 2012 17:39Reed, while I was spluttering my two sentences, you came up with a complete solution and description. How good I didn't send mine. ;) Good job (again)!
Armin
-
miércoles, 15 de agosto de 2012 21:44Moderador
haha Armin, thanks, but don't let me discourage you! Multiple viewpoints can be helpful for open-ended situations like this one. :)
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
-
jueves, 16 de agosto de 2012 2:40
Haha thanks for the compliment! I'm actually going to be started college here on the 27th for Computer Science on the track of Game and Virtual World Development!
I never knew about the F1 function, but thanks for pointing that out! Gonna have to start using it a lot more often.
Also, thanks for the Dictionary explaination that makes it much clearer and puts it into perspective for me. But I'm guessing I can't do Dictionary(Of RpgItem, Integer, Integer) to sovle the stacking problem? ;P The first integer being qauntity stacked, and second being quantity total? Or is that where custom lists would come in?
And thanks for the links, I'll be sure to go through them thoroughly! I also started my outline like you suggested.
Four thanks in this post. Just to bad I can't vote as helpful four times! ;) -
jueves, 16 de agosto de 2012 19:40Moderador
Hi magnite7,
If you wanted the dictionary to be able to represent an item, a "max stack qty" and a "current stack qty" then you could do it using another custom class. Please consider the following:
Public Class RpgInventory Private _Items As New Dictionary(Of RpgItem, RpgStack) End Class Public Class RpgStack Public Property MaximumStackSize As Integer Public Property CurrentStackCount As Integer End ClassSo while we can't create a Dictionary(Of RpgItem, Integer, Integer), we can create a new type to encapsulate the two integer values and then use that type as the value for the dictionary.
=)
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
-
jueves, 16 de agosto de 2012 19:52
Well darn I liked my way. lol Thank you for giving that example, as of now I am out of questions but I will be back if any arise. Thank you for all the help that you have given me.
-
martes, 21 de agosto de 2012 20:18
Hey I've arrived at a brick wall and was hoping for some advice.
Firstly, I wanted to add a save/load game feature where there are three Load/Save slots (3 different save files basically.)
I am currently using StreamWriter to write the save files (No problem with this) but loading the save file is where I am having difficulty. I am using System.IO to read the fille and Split it by line into a String Array. The first save file (save001.msav) has no difficultys in being read and correctly splitting the right information but when I try to repeat that process it just duplicates the same variables from the first file and seems to completely ignore the second save file.
My current code for this is:
Dim sTemp As String Dim save1() As String Dim save2() As String Dim save3() As String Dim temp As New DirectoryInfo("C:\Users\Owner\Desktop\Arena Fighters 2 Dark Ages\") saveFilePath = SearchForFile(temp, "save001.msav") If IO.File.Exists(saveFilePath) Then save1 = IO.File.ReadAllLines(SearchForFiletemp, "save001.msav")) sTemp = save1(1).Substring(save1(1).IndexOf("=") + 1) _SETTINGS.hasSave = sTemp sTemp = save1(2).Substring(save1(2).IndexOf("=") + 1) _SETTINGS.s2Name = sTemp sTemp = save1(3).Substring(save1(3).IndexOf("=") + 1) _SETTINGS.s2Level = sTemp End If saveFilePath2 = SearchForFile(temp, "save002.msav") If IO.File.Exists(saveFilePath) Then save2 = IO.File.ReadAllLines(SearchForFiletemp, "save002.msav")) sTemp = save2(1).Substring(save2(1).IndexOf("=") + 1) _SETTINGS.hasSave = sTemp sTemp = save2(2).Substring(save2(2).IndexOf("=") + 1) _SETTINGS.s2Name = sTemp sTemp = save2(3).Substring(save2(3).IndexOf("=") + 1) _SETTINGS.s2Level = sTemp End If saveFilePath3 = SearchForFile(temp, "save003.msav") If IO.File.Exists(saveFilePath) Then save3 = IO.File.ReadAllLines(SearchForFiletemp, "save003.msav")) sTemp = save3(1).Substring(save3(1).IndexOf("=") + 1) _SETTINGS.hasSave = sTemp sTemp = save3(2).Substring(save3(2).IndexOf("=") + 1) _SETTINGS.s2Name = sTemp sTemp = save3(3).Substring(save3(3).IndexOf("=") + 1) _SETTINGS.s3Level = sTemp End IfI have each of the variables loaded into a seperate Label.Text for testing purposes but they all come back as the same variables as in Save001, I have even tried manually editing each save file to be 100% positive of this.
Second, Reed Kimble the class you posted above has come in a lot of use and has helped me a lot but I am stuck on loading the RpgInventory into a visual interface. Right now I have 8 picture boxes that are designated as "Equipped Item Slots" and 21 picture boxes that are designated as "Inventory Slots", 1 item per slot, no Diablo style inventory. I have also added onto the RpgItem to include a .Resource property which links that item with its respective item image. I haven't currently tried to load the dictionary into the inventory slots, but I am working on get the equipped items out of the currentEquipment and grabbing its .Resource and displaying it as the respective pictureboxes images.
The only thing I have for this so far, since I haven't even got on picturebox to work, is:
Head.Image.Tag = _HERO.RpgCharacter.Equipment(slot.Head).Resource.ToString
Any advice? Thanks in advance.- Editado magnite7 martes, 21 de agosto de 2012 21:47
-
martes, 21 de agosto de 2012 20:35Moderador
You would need to use a loop calling IndexOf on the string looking for the first index of "=", and then storing that index. On the next loop you would pass that index + 1 to IndexOf for the start position parameter.
However, working with a save game file may be much easier using Serialization. You could create a simple class with properties to hold the values that you need to save. Then you mark the class with the Serializable attribute and use a BinaryFormatter to serialze the entire class with all of its property values into a binary file (bytes written to disk). You can then later use another instance of BinaryFormatter to turn the byte file back into an instance of the save-game class, with all of the property values in-tact.
Here's a real short example:
Public Class Form1 Public Sub SaveGame(data As SaveGameData, path As String) Dim baseStream As System.IO.FileStream = System.IO.File.Create(path) Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter.Serialize(baseStream, data) baseStream.Close() baseStream.Dispose() 'not explicity required since Close() does this, but its good habit and won't hurt anything End Sub Public Function LoadGame(path As String) As SaveGameData Dim baseStream As System.IO.FileStream = System.IO.File.Open(path, IO.FileMode.Open) Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Dim result As SaveGameData = formatter.Deserialize(baseStream) baseStream.Close() baseStream.Dispose() Return result End Function End Class <Serializable()> Public Class SaveGameData Public Property PlayTime As TimeSpan Public Property SaveDate As Date Public Property PlayerData As RpgCharacter End Class <Serializable()> Public Class RpgCharacter 'the character class definition End ClassThere is also an XML serializer if you prefer, but for a saved game, you typically don't want the user mucking around changing values in clear text. =)
-EDIT-
Oh, I forgot to mention that the one limitation on simple serialization like that is that every Type serialized must have the Serializable attribute. Notice how I added that attribute to the RpgCharacter class since the SaveGameData includes an instance of RpgCharacter. This attribute must exist on every type in the chain of data that you are storing.
Note that intrinsic types such as Int, Double, String, Boolean, etc are all serializable by default.
You can also implement complex serialization in which you write the code process that serializes the object. Then your SaveGameData class could contain instances of other classes which do not have the serializable attribute and you could manually save enough information to manually recreate a new instance when loading.
For more information on simple serialization see:
http://msdn.microsoft.com/en-us/library/y50tb888(v=vs.100)
For more information on complex serialization see:
http://msdn.microsoft.com/en-us/library/wf4375ks(v=vs.100)
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
- Editado Reed KimbleMicrosoft Community Contributor, Moderator martes, 21 de agosto de 2012 20:40
-
martes, 21 de agosto de 2012 21:49
Thanks, that actually seems way simpler.
Any advice on the second part?
-
miércoles, 22 de agosto de 2012 2:53
I played around with the dictionarys and was finally able to retrieve the item from the dict.
Heres the code for anyone else who reads this thread:
Dim item as RpgEquipment = _ITEMS.dScaleHelm
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click _HERO.RpgInventory.AddItem(item) _HERO.RpgCharacter.Equip(item) Dim output As String output = _HERO.RpgCharacter.Equipment.Item(RpgEquipmentSlot.Head).Name MsgBox(output, vbOKOnly) End Sub
When the button is clicked the item is automatically added to the inventory then equiped at which point output is defined with the name of the item equiped in the Head slot.
When I did this though, I made a HERO class a lot like the example Reed gave me above. And in order to call the equip and additem outside of that class I had to add 'Shared' to almost every function inside my HERO class. Is that bad? Or will the Shared being there not really hurt anything?

