Game Dev Diary: Building an inventory

Do repost and rate:

A lot of my talk about Witch's Brew so far has been fairly high level stuff, the "why" more than the "how", with a few little references to code stuff.

This time I want to take a slightly deeper look at how I am coding something (without posting walls of code) and I think the best place to start is a feature which I am working on right now - player inventory!

Don't worry if you are not so interested in the coding side of things. I will warn you when you should skip to the end to avoid the technical stuff. But for now, a small introduction to what inventory means to this game and how it affects gameplay....

 

The basis of player inventory for Witch's Brew is that the player will have a limited number of ingredients they can carry at any time. You must return to near the sister witch who is stirring the cauldron in the bottom corner to drop off what you've collected before you can pick up more. For now there is a barrel next to her as a drop-off point, but I would like to find something better.

Your carrying limit is 4 ingredients, but it may change depending on eventual gameplay balance. Also when I get around to adding a full story mode I've considered increasing the limit past 4, either incrementally and permanently at specific points of the story, or through a rare power-up like a strength potion. That decision hasn't been fully thought out yet.

Also, instead of scoring each ingredient as you pick it up now you will only score when you deliver what you are carrying.

 

Ok, I'm about to get into the heavier stuff so if you aren't interested in coding talk go ahead and skip to the last few paragraphs.

 

/* Begin code talk */

 

In coding terms this is not really a huge technical challenge (using JavaScript terms here since that is what I am coding in):

  • Create an array for the inventory
  • Set a number of items equal to the inventory limit to a default value to indicate the slot is empty
  • Whenever the player touches a collectable object check to see if it is something that can go to inventory - if so, iterate through the inventory and find the first slot with the default value
    •  If there is no slot with the default value return something so the calling code knows the ingredient can't be picked up
    • Otherwise set the value of the first "empty" slot to the ingredient and return something so the calling code knows the ingredient was able to be picked up
  • When clearing the inventory just set every slot back to the default value and do any other logic needed

 

That is the bare basics of the idea but of course it all depends on code, and it doesn't take into account anything to do with actually showing the inventory on screen.

A quick overview of my code layout for the pertinent bits:

  • I am using classes for everything to separate concerns
  • I have a Player class to encapsulate my player logic
  • I have a Collectable class for all types of collectable items, which is then extended by an Ingredient or PowerUp class
  • I have a UI class that manages the screen overlay, but each component (score, health, inventory, and pause button) are their own separate class - so we only care about the Inventory class here
  • Technically I could put all the inventory logic into the Player class and just use a normal array of objects to track it, but I have chosen to make an InventorySlot class as well to separate out that logic

 

The InventorySlot class has 4 class methods: isEmpty, getIngredient, setIngredient, and empty which are used by logic in the Player class.

Digging a little deeper into each of these:

  • isEmpty() - Simply enough, this just returns if the slot has the default value set
  • getIngredient() - Not used quite yet because I don't have any recipes to interact with, but this just returns the Collectable object currently set in the slot
  • setIngredient(collectable) - This sets the slot to the passed in Collectable object and emits an event for the UI to update this slot's graphic
  • empty() - Set the slot's value to null and emit an event for the UI to update this slot

 

Then in the constructor for the Player class I loop through the required number of inventory slots and create an InventorySlot for each.

 

Also in the Player class I have class methods hasEmptySlot, canPickUp, pickUp, getFirstEmptySlot, addToInventory, and deliverIngredients which do the following:

  • hasEmptySlot - Returns true if at least one slot is empty
  • canPickUp(collectable) - If the passed Collectable is an ingredient and there is an empty slot, or if it is a power-up, return true
  • pickUp(collectable) - If the passed Collectable is an ingredient call addToInventory, or if it is a power-up call a method on the Collectable class to impart its effect(s) on the player (not yet finished)
  • getFirstEmptySlot - Iterate through the slots and return the first one that is empty
  • addToInventory(collectable) - Call setIngredient on the slot returned by getFirstEmptySlot, passing in the ingredient
  • deliverIngredients - Calculate score for the items being delivered and emit an event to update the score, and empty every slot

Then putting it all together, in my collision handler for the player and collectables I simply check if the player can pick up the collectable using canPickUp. If that is true I call pickUp. Everything else is handled by the class methods on the player and the inventory slot, plus a few related bits of code on the collectable!

 

Then on to the surprisingly easy bit - displaying the inventory state in the UI!

 

My Inventory class is very simple. A bit of logic in the constructor to create 4 Phaser.GameObject.Images at the correct positions and hide them, a class method to draw the outer box (this could honestly be moved into the constructor since this is such a simple shape and doesn't need redrawing during gameplay), then class methods for addItem and removeItem which are linked to events by the UI class.

addItem receives the slot number and collectable object through the event, so it just sets the new texture & frame it needs from the collectable, and sets the image in the slot to visible.

removeItem receives the slot number through the event, and simply sets the image in that slot to be not visible.

 

/* End code talk */

 

So there we go, now you know the basics of why and maybe of how I added inventory to the game. It is not very pretty (yet), but it works.

 

The only thing really left to do is add in the obligatory link to the updated game. But before I do, you might notice if you've played previous versions that this one has only pumpkin ingredients while the other ingredients like candles and eyeballs are missing.

That happened when I moved the ingredients to their own Collectable class, and I haven't figured out yet how I want ingredient types to become available within the game, so I haven't bothered adding more types back in yet. They will come back soon enough.

 

 

And finally the link to Witch's Brew v0.3.0!

Regulation and Society adoption

Ждем новостей

Нет новых страниц

Следующая новость