开发者

AS2 Inventory System

I'm attempting to create an Inventory System written in action script 2 (flash as2) I'm trying to create one that has inventory spots dynamically created and a movie clip remotely loaded into the mc in the inventory spot.

I cannot find any online guide on how to do this (Only man开发者_如何学编程ual ones which you have to create the inventory spots yourself)

Would anyone be able to point me in the right direction to do this?

Any help is greatly appreciated!

Thanks Daniel.


I don't understand how you imagine this inventory system: how does it look ? how does it work ?

From a simplified perspective I understand you have a list of items that will be loaded from an external source(csv file parsed using LoadVars, xml file, etc.) and you want to display them. I would split it into this:

  • a data source(txt,xml,etc.)
  • a data provider - in the end you will have items for the invetory,each item will have properties(label,image, price, etc.)
  • a draw/render method (items in a horizontal/vertical list, tile list, data grid, etc.)

For displaying the item dinamically, I recommend having a look at the MovieClipLoader class. You could use MovieClip's loadMovie() method, but MovieClipLoader is more flexible(you can find out if the item is loading(%), get it's dimensions, etc.) as opposed to the loadMovie() method.

Regardless of your data source, you will end up with an array of inventory objects that will have properties I presume.

Here is a basic approach to displaying inventory items:

//using dummy data, you would populate the array by parsing loaded vars or xml, whatever works best for you
var dataProvider:Array = [];
var dummyItems:Number = 20;
for(var i:Number = 0 ; i < dummyItems ; i++) dataProvider[i] = {label:'item '+i,source:'http://stackexchange.com/images/icon/stackoverflow.com'};
//make a container
var inventory:MovieClip = this.createEmptyMovieClip('inventory',1);
var inventoryMask:MovieClip = this.createEmptyMovieClip('inventoryMask',2);
inventoryMask.beginFill(0);inventoryMask.lineTo(Stage.width,0);inventoryMask.lineTo(Stage.width,50);inventoryMask.lineTo(0,50);inventoryMask.lineTo(0,0);inventoryMask.endFill();
inventory.setMask(inventoryMask);
//add items to it
for(i = 0 ; i < dummyItems ; i++) makeInventoryRenderItem(dataProvider[i],inventory,i);
//scroll on mouse over
inventory.onRollOver = function():Void{
    inventory.onEnterFrame = function(){
        inventory._x = -_xmouse;//this is just a stub, replace with any navigation method you wish
    }
}
inventory.onRollOut = function():Void{
    delete inventory.onEnterFrame;
}
//make a movie clip with a loader and a label
function makeInventoryRenderItem(data:Object,container:MovieClip,index:Number):Void {
    var renderItem:MovieClip = container.createEmptyMovieClip(data.label,index);
    var loader:MovieClipLoader = new MovieClipLoader();
    loader.loadClip(data.source,renderItem);
    var handler:Object = new Object();
    handler.onLoadInit = function(target:MovieClip):Void{
        target._x = (target._width + 2) * index;
        var label:TextField = renderItem.createTextField(data.label+'Label',renderItem.getNextHighestDepth(),0,0,40,22);
        label.text = data.label;
    }
    loader.addListener(handler);
}

and here's a preview:

AS2 Inventory System

Note that this is not a fast/efficient way of writing it, but is a simple one, to illustrate the idea easier.

A different approach:

As another option, if filesize isn't a problem, you could use components(you can get about 70KB of bload just from them). An advantage is, there already are ways to handle data without touching too much code and you can either use hacky way to display your items, or create custom cell renderers.

Here's a basic approach using a List and a XMLConnector:

  • Add a List component to the stage, name it ls

  • Add a XMLConnector (from the Data components) and name it xml

  • Create an xml file with the structure you choose.

I used a structure like this:

<data>
  <item label="item 1" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 2" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 3" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 4" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 5" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 6" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 7" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 8" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 9" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 10" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 11" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 12" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 13" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 14" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 15" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 16" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 17" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 18" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 19" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
  <item label="item 20" source="http://stackexchange.com/images/icon/stackoverflow.com"/>
</data>

In the Parameters tab of the Component inspector you need to set the URL to your xml, and the direction to receive.

The next thing is to import the xml schema into the XML connector, so it can 'understand' the structure of your xml file. You do so by pressing the import schema button in the Schema Tab of the Component Inspector.It's the tiny button on the top right of the tab with the tiny blue arrow pointing downards. Also, make sure your results are selected.

AS2 Inventory System

You will see the results update and an array will be created from your xml, you can also see each object's property.

Now that the xml schema/structure is imported, we can create a binding. We do that by pressing the + icon the Bindings tab of the Component Inspector:

AS2 Inventory System

The Add Binding dialog will appear, this is where you select the Array element and press OK.

AS2 Inventory System

In my case it's called item, it could be called something else, depending on the xml, but the idea is you choose the element containing the repeating([n]) items.

The next step is to bind the incoming data to something, in this case, to our list component. Set the direction to out, then double click the bound to value:

AS2 Inventory System

The Bound To dialog will pop up. This is where we'll select the list and it's data Provider as the receivers.

AS2 Inventory System

That is all the component Inspector you need to do. Now you have something that loads and handles your xml and sends the data to the list when it's ready.

Now we just create an empty MovieClip, named Icon, we draw a 50x50 border, because it will hold the stackoverflow icon(48x48) inside, and we Export for Actionscript (Linkage)

These last steps involve 7 lines of actionscript. In the main timeline we trigger the xml connector, we set the defaultIcon style property, set the row height, so the inventory image/logo will fit, and disable roll over, just to avoid redrawing on that event:

