00:00
00:00
Newgrounds Background Image Theme

SourJovis just joined the crew!

We need you on the team, too.

Support Newgrounds and get tons of perks for just $2.99!

Create a Free Account and then..

Become a Supporter!

As: Oop Inventory System

7,433 Views | 25 Replies
New Topic Respond to this Topic

As: Oop Inventory System 2005-12-06 15:44:24


AS:Main

AS: OOP Inventory System

See it
Download source
Inventory Class
Item Class

*note: .as files must be placed in the same folder as the .fla file for everything to work properly

This tutorial covers an Object-Oriented approach to creating an inventory system for your games. If you are interested in making a basic inventory, check out AS: Inventory 1 by Inglor. Also, this tutorial will not teach you Object-Oriented Programming. This tutorial assumes you understand basic OOP concepts such as objects, classes, constructors, encapsulation, etc. If you need an OOP lesson try AS:Basic OOP by Inglor. I also suggest senocular’s tutorial on OOP for actionscript 2.0 if you really want to learn more. Now, let’s move on

Why OOP?
Look, I wont lie to you. There’s a lot of code here. In fact you’ll probably look at it and say ‘wow, I could code that in a quarter of the lines.’ And you would be right. But OOP isn’t about conserving code. Reasons I have chosen to do this in OOP:

-Portability- ideally you should be able to drop this code in place into any flash with a few minimal changes to the graphics. Also, it allows flexibility during the design process. If partway through your game you decide you want your inventory to have six slots in two rows instead of four slots in three rows, you can change it with no hassle.
-Dynamic behavior- this is not a static system. Items are added into the first available slots, not into predetermined places. This lets you fill your inventory in a more realistic manner
-Encapsulation- Most of the dirty work is done by the inventory class. You as the programmer have a set of methods at your disposal. Instead of rewriting lines and lines of code you can simple create an inventory object and call methods such as Inventory.Add(), Inventory.Remove, and Inventory.ToggleVisibility()

Please also note that I am in no way, shape, or form an OOP expert. I only know what I know. In fact I’m anxious to see other programmers’ take on my code

Starting The Inventory

First, we need a movie clip to act as a generic ‘slot.’ This is what each item in your inventory will be placed into. I just used a 75x75 black outline square. Make whatever you like, just make sure it is square. Convert it to a movieclip and set its linkage identifier to “Ibox.” Make sure its registration point is set to the top left. THIS IS IMPORTANT.

Next, you need to draw your inventory items. In my example I drew three simple objects. Whatever you draw make sure they fit within the size of your inventory slot. Convert them to movieclips and give each one a linkage name to remember them by. IE a hammer should be named “hammer,” a knife “knife,” etc. Make sure to set their registration points back to the center. ALSO IMPORTANT.

Now, we’ll jump into our first class, the Item class. Create a new .as file and paste the following code into it:

class Item {
var itemName:String = '';

function Item(inName:String)
{
itemName = inName;
}
}

Remember that .as files must be named the same as the class they represent. The above file MUST be named Item.as or it will simply not work. This is a very basic class and only serves to help us visually see our inventory as a collection of Item objects. This is a class that will be applied to all items, but right now it will remain by itself.


BBS Signature

Response to As: Oop Inventory System 2005-12-06 15:45:19


The Inventory Class

Here’s where it gets fun- the inventory class. For now I’m just going to post my commented code for you to copy and paste into a new .as file:

