I am trying to code the inventory system in my first real game so I have very little experience in both c# and game engine development. Basically, I need some general guidance and tips with how to structure and organize these sorts of systems. Please tell me if I am on the right track or not before I get too deep into making some badly structured system. It's fine if you don't feel like looking through my code, suggestions about general structure would also be appreciated.
What I am aiming to end up with is some sort of system like Minecraft or Terraria. It must include:
main inventory GUI (items can be dragged and placed in whatever slot desired
Itembar outside of the main inventory which can be assigned to certain items
the ability to use items from either location
So far, I have 4 main classes: Inventory holds the general info and methods, inventoryslot holds info for individual slots, Itembar holds all info and methods for itself, and finally, ItemManager to manage interactions between the two and hold a master list of items.
So far, my itembar works perfectly and interacts well with mousedragging items into and out of it as well as activating the item effect.
Here is the code I have so far:
(there is a lot but I will try to keep it relevant)
This is the code for the itembar on the main screen:
class Itembar
{
public Texture2D itembarfull, iSelected;
public static Rectangle itembar = new Rectangle(5, 218, 40, 391);
public Rectangle box1 = new Rectangle(itembar.X, 218, 40, 40);
//up to 10 Rectangles for each slot
public int Selected = 0;
private ItemManager manager;
public Itembar(Texture2D texture, Texture2D texture3, ItemManager mann)
{
itembarfull = texture;
iSelected = texture3;
manager = mann;
}
public void Update(GameTime gametime)
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(
itembarfull,
new Vector2 (itembar.X, itembar.Y),
null,
Color.White,
0.0f,
Vector2.Zero,
1.0f,
SpriteEffects.None,
1.0f);
if (Selected == 1)
spriteBatch.Draw(iSelected, new Rectangle(box1.X-3, box1.Y-3, box1.Width+6, box1.Height+6), Color.White);
//goes up to 10 slots
}
public int Box1Query()
{
foreach (Item item in manager.items)
{
if(box1.Contains(item.BoundingBox))
return manager.items.IndexOf(item);
}
return 999;
}
//10 different box queries
It is working fine right now. I just put an Item in there and the box will query things like the item's effects, stack number, consumable or not etc...This one is basically almost complete.
Here is the main inventory class:
class Inventory
{
public bool isActive;
public List<Rectangle> mainSlots = new List<Rectangle>(24);
public List<InventorySlot> mainSlotscheck = new List<InventorySlot>(24);
public static Rectangle inv = new Rectangle(841, 469, 156, 231);
public Rectangle invfull = new Rectangle(inv.X, inv.Y, inv.Width, inv.Height);
public Rectangle inv1 = new Rectangle(inv.X + 4, inv.Y +3, 32, 32);
//goes up to inv24 resulting in a 6x4 grid of Rectangles
public Inventory()
{
mainSlots.Add(inv1); mainSlots.Add(inv2); mainSlots.Add(inv3); mainSlots.Add(inv4);
//goes up to 24
foreach (Rectangle slot in mainSlots)
mainSlotscheck.Add(new InventorySlot(slot));
}
//update and draw methods are empty because im not too sure what to put there
public int LookforfreeSlot()
{
int slotnumber = 999;
for (int x = 0; x < mainSlots.Count; x++)
{
if (mainSlotscheck[x].isFree)
{
slotnumber = x;
break;
}
}
return slotnumber;
}
}
}
LookforFreeSlot() method is meant to be called when I do AddtoInventory(). I'm kinda stumped about what other things I need to put in this class.
Here is the inventorySlot class:
(its main purpose is to check the bool "isFree" to see whether or not something already occupies the slot. But i guess it can also do other stuff like get item info.)
class InventorySlot
{
public int X, Y;
public int Width = 32, Height = 32;
public Vector2 Position;
public int slotnumber;
public bool free = true;
public int? content = null;
public bool isFree
{
get { return free; }
set { free = value; }
}
public InventorySlot(Rectangle slot)
{
slot = new Rectangle(X, Y, Width, Height);
}
}
}
Finally, here is the ItemManager (I am omitting the master list because it is too long)
class ItemManager
{
public List<Item> items = new List<Item>(20);
public List<Item> inventory1 = new List<Item>(24);
public List<Item> inventory2 = new List<Item>(24);
public List<Item> inventory3 = new List<Item>(24);
public List<Item> inventory4 = new List<Item>(24);
public Texture2D icon, filta;
private Rectangle msRect;
MouseState mouseState;
public int ISelectedIndex;
Inventory inventory;
SpriteFont font;
public void GenerateItems()
{
items.Add(new Item(new Rectangle(0, 0, 32, 32), icon, font));
items[0].name = "Grass Chip";
items[0].itemID = 0;
items[0].consumable = true;
items[0].stackable = true;
items[0].maxStack = 99;
items.Add(new Item(new Rectangle(32, 0, 32, 32), icon, font));
//master list continues. it will generate all items in the game;
}
public ItemManager(Inventory inv, Texture2D itemsheet, Rectangle mouseRectt, MouseState ms, Texture2D fil,
SpriteFont f)
{
icon = itemsheet;
msRect = mouseRectt;
filta = fil;
mouseState = ms;
inventory = inv;
font = f;
}
//once again, no update or draw
public void mousedrag()
{
items[0].DestinationRect = new Rectangle (msRect.X, msRect.Y, 32, 32);
items[0].dragging = true;
}
public void AddtoInventory(Item item)
{
int index = inventory.LookforfreeSlot();
if (index == 999)
return;
item.DestinationRect = inventory.mainSlots[index];
inventory.mainSlotscheck[index].content = item.itemID;
inventory.mainSlotscheck[index].isFree = false;
item.IsActive = true;
}
}
}
The mousedrag works pretty well. AddtoInventory doesn't work because LookforfreeSlot doesn't work.
Relevant code from the main program:
When I want to add something to the main inventory, I do something like this:
foreach (Particle ether in ether1.ethers)
{
if (ether.isCollected)
itemmanager.AddtoInventory(itemmanager.items[14]);
}
This turned out to be much longer than I had expected :(
But I hope someone is interested enough to comment.