xml.trigger();//trigger the xml loading
ls.setStyle('defaultIcon','Icon');//use your library clip as an icon
ls.setStyle('useRollOver',false);//stop redrawing list item on rollOver
ls.rowHeight = 48;//you should know the size of the inventory item

Now the last 3 lines of code are quite hacky because what we're doing is using the Icon of the list(which usually is the same library item repeated) to find the index of the item from the icon clip itself, and so accessing the list, the data provider and therefore the data for each icon clip.

We place this code in the Icon movieClip:

var index:Number = parseInt(_parent._name.substr(7))-10;//hack #1 use the rendered icon clip's name property to get it's index
var image:MovieClip = createEmptyMovieClip('image',1);
image.loadMovie(_parent._parent._parent.dataProvider.getItemAt(index).source);//hack #2 'clip' up from the icon clip to the list to find the list and source property for current item

And that's it, you get a list that displays labes and images from an xml file:

AS2 Inventory System

This is an option if you are willing to use components, and just want a hacky way with less code. If you still want to use the components, but do it the right way, You need create a custom Cell Renderer, which will display data for each inventory item. There's a very good tutorial on the flash-db site for this.

HTH

UPDATE:

I've just read the rest of the comments. @gmale is right, attachMovie is what you need if you plan to use items from the library. you use it like this:

theContainerForYourItem.attachMovie('itemLinkageName','someOptionalName',depth);//note depth is a number

here's a simple test, you must change the itemSize and either linkage strings(either you have clips in the library with the same names the ones used in code, or you update the names in the code):

var selectedItem:MovieClip;//this will keep track of the selected item
var itemSize:Number = 67;//set this to the size of a inventory item
var inventoryIds:Array = ["New","Folder","Disk","Mail","Graph"];//item linkage ids, make sure you've got some movie clips in library with these ids, or update the array
var inventory:MovieClip = this.createEmptyMovieClip("inventory",0);//container
var level:MovieClip = this.createEmptyMovieClip("level",1);
//create items
for(var i:Number = 0 ; i < inventoryIds.length ; i++){
    //create container for item
    var itemContainer:MovieClip = inventory.createEmptyMovieClip('item'+i,i);
    //draw border, invisible bg
    itemContainer.lineStyle(1);itemContainer.beginFill(0,0),itemContainer.lineTo(itemSize,0);itemContainer.lineTo(itemSize,itemSize);itemContainer.lineTo(0,itemSize);itemContainer.lineTo(0,0);itemContainer.endFill();
    //position, add library item
    itemContainer._x = (itemSize+2) * i;//2 is just spacing
    itemContainer.attachMovie(inventoryIds[i],'icon',0);
    itemContainer.onPress = itemSelected;//selec item
}
function itemSelected():Void{
    //if there was previously an item removed, restore it...depends on your game's logic, u need clicks though
    if(lastItem != undefined) restoreItemToInventory();
    trace('selected item is: ' + inventoryIds[this.getDepth()]);//trace ths selected item
    this.getInstanceAtDepth(0).removeMovieClip();//and remove the icon from the invotory
    delete this.onPress;//disable clicks
    lastItem = this;//update the last Item for restoring
    //draw an item inside the level
    var levelItem:MovieClip = level.attachMovie(inventoryIds[this.getDepth()],'icon',0);
    levelItem._x = Stage.width * .5;level._y = Stage.height * .5;//position item;
    levelItem.onPress = itemUsed;
}
function restoreItemToInventory():Void{
    lastItem.attachMovie(inventoryIds[lastItem.getDepth()],'icon',0);//attach the icon again
    lastItem.onPress = itemSelected;//make restore click
}
function itemUsed():Void{
    this.removeMovieClip();//remove from stage
    trace('item is: ' + inventoryIds[lastItem.getDepth()] + ' was used');//do whatever to hero/enemies
    restoreItemToInventory();//restore to inventory or not
}

Note that for each library item I use a container. The reason for this is, when I remove an item, in fact I just the remove the library item the container holds, and the container is still there, and mentains it's depths, which is the same as the index of the item in the array. This is used later to remove/attach inventory items. In general it's a bad practice, since there are tightly coupled elements, but for the sake of a simple demo, will do.

If in your game, new items will be added(player won't have all possible items at once) and removed, used...it might also be worth learning how to use the Array class, especially the splice() method which will allow you to add, remove items from an array at a given index. based on your updated inventory array you will display the items and setup interactivity.


This sounds like something I can help you with but I need more information on what you're trying to do.

Also, is there a good reason you're using AS2 instead of actionscript 3?

From what I can gather, it sounds like you have one movieclip (let's call it the "parent container") and you want to load another clip into it, dynamically.

If I'm correct, you're in luck because this is a very common way to use ActionScript. There are guides everywhere on it. I'm writing an application right now that does this very thing in AS3. Given a parent container, it dynamically loads different movieclips into it over time based on how the user navigates or what is selected. However, my project is in AS3.

In AS2, this same technique is achieved using the attachMovie() method of MovieClip.
Here is the old support document for that feature.

There's a great working example here:
ActionScript.org - Using attachMovie


Alternatively, you may be trying to dynamically load data into your movie. Again, this is also a common usage for flash so you will definitely be able to get this done.

Here are some examples that may help:
Thorough example on Loading vars that came from PHP
Loading variables from text files


If none of that helps, provide some more details and we all can help you a little easier.

Hope that helps in some way,

-gMale


Just set it to put item in the next open slot. It's not that hard.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