class Inventory
{
//instance variables
var Items:Array = new Array(); //Object array to hold all Item objects
var capacity:Number; //user defined inventory capacity
var isFull:Boolean = false; //property to determine whether inventory is full or not
var numItems:Number = 0; //number of items currently in the inventory
var boxSize:Number; //pixel size, squared, of the size of the inventory items
var startX:Number;
var startY:Number; //X,Y coordinates for where to draw the inventory
var spacing:Number; //pixels in between menu items
var itemsPerRow:Number; //number of items allowed per inventory row
var hidden:Boolean = false; //custom property for inventory visibility, akin to _visible

//constructor
function Inventory(inCapacity:Number, inBoxSize:Number, inStartX:Number, inStartY:Number, inSpacing:Number, inPerRow:Number)
{
//user-defined variables
capacity = inCapacity;
boxSize = inBoxSize;
startX = inStartX;
startY = inStartY;
spacing = inSpacing;
itemsPerRow = inPerRow;

//redefine other variables to keep them instance-unique
Items = new Array();
isFull = false;
numItems = 0;
hidden = false;

//initialize items array with null values
var i:Number;
for (i=0; i<capacity; i++)
{
Items[i] = null;
}
}

//draw the inventory based on instance variables
function DrawInventory():Void
{
//did they specify the dimensions correct?
if(capacity%itemsPerRow!=0)trace("Warning: Inventory capacity is not evenly divisible by the items per row");

//figure out how many rows
var rows:Number = Math.ceil(capacity/itemsPerRow);

var i:Number;
var j:Number;

var totalBoxes:Number=0;

//loop the rows
for(i=0;i<rows;i++)
{
//make a copy of startX to use for each row since the x position will reset
var curX:Number = startX;

//loop for each item
for(j=0;j<itemsPerRow;j++)
{
//form instance name for box
var boxName:String = "box" + totalBoxes;
totalBoxes++;

//place a new item box
var box:MovieClip = _root.attachMovie("Ibox",boxName,_root.get
NextHighestDepth());

//set its x and y coordinate
box._x=curX;
box._y=startY;

//set its dimensions, just in case
box._width = box._height = boxSize;

//increase x position for next box to be placed
curX += (boxSize+spacing);
}

//increase startY for the new row using spacing and box size
startY += (boxSize+spacing);
}

}

//add an item object to the item array
function Add(inItem:Item):Void
{
var index:Number = nextAvailableIndex();
//place in array
Items[index]=inItem;
numItems++;

//place on stage
var curName:String = Items[index].itemName;
var curClip:MovieClip = _root.attachMovie(curName, "inv_"+curName, _root.getNextHighestDepth());

//determine x and y coords
curClip._x= _root["box"+index]._x + boxSize/2;
curClip._y=_root["box"+index]._y + boxSize/2;

//set event handlers
curClip.onRollOver = function():Void
{
this._alpha=50;
}
curClip.onRollOut = function():Void
{
this._alpha=100;
}

/***********************
HERE IS WHERE YOU DEFINE WHAT YOU WANT THE ITEM TO DO WHEN IT IS CLICKED IN THE INVENTORY!
***********************/
curClip.onPress = function():Void
{
//curently set to remove itself from the Inventory
_root.myInventory.Remove(curName);
}

//check for full
checkCapacity();
}

//this function removes an item from the item array, the stage inventory, and places it back on stage
function Remove(itemName:String):Void
{
//run through the items array and set appropriate value to null
var i:Number;
for(i=0;i<Items.length;i++)
{
if(Items[i].itemName == itemName)
{
_root["inv_"+Items[i].itemName].removeMovi
eClip();
_root[Items[i].itemName]._visible=true;
Items[i]=null;
break;
}
}
numItems--;
checkCapacity();
}

//this is called by each item on the stage, to see if it needs to be visible or not
function isItem(itemName:String):Boolean
{
var i:Number;
var returnB:Boolean = false;
for(i=0;i<Items.length;i++)
{
Items[i].itemName == itemName ? returnB = true: null;
}
return !returnB;
}

//find the first available index in the item array
function nextAvailableIndex():Number
{
//look for first index set to null
var i:Number;
for(i=0;i<Items.length;i++)
{
if(Items[i] == null)break;
}
return i;
}

//hide or unhide the inventory from view
function ToggleVisibility():Void
{
//alter hidden property
hidden = !hidden;

//take care of boxes
var i:Number;
for(i=0;i<capacity;i++)
{
_root["box"+i]._visible = !_root["box"+i]._visible;

//if item exists in that box, hide it as well
if(Items[i]!=null)_root["inv_" + Items[i].itemName]._visible = !_root["inv_" + Items[i].itemName]._visible;
}
}

//quick check to see if the inventory is full
function checkCapacity():Void
{
numItems == capacity ? isFull=true : isFull=false;
}
}

This is the class that runs your inventory system. Its main methods build you inventory, add items to it, remove items, and toggle the visibility of the inventory. I will break this class apart later. But for now, we’re aiming to get this up and running. The comments should be sufficient for now.


BBS Signature

Response to As: Oop Inventory System 2005-12-06 15:46:46


