RPG Inventory

August 22nd, 2008

This tutorial is continuing from the RPG tutorials previous posted, RPG Character Movement Part 3

Making an inventory for our Hero is needed. Our Hero is most likely going to pick up items along his/hers journey, and those items need to stored and saved for later use. The Hero could pick up some Potion or Bread and use that to heal himself when low on HP (Hit/Health Points). Well, lets start setting up a in game menu movie clip which is of course very needed as well. The in game menu movie clip at this point will just have a button called “Inventory” which will open a list of items our Hero has been carrying around, but we can use the in game menu for other things like “Options”, “Quests”, etc. But for now, lets just do the Inventory. Before I begin, prepare yourself for a lengthy tutorial.. but I assume you knew that before beginning? Lets start…

(note, if you are downloading the .fla file, and you have kept up to date from the previous tutorials, you will notice several changes which the level object… it no longer exists!)

The In Game Menu:
Firstly, create a new movie clip and give it an name of “InGameMenu” and check the box “Export for Actionscript” and make sure the registration point is in the top left corner. This if you recall, allows us to attach the movie clip to the stage from our Actionscript code. Next create 5 (thats right, five) layers in this movie clip, naming them from bottom to top “border”, “menu_btns”, “menu_text”, “–flags–“, and “–script–“. Now use the Rectangle tool to create a border in the “border” layer. The border should have the same dimensions as the game’s width and height, and it should have no fill color. So when you select the Rectangle tool, select a border color and no fill. Align the border to be left and top of the “InGameMenu” movie clip.

Now in the top right of the InGameMenu movie clip, in the first frame on the “–flag–” layer, give the frame a name of “menu”. Next, add a static text field and write the word “Inventory” in it. Then create another movie clip called “Box” and again, click the “Export for Actionscript” checkbox. This Box will be used a lot through our RPG game. We will be using this Box as a button, but for now it will just be our Inventory button. In the Box movie clip create a Rectangle of any size (mine is 30×30) and align it to be in the top left corner. Next, open up the InGameMenu and drag the Box movie clip we just created under the Inventory text and give it an instance name of “btn_inventory”. Adjust the Inventory text and button so they are on the proper layers in the movie clip. You should have something like this when you are up to this point (I highlighted everything on the stage):

The Inventory Menu:
In the InGameMenu movie clip, add up to 20 frames for all the layers. Next, create a folder in the movie clip (its right next to the “New Layer” button) and name it “Inventory”, and create 3 new layers in that folder called (from bottom to top) “bg” (short for background), “images/btn”, “text”. On frame 10 in the “–flag–” layer, give the frame a name of “inventory”. Now create 1 keyframe for each of the new 3 layers on frame 10. This is what your timeline should like so far (ignore the “a” in the timeline for now, we will do that shortly):

Next, create a new movie clip (this is the last movie clip to create I promise) and name it “InventoryImages” and this time you don’t need to click the checkbox, we will be adding this movie clip to the stage manually. Open the InventoryImages movie clip and create the layers, from bottom to top, “border”, “graphic”, and “–flag–“. In the “border” layer create another border as we did for the InGameMenu movie clip about 30×30. Create about 20 additional frames to this movie clip and for every 5 frames, create a key frame for both the “graphic” and “–flag–” layers. In the “–flag–” layer write a name of an item on the frame, except for frame 1. For example, in frame 5 I am going to write “Potion”, and in frame 10 I am going to write “Cloth” on the “–flag–” layer. And on the “graphic” layer I will draw a picture to represent that item. Here is an example of what you should have:

Now lets move back to the InGameMenu movie clip to polish it up and to write some code.

Open the InGameMenu by double clicking on it in the Library. In the first frame on the “–script–” layer write this code:

[as]
stop();

// make it a button
btn_inventory.buttonMode = true;

// add events
btn_inventory.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {

gotoAndStop(“inventory”);

});
[/as]