Now you need some code on the main timeline to make a new inventory object. Place this on the first frame of your movie:

stop();
var once:Boolean =false;
if(!once)
{
var myInventory:Inventory = new Inventory(10,75,100,100,10,5);
myInventory.DrawInventory();
once=true;
}

the ‘once’ variable is just there to ensure that the code runs once. First you create a new Inventory object. The constructor works as follows:

Inventory(capacity:Number,boxSize:Number,s
tartX:Number,startY:Number,spacing:Number,
itemsPerRow:Number)

capacity: the number of slots to be drawn in the inventory
box size: the squared dimension of how large each slot is. In this case, 75x75
startX and startY: the starting coordinates of where this inventory will be drawn.
spacing: the number of pixels placed in between each inventory item, both horizontal and vertical
itemsPerRow: the number of slots per row that you want to display. This number must divide into capacity evenly, or else it will not work right. A warning will be thrown if you enter a bad number. If you have a capacity of ten, your itemsPerRow can only be one, five, or ten. Understand?

Now that you define the inventory, you call the DrawInventory method to actually place it on the screen. Test your movie and you should see a blank inventory show up

Items on the screen
So we have an inventory on the screen, but we need items to place inside of it. Pull out the instances of the items you drew in your library and put this code on them:

onClipEvent (load) {
_visible = _parent.myInventory.isItem(_name);
}
on (press) {
//can an item be added? check if inventory is hidden or full
//if either, don't do anything
if (!_parent.myInventory.hidden && !_parent.myInventory.isFull)
{
//create item object, add to inventory
var myItem:Item = new Item(_name);
_parent.myInventory.Add(myItem);
//change to invisible
_visible = false;
}
}

The code for all items is the same. First a load event to see if the item needs to be visible or not. If someone picks the item up and comes back to this area, we don’t want it to appear. This makes use of the Inventory.isItem function, which accepts a name and runs through its items to make sure the item doesn’t exist inside of it. If it does, it turns itself invisible. Note: this means all your items must have unique instance names, which they should anyway.
The the on press handler. First it makes use of two key properties of the Inventory class, isFull and hidden. If the inventory is full or hidden, we don’t want to add an item to it. Otherwise, we create a new Item object (from the basic item class I showed you earlier) using the movieclip’s instance name. Then we call Inventory.Add() to add this newly created item to the Inventory’s item array

Breaking apart the Inventory Class

Here is a breakdown of the methods inside the Inventory class- what they do and why they are there-

Inventory
Well, this is the constructor. Remember when you made a new Inventory object and passed all those numbers to it? This is where they come to. The Constructor simply takes those input values and places them into the instance-specific values. Something to take note of is the Items() Array that is here. This is not an array of numbers, strings, chars, etc. This is an array of objects, specifically, Item objects.

Draw Inventory
This function does a lot of work. Based on the capacity and items per row, it runs a nested for loop to place instances of your blank inventory clip on stage. It also throws an warning if you specified bad values- such as a capacity of 11 and 5 items per row (doesn’t work evenly)

Add
This function accepts an item object that you want added to your array. First the nextAvailableIndex function is called to find where the first open slot in the inventory is. Once found the item object is placed into that slot. Remember that the boxes(slots) on stage run parallel index-wise. IE box0 = Items[0]. Using that, an instance of that item is placed on stage from the library and given proper x and y coordinates to line up with that box. Items are also assigned their event handlers here. First, a rollover and rollout handler for changing the alpha. Then an onclick handler is set to call the remove function. You can set this to do whatever you want. Note that instead of directly calling the Remove function I have to call _parent.myInventory.Remove(). This is because the scope of the created movieclip does not match that of the class we are currently in.

Remove
As you would guess, this removes an item from the array. It searches the item array to find a name that matches the one passed to it, and sets that entry to null. It also removes the movieclip that was placed in the inventory and sets the original item’s visibility back to visible. Again you can alter this to your liking- maybe you don’t want the original objects to be placed back on the stage. This would also require modification of the code that is on the stage items above.

isItem
This function is called by each item (not yet picked up) when it loads. It searches the Item array to see if it exists inside of it. It returns a Boolean and that Boolean is used to alter the item’s visible property on the stage. If a hammer is picked up from a table, we don’t want that hammer to appear again on the table.

nextAvailableIndex
Simply does a search to find the first index in the array that is set to null. When it finds it that index is returned and the search loop is broken. This is used to complement the Add function

ToggleVisibility
Call this function when you want to turn the inventory’s visibility off or on. It reverses the visible property for all boxes on stage (based on capacity) and then for each of those boxes checks to see if there is a matching item for it. If so, that item’s visibility is reversed as well.

Check Capacity
This is just called whenever the add or remove method is called. Checks to see if the amount of items meets the capacity of the inventory. If so the isFull variable is set to true, otherwise it is set to false. This variable governs whether or not a new item can be added to the inventory


BBS Signature

Response to As: Oop Inventory System 2005-12-06 15:47:08


Well, there you have your inventory. The items are set to call Inventory.Remove() on themselves when they are clicked, so they are placed back on the stage. Also, you can call Inventory.ToggleVisibility() to turn the inventory on or off. Keep in mind though that when I say something like ‘Inventory.ToggleVisibility()’ I don’t literally mean to use ‘Inventory.’ You use whatever instance name you gave your inventory object.. in this case it would be myInventory.ToggleVisibility();

Whew! Still with me? Pat yourself on the back for making it through. You now have an portable, modifiable inventory system to use in your games. And hopefully, you understood the concepts I threw out. If nothing else, I hoped I enlightened you the power of object-oriented programming. Like I said, I am not an authority on object-oriented programming. I just found this to be a good solution to the inventory questions that come up. Please ask questions, correct me, optimize what I have, anything you see fit. I have not extensively tested this system, so I’m curious to see how it will work for others.

Things to keep in mind:
-Your inventory is placed on the screen via attachMovie. This means the only way to remove it is to use removeMovieClip on the parts of it. It will remain through scenes, that is why I provided the ToggleVisibility method
-I will not modify this for you. Yes, there are plenty of things you can do to make this better and more interactive. I’ve given you a starting place, it’s up to you to take it from there ;)
-Inheritence: if you want to get more involved, use the Item class as a base class and create specific item classes that inherit from it. Then you can use instanceof (I think) to determine what type of item you are working with and make changes based on that
-I’m probably forgetting something, but that’s all I can think of for now =)

Thanks for reading!


BBS Signature

Response to As: Oop Inventory System 2005-12-06 15:52:43


Very detailed, well explained, pretty much descriptive. Good work. :D


BBS Signature

Response to As: Oop Inventory System 2005-12-06 15:53:37


At 12/6/05 03:52 PM, BrotherToast wrote: Very detailed, well explained, pretty much descriptive. Good work. :D

I second that.

Not to mention it mustve been a shitload of work, Afro.

Response to As: Oop Inventory System 2005-12-06 16:01:05


Yeah, it's very detailed and good. Nice work =D


BBS Signature

Response to As: Oop Inventory System 2005-12-06 16:20:36


Really, really good work on this. As you stated, it's not a mind-blowing inventory, but that's not really what classes are for. It's great to see a tutorial from you, too.

Now, there is only one thing that left me confused. Is there a way, a variable or parameter to tell what the linkage name of the slot's graphic are? Because I can't find it. Did you just forget it, or am I blind? =P


BBS Signature

Response to As: Oop Inventory System 2005-12-06 16:24:16


At 12/6/05 04:20 PM, Santazien wrote:
Now, there is only one thing that left me confused. Is there a way, a variable or parameter to tell what the linkage name of the slot's graphic are? Because I can't find it. Did you just forget it, or am I blind? =P

you can't see a symbol's linkage name, but you can see its instance name with MC._name. I kept the linkage names and instance names the same though so it would work smoothly


BBS Signature

Response to As: Oop Inventory System 2005-12-06 16:29:28


At 12/6/05 04:24 PM, Afro_Ninja wrote: you can't see a symbol's linkage name, but you can see its instance name with MC._name. I kept the linkage names and instance names the same though so it would work smoothly

No, I meant differently... Let me put it this way, I know the linkage name to my graphic, only the code doesn't. It seems that in the class the linkage name is already specified.


BBS Signature

Response to As: Oop Inventory System 2005-12-06 16:32:44