This is just simply making the “btn_inventory” movie clip instance that we placed earlier on the stage a button. Once the gamer clicks on the button, they will be taken to the frame that has the label “inventory” within the InGameMenu movie clip. But right we don’t have anything on the “inventory” frame, correct? Right, so lets make our inventory. On the “bg” layer in the “inventory” folder create a solid rectangle and place it on the stage. This will be used as the background of our inventory. Next, on the “text” layer, create two dynamic text fields on top of the rectangle and give one an instance name of “count” and the other “description”. This will tell the game the description of the item and quantity. On the “images/btn” layer, drag and drop the “InventoryImages” movie clip on the stage and duplicate it 20 times in a nice ordered form. After you have duplicated the movie clip 20 times, give each one an instance name of “i[n]”. So, i0, i1, i2, i3, all the way to i19. In the end, you should have some thing like this on the frame “inventory”:

If you have done well up to this point, we more than half way done. Lets write the rest of the code shall we?

Now on the same frame, in the “–script–” layer, write this code:

[as]
stop();

// make it a button
btn_inventory.buttonMode = true;

// add events
btn_inventory.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {

gotoAndStop(“menu”);

});

// loop through inventory and display
// lets also set up the buttonMode and events
for(var i:int = 0; i < 20; i++) { // set everything to empty count.text = ''; // no count description.text = ''; // no description this["i" + i].buttonMode = false; // no buttonMode this["i" + i].gotoAndStop(1); // go to the empty frame // first, lets remove the events, if any if(this["i" + i].hasEventListener(MouseEvent.CLICK)) { this["i" + i].removeEventListener(MouseEvent.CLICK, inventory_click); this["i" + i].removeEventListener(MouseEvent.ROLL_OVER, inventory_roll_over); this["i" + i].removeEventListener(MouseEvent.ROLL_OUT, inventory_roll_out); } // if the hero has something in the inventory if(MovieClip(root).hero.inventory[i]) { // get the name and count, 'c' for short, of the item var nm:String = MovieClip(root).hero.inventory[i][0]; var c:int = MovieClip(root).hero.inventory[i][1]; // have the button/movie clip hold the name and count of the item, this will be used a reference later this["i" + i].nm = nm; this["i" + i].count = c; // show graphic this["i" + i].gotoAndStop(nm); // set buttonMode back to true this["i" + i].buttonMode = true; // add events this["i" + i].addEventListener(MouseEvent.ROLL_OUT, inventory_roll_out); this["i" + i].addEventListener(MouseEvent.ROLL_OVER, inventory_roll_over); this["i" + i].addEventListener(MouseEvent.CLICK, inventory_click); } } // the functions function inventory_roll_out(e:MouseEvent):void { count.text = ''; description.text = ''; } function inventory_roll_over(e:MouseEvent):void { count.text = "Total: " + e.target.count; description.text = MovieClip(root).game_item["" + e.target.nm + ""]; } function inventory_click(e:MouseEvent):void { MovieClip(root).inventory_action("use", e.target.nm); nextFrame(); // in the next frame it goes back to this frame, this is a quick and dirty way to reload this script } [/as] All of the code has an explanation of what it is doing or going to do. If you followed along from the beginning of the RPG tutorials, this type of structure should be very understandable. You may be asking, "where is this MovieClip(root).hero.inventory variable coming from”, and “what does MovieClip(root).inventory_actions('use', e.target.nm) do?”. Well, those are answers are going to be coming up shortly. MovieClip(root) simply reads the root of the flash player. If you are familiar with Actionscript 1 and 2, its the same as _root. And for the game_item and hero.inventory and inventory_actions, one is a global variable, a property, and the other is the function. Lets do those two parts and be done with our tutorial.

Go back to the main time line of the stage and click on the “–script–” layer.

Add these properties to your hero object:

[as]
hero.inventory = new Array();
hero.inventory[0] = new Array(“Potion”, 2);
hero.inventory[1] = new Array(“Cloth”, 10);
hero.inventory[2] = new Array(“Key”, 1);
[/as]

Here we are creating an inventory array which holds our Heros items. If you looked at it more closely, its a two dimensional array. For each item the Hero has in his inventory, we keep track of the items name and quantity. Right after those lines, add these:

[as]
// items
var game_item:Array = new Array();
game_item[“Potion”] = new Array(“This potion is very special, it can heal 20 HP”);
game_item[“Cloth”] = new Array(“A cloth found on the ground. It’s a little dirty, you need to wash it”);
game_item[“Key”] = new Array(“This is a key that was given to for free because you visited gregathons.com and read the tutorial”);
[/as]

This is our global variable game_item which is also an array. This array however uses the indexing through a string, which is in this case, the string name of the item. This is also a two dimensional array. Here is the inventory_action function that does magic, place it at the top of the functions we have already written:

[as]
function inventory_action(action:String, item:String, count:int = 1):void {

var i:int;

// if we are using the item
if(action == “use”) {

// loop through inventory
for(i = 0; i < 20; i++) { if(hero.inventory[i]) { if(hero.inventory[i][0] == item) { hero.inventory[i][1] -= count; if(hero.inventory[i][1] <= 0) { inventory_action("drop", item); } break; } } } // if we are ridding of the item } else if(action == "drop") { // again, lets loop for(i = 0; i < 20; i++) { if(hero.inventory[i]) { if(hero.inventory[i][0] == item) { hero.inventory.splice(i,1); } } } } } [/as] 1 Create a function inventory_action which requires two variables/parameters and one optional. We pass the action that we are going to be doing and the item we are going to do it to. The variable count is already declared and set to 1, assuming when you pick up an item, or drop, or use an item, it will be 1.
3 Declare a local variable i. Flash doesn’t like it when you create multiple local variables, even if they are being using in if and else ifs
6 If the action variable passed equals “use”, continue inside the if block
9 Begin looping through the items
10 Check to see if the Hero has an item before we check we check the name of the item
11 Check if the Hero’s inventory item matches the passed item
12 Subtract the hero.inventory[i][1] count by the passed count variable. Where i is the name of the item
13 – 15 If we don’t have any more of that particular item, we run the same inventory_action function but this time passing the string “drop” instead
16 We stop the for loop because we are done with it
22 Check if the action variable matches “drop”, if so we continue inside of the if block
25 – 30 Same as before, we loop through the Hero’s inventory checking if the Hero has an item, if the item strings match, but instead using the function splice to get rid of it for good from the Hero’s inventory
35 Close the function inventory_action

We will sometime in the future go more in depth of this function, like adding an item, what to do when we use it, etc. But for now, we have the basics of it working. If you think we are done, we have two VERY small and important things left to do. First we need to add our InGameMenu to the stage, and secondly we need to have it move with our Hero as he journeys our level/world. In the game_begin function, add these lines after placing our Hero:

[as]
// add menu
var igm:InGameMenu = new InGameMenu();
igm.name = “ingamemenu”;
game.mc.addChild(igm);
[/as]

Here we are just giving it a instance name of “ingamemenu” so we can reference it later when needed, like in the center function. In the function center add these lines at the end:

[as]
// get the menu and set its coordinates
var igm_mc:MovieClip = game.mc.getChildByName(“ingamemenu”);
igm_mc.x = Math.abs(root_mc.x);
igm_mc.y = Math.abs(root_mc.y);
[/as]

Well, that is everything. Sorry that seemed long and tedious, but adding an inventory to a game isn’t something you can just draw… it takes a bit to set up and get going. Here is a sample of it working and the .fla file to look through if you got lost along the way.

Click on the item to “use” it and leave the Hero’s inventory.

AS3 > Games > RPG

2 Responses to “RPG Inventory”

  1. Watkins577 Says:

    When I open the inventory, it comes up in output ‘TypeError: Error #1006: hasEventListener is not a function.
    at InGameMenu/frame10()’
    Why does it say this?
    Also the inventory things seem to be scrolling through without stopping EXCEPT for i0.

  2. Watkins577 Says:

    Nevermind… Seems that my code was wrong somewhere