At 12/6/05 04:29 PM, Santazien wrote:
At 12/6/05 04:24 PM, Afro_Ninja wrote: you can't see a symbol's linkage name, but you can see its instance name with MC._name. I kept the linkage names and instance names the same though so it would work smoothly
No, I meant differently... Let me put it this way, I know the linkage name to my graphic, only the code doesn't. It seems that in the class the linkage name is already specified.

like I said, I kept instance names and linkage names the same. The hammer item to be picked up on the stage has an instance name of 'hammer.' The hammer MC in the library has a linkage ID of 'hammer.' So when the Add method fires, it just needs to use the name of the MC in question to create the linkage

var curName:String = Items[index].itemName;
var curClip:MovieClip = _root.attachMovie(curName, "inv_"+curName, _root.getNextHighestDepth());

in this case Items[index].itemName is set to 'hammer', and 'hammer' is used for the linkage in attachMovie. The hammer in the inventory however, is given a name of inv_hammer


BBS Signature

Response to As: Oop Inventory System 2005-12-06 16:45:28


At 12/6/05 04:32 PM, Afro_Ninja wrote: like I said, I kept instance names and linkage names the same. The hammer item to be picked up on the stage has an instance name of 'hammer.' The hammer MC in the library has a linkage ID of 'hammer.' So when the Add method fires, it just needs to use the name of the MC in question to create the linkage

Sorry, but it still isn't what I'm getting at. I'm talking about the graphic for the slot, this one:

var box:MovieClip = _root.attachMovie("Ibox", boxName, _root.getNextHighestDepth());

Guess I'm kinda stupid though, it clearly says "Ibox", and not a variable or something. It's just that I didn't see any instructions on it. =)


BBS Signature

Response to As: Oop Inventory System 2005-12-06 17:20:01


Fucking hell that was the longest one yet. I'll definately come back and check this out in detail at some point.

Response to As: Oop Inventory System 2005-12-06 17:27:20


tldr

j/k

Hopefully this will be the one to help me finally get my head round OOP =)


- - Flash - Music - Images - -

BBS Signature

Response to As: Oop Inventory System 2005-12-06 17:38:19


At 12/6/05 05:27 PM, Denvish wrote: tldr

j/k

Hopefully this will be the one to help me finally get my head round OOP =)

Hehe, why oh why do you keep changing your name? =P


BBS Signature

Response to As: Oop Inventory System 2005-12-06 21:13:59


At 12/6/05 04:45 PM, Santazien wrote:
Sorry, but it still isn't what I'm getting at. I'm talking about the graphic for the slot, this one:

oh, sorry. Yeah, that was in the first part

First, we need a movie clip to act as a generic ‘slot.’ This is what each item in your inventory will be placed into. I just used a 75x75 black outline square. Make whatever you like, just make sure it is square. Convert it to a movieclip and set its linkage identifier to “Ibox.” Make sure its registration point is set to the top left. THIS IS IMPORTANT.


BBS Signature

Response to As: Oop Inventory System 2005-12-06 21:15:09


At 12/6/05 05:27 PM, Denvish wrote: tldr

j/k

Hopefully this will be the one to help me finally get my head round OOP =)

eh, I don't really explain many of the OOP concepts.. if you want to learn flash OOP, I highly suggest visiting the link I gave to senocular's OOP tutorial : )


BBS Signature

Response to As: Oop Inventory System 2005-12-06 21:26:33


At 12/6/05 09:15 PM, Afro_Ninja wrote: eh, I don't really explain many of the OOP concepts.. if you want to learn flash OOP, I highly suggest visiting the link I gave to senocular's OOP tutorial : )

Hmmm, I do understand the concept, and even the way works - I could probably write classes no problem, if I put my mind to it - but it just doesn't seem to me that there's any real advantage to OOP over procedural. In fact, if anything, I'd get annoyed with the fact that I have to mess with (and save) one or more .as files. As far as I can see, the code that's used in classes is pretty much identical (except it requires more typing Public Private and strict definitions) to the code I normally use, and I just find it easier to click a movieclip and see what actions it has on it, rather than having to try and find the appropriate section in the .as file.

I dunno. Maybe if I attempt an RPG or something, I'll need to start using classes, but I'm currently pretty happy just coding normally.


- - Flash - Music - Images - -

BBS Signature

Response to As: Oop Inventory System 2005-12-06 22:17:48


I just think oop is really good for visualizing virtual objects. Helps keep things organized. I'll make a class and an array of those objects way before I mess with a two dimensional array


BBS Signature

Response to As: Oop Inventory System 2005-12-06 22:20:32


Wow, VERY excellent. I tried doing this myself before (in AS and Visual Basic), didn't go very far. I'm sure I'm going to use this tutorial sometime in the future :)


BBS Signature

Response to As: Oop Inventory System 2005-12-07 10:33:24


At 12/6/05 09:13 PM, Afro_Ninja wrote: Convert it to a movieclip and set its linkage identifier to “Ibox.”

Yeah, that was the part I missed. Thanks


BBS Signature

Response to As: Oop Inventory System 2005-12-07 13:01:20


At 12/6/05 09:26 PM, Denvish wrote: Stuff

That's true, but the main reason I like OOP is the portability (as Afro mentioned). I can create a class for something but then use it in something else, or I can create a class and use it all the time if it's that good. Say I create a class called Debug and it has the following actions:

class Debug {
static function cout():Void {
trace(arguments); //function stolen from dELta :P
}
static function setPosition(mc:MovieClip, coord:Array):Void {
mc._x = coord[0];
mc._y = coord[1]; //function is useless, useless I say :P
}
}

Then I place it in a folder which I have set as one of my class directorys, then I can just do

Debug.cout(1, 2, 3, 4, 5); or Debug.setPosition(_root.hero, [275, 200]);

Rather than re-writing the function over and over again every time you want to use it, you can just make it a static function in a class and use it like that.


Sup, bitches :)

BBS Signature

Response to As: Oop Inventory System 2005-12-07 13:19:41


At 12/7/05 01:01 PM, -Christmas- wrote:
At 12/6/05 09:26 PM, Denvish wrote: Stuff
That's true, but the main reason I like OOP is the portability (as Afro mentioned). I can create a class for something but then use it in something else, or I can create a class and use it all the time if it's that good. Say I create a class called Debug and it has the following actions:

class Debug {
static function cout():Void {
trace(arguments); //function stolen from dELta :P
}
static function setPosition(mc:MovieClip, coord:Array):Void {
mc._x = coord[0];
mc._y = coord[1]; //function is useless, useless I say :P
}
}

Then I place it in a folder which I have set as one of my class directorys, then I can just do

Debug.cout(1, 2, 3, 4, 5); or Debug.setPosition(_root.hero, [275, 200]);

Rather than re-writing the function over and over again every time you want to use it, you can just make it a static function in a class and use it like that.

i think procedural (sp? + right word?) would be better here:

//util.as (stolen from AS3)
_global.cout = function()
{
trace(arguments);
}

then in your flash file

#include "util.as"

then you can just use cout(1,2,3,4,"g2",",g2",[1,2,]); or whatever from anyway in the flash file after being included, but without doing ClassName.cout();

Response to As: Oop Inventory System 2010-07-22 17:31:44


It doesn't work for me. I don't know why. I have the .as files name the same as the class and in the same folder.

heres the flash files I am using to test the inventory:
http://www.mediafire.com/file/uhtdlidpiy qcjue/OOPtry.rar

hopefully someone can help me out. I am really stumped. Thanks in advance.

Response to As: Oop Inventory System 2010-07-22 23:22:00


Why are you trying to bring back a topic that was posted 5 years ago??

Response to As: Oop Inventory System 2010-07-23 01:38:15


At 7/22/10 05:31 PM, zakn wrote: It doesn't work for me. I don't know why. I have the .as files name the same as the class and in the same folder.

heres the flash files I am using to test the inventory:
http://www.mediafire.com/file/uhtdlidpiy qcjue/OOPtry.rar

hopefully someone can help me out. I am really stumped. Thanks in advance.

dELtaluca: 12/7/05
zakn: 7/22/10

lol

http://www.mediafire.com/file/uhtdlidpiy qcjue/OOPtry.rar

This isn't trying OOP, this is copy pasting OOP. You might have more success if you TRY.


#include <stdio.h>

char*p="#include <stdio.h>%cchar*p=%c%s%c;%cmain() {printf(p,10,34,p,34,10);}";

main() {printf(p,10,34,p,34,10);}

BBS Signature