Flash AS3 Tutorial: How To Put TileList Pictures Beside Label Text

Leave a comment Standard

So I wanted to make a chat room list with icons formatted beside it and I thought, why not just use a TileList? It already shows images and scrolls so I’ll save myself some trouble. I thought it would incredibly easy and intuitive to change the layout of how the images/label were being displayed but BOY WAS I WRONG!! So hoping to save you the three days of research I spent trying to figure this out here you go:

1. Create a new as3 flash .fla file. Modify the properties and click on the settings next to where it says Actionscript 3. Uncheck the strict errors and warnings boxes.

2. Click on the components tab in the library and drag the TileList component onto the stage. Do the same for a Label component.

3. Delete the TileList and Label components from the stage. You’ll notice they are still available in your library.

4. Create a new as3 file called myTileList.as and put it in the same location as the as3 .fla file.

5. Find the properties section for the .fla file. Where it says class type in myTileList. This will tell the .fla we want to load this .as file when we compile and then execute our flash file.

6. Create three new movie clip objects called Mod_Icon, Reg_Icon and Speaker_Icon. These are the images that will show up beside the user names in the list. Now take a .png image and put it in an icons folder in the same location as your .fla and .as files. We’ll use this so you can see the difference in how to load external files and how to load display objects. Save your myTileList.fla file.

6. Now we’ll update the myTileList file so that it adds a TileList to the stage so we can do some simple interactions with it. Put this into your myTileList file:

/****
* File: myTileList.as
* Author: design1online.com, LLC
* Date: 9.4.2011
* Purpose: display a list of chat room user
****/
package {

    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;

    import fl.controls.Label;
    import fl.events.ListEvent;
    import fl.controls.TileList;
    import fl.controls.ScrollPolicy;
    import fl.controls.ScrollBarDirection;
    import fl.data.DataProvider;

    import UserListRenderer;

    public class myTileList extends MovieClip {

        //Labels
        private var msg_lbl:Label = new Label();

        //Lists
        private var user_tilelist:TileList = new TileList();

        /****
        * Purpose: default constructor
        * Precondition: none
        * Postcondition: build what appears on the stage
        **/
        public function myTileList()
        {            

            //add the TileList to the stage
            user_tilelist.width = 170;
            user_tilelist.height = 100;
            user_tilelist.move(200, 40);
            user_tilelist.columnWidth = 170;
            user_tilelist.rowHeight = 30;
            user_tilelist.visible = true;
            user_tilelist.direction = ScrollBarDirection.VERTICAL;

            /**
            * this tells the tileList to use our userListRenderer class to
            * change the way it displays each item in the list
            **/
            user_tilelist.setStyle("cellRenderer", UserListRenderer);

            //this adds the list to the stage
            addChild(user_tilelist);

            //add a label to the stage to show what we've selected
            msg_lbl.width = 170;
            msg_lbl.height = 100;
            msg_lbl.x = 200;
            msg_lbl.y = 150;
            msg_lbl.text = "Select a user above.";
            msg_lbl.visible = true;
            addChild(msg_lbl);

            //Add an event listener
            user_tilelist.addEventListener(ListEvent.ITEM_CLICK, clickUserHandler);

            //Load the list
            loadUserList();

        }

        /****
        * Purpose: draw the users list
        * Precondition: none
        * Postcondition: user list has been updated
        ****/
        private function loadUserList()
        {

            var dp_mod:DataProvider = new DataProvider();
            var dp_reg:DataProvider = new DataProvider();
            var dp_speak:DataProvider = new DataProvider();
            var dp_users:DataProvider = new DataProvider();
            var users:Array = [{name:"John", privileges:"mod"}, {name:"Amy", privileges:"regular"}, {name:"Lucas", privileges:"reg"}, {name:"Claire", privileges:"speaker"}];  
            var icon = Reg_Icon;

            for (var u:String in users)
            {
                switch (users[u].privileges)
                {
                    case "mod":
                        icon = Mod_Icon; //is a moderator using the movie clips we have in the library
                        dp_mod.addItem( {label: users[u].name, source: icon, data:users[u] });
                        break;
                    case "regular":
                        icon = Reg_Icon; //is a regular member
                        dp_reg.addItem( {label: users[u].name, source: icon, data:users[u] });
                        break;
                    case "reg":
                        icon = "icons/reg.png"; //you can also use a URL or a relative link to where this image is uploaded
                        dp_reg.addItem( {label: users[u].name, source: icon, data:users[u] });
                        break;
                    case "speaker":
                        icon = Speaker_Icon; //is a speaker
                        dp_speak.addItem( {label: users[u].name, source: icon, data:users[u] });
                        break;
                }
            }

            //sort the lists
            dp_reg.sortOn("label", [Array.DESCENDING, Array.NUMERIC, Array.CASEINSENSITIVE]);
            dp_mod.sortOn("label", [Array.DESCENDING, Array.NUMERIC, Array.CASEINSENSITIVE]);
            dp_speak.sortOn("label", [Array.DESCENDING, Array.NUMERIC, Array.CASEINSENSITIVE]);

            //merge the lists
            dp_users.merge(dp_mod);
            dp_users.merge(dp_speak);
            dp_users.merge(dp_reg);

            //our final list is sorted by type and user name
            user_tilelist.dataProvider = dp_users;
        }

        private function clickUserHandler(evt:Event)
        {
            /**
            * We have to use evt.rowIndex to get the selected user from the
            * TileList because the event fires before the TileList selectedIndex
            * has been updated. If you're trying to get an item from the tileList
            * and you're not inside one of it's event handlers you would use
            * user_tilelist.selectedIndex in place of evt.rowIndex
            **/
            var selectedUser:Object = user_tilelist.getItemAt(evt.rowIndex).data;

            msg_lbl.text = selectedUser.name + " is a " + selectedUser.privileges;
        }
    }
}

7. Create another as3 .as file and call it UserListRenderer. We’ll use this to change how our TileList looks so the pictures appear beside the label. Put this into your UserListRendererfile:

/****
* File: UserListRenderer.as
* Author: design1online.com, LLC
* Date: 9.4.2011
* Purpose: change the formatting for the user tile list
*    so images appear beside the user name
****/
package {

    import fl.controls.listClasses.ICellRenderer;
    import fl.controls.listClasses.ImageCell;
    import fl.controls.TileList;
    import flash.text.*;

    public class UserListRenderer extends ImageCell implements ICellRenderer {

        public var desc:TextField = new TextField();
        private var textStyle:TextFormat = new TextFormat();

        public function UserListRenderer() {

            //inherit the variables from the parent
            super();

            //we don't want to stretch our images to fit the size of the box
            loader.scaleContent = false;

            //change the cursor as if this was a button
            useHandCursor = true;

            //Create and format the text field
            //that will appear beside the image
            desc.autoSize = TextFieldAutoSize.LEFT;
            desc.x = 24;
            desc.y = 5;
            desc.width = 150;
            desc.height = 28;
            desc.multiline = false;
            desc.wordWrap = false;
            addChild(desc);

            //apply some styles to our text field
            setStyle("imagePadding", 2);
            textStyle.font = "Tahoma";
            textStyle.color = 0x000000;
            textStyle.size = 15;
        }

        /**
        * Now we override the function that draws the layout
        * so we can move the image beside the text
        **/
        override protected function drawLayout():void {

            //adjust the icon for any existing padding
            var imagePadding:Number = getStyleValue("imagePadding") as Number;

            //offset the image in the box so it's not touching the top of it
            loader.move(0, 4);

            var w:Number = width-(imagePadding*2);
            var h:Number = height-(imagePadding*2);

            if (loader.width != w && loader.height != h) {
                loader.setSize(w,h);
            }

            //re-draw the image
            loader.drawNow();

            //hide the original cellImage textField so we can display our new one later
            textField.visible = false;

            //display the new text box beside our image
            desc.text = data.label;
            desc.setTextFormat(textStyle);

            //adjust the background
            background.width = width;
            background.height = height;

        }
    }
}

8. That’s it! You can load images from the stage directly into the tile list or you can load images from an external URL. I’ve created a .zip you can download that shows you how to do it along with figuring out which item is selected, changing labels and images, and sorting the list.

Download the Working Code

ML Text Based Game: Fantasy Quest

Comments 2 Standard

Haha I just found this old game I wrote in ML for a programming languages class in college. It takes about 20 minutes to play. Maybe it’ll be useful to someone out there?

Code

/*
  First, text descriptions of all the places in
  the game.
*/
description(valley,
  'You find yourself in a pleasant valley, with a trail ahead.').
description(path,
  'You are on a path, with ravines on both sides.').
description(cliff,
  'You are teetering on the edge of a cliff.').
description(fork,
  'There is a fork in the path.').
description(maze(_),
  'You are in a maze of twisty trails, all alike.').
description(gate,
  'You see a large locked gate before you.').
description(dungeon(0),
  'You wake up with an aching head. Finally you manage to look around. You are in a small dungeon 

room. The walls are slimy and damp.').
description(dungeon(1),
  'The wall appears slimy.').
description(dungeon(2),
  'You see a small window above you, but there is little light coming through.').
description(dungeon(3),
  'The sound of water can be heard.').
description(dungeon(4),
  'The wall is slimy to the touch.').
description(dungeondoor, 'A guard walks by and grins at you with broken teeth.').
description(alley1, 'You find yourself in a rotting, fetid alley.').
description(alley2, 'The smell grows fainter. You see shorter buildings and people ahead').
description(town(0), 'You find yourself in town outside of the alley.').
description(town(1), 'You find yourself on a fairly busy street.').
description(town(2), 'A colorful marketplace looms ahead.').
description(town(3), 'You wander past the marketplace and towards the service district').
description(town(4), 'A weaver tries to get you to buy and other hawkers preach about their wares').
description(town(5), 'The streets grow narrow.').
description(town(6), 'A blacksmith sits before his forge. He asks you if you\'ve seen his missing 

horseshoe and offers a reward if you find it.').
description(town(7), 'You can see the alley in the distance ahead of you.').
description(town(8), 'The marketplace is full of many exotic fruits and vegtables').
description(town(9), 'Past the market place houses line the streets.').
description(town(10), 'Houses grow sparce and delaphidated out here.').
description(town(11), 'Small boys play in sewage.').
description(town(12), 'A drunken man staggers towards you. You see the tavern ahead.').
description(town(13), 'You wander out of town and into the countryside.').
description(tavern, 'You enter the tavern you were in last night. The barkeep look as you oddly.').

/*
  report prints the description of your current
  location.
*/
report :-
  at(you,X),
  description(X,Y),
  write(Y), nl.

/*
  These connect predicates establish the map.
  The meaning of connect(X,Dir,Y) is that if you
  are at X and you move in direction Dir, you
  get to Y.  Recognized directions are
  forward, right, and left.
*/
connect(valley,forward,path). %outside of the town
connect(path,right,cliff).
connect(path,left,cliff).
connect(path,forward,fork).
connect(fork,left,maze(0)).
connect(fork,right,gate).
connect(gate,forward,mountaintop).
connect(gate,left,valley).
connect(gate,right,cliff).
connect(maze(0),left,maze(1)). %the maze
connect(maze(1),right,maze(2)).
connect(maze(2),left,fork).
connect(maze(0),right,maze(3)).
connect(maze(_),_,maze(0)).
connect(dungeon(0),forward,dungeon(1)). %the dungeon
connect(dungeon(0),left,dungeon(1)).
connect(dungeon(1),forward,dungeon(2)).
connect(dungeon(1),left,dungeon(2)).
connect(dungeon(2),left,dungeon(3)).
connect(dungeon(3),right,dungeon(2)).
connect(dungeon(3),forward,dungeon(4)).
connect(dungeon(4),forward,dungeondoor).
connect(dungeon(4),right,dungeon(1)).
connect(dungeon(4),left,dungeon(3)).
connect(dungeondoor,forward,alley(1)).
connect(dungeondoor,right,dungeon(4)).
connect(dungeondoor,left,dungeon(4)).
connect(alley(1),forward,alley(2)). %the alley outside the dungeon
connect(alley(2),forward,town(0)).
connect(town(0),right,town(1)). %the town
connect(town(0),forward,town(7)).
connect(town(1),right,town(2)).
connect(town(2),right,town(8)).
connect(town(2),right,town(3)).
connect(town(8),forward,town(9)).
connect(town(8),right,town(2)).
connect(town(8),left,town(2)).
connect(town(9),right,town(12)).
connect(town(10),left,town(10)).
connect(town(12),forward,tavern).
connect(town(12),right,town(9)).
connect(town(12),left,town(9)).
connect(town(10),forward,town(11)).
connect(town(10),right,town(9)).
connect(town(10),left,town(9)).
connect(town(11),right,town(13)).
connect(town(11),forward,town(13)).
connect(town(11),left,town(10)).
connect(town(13),forward,valley).
connect(town(13),right,town(11)).
connect(town(13),left,town(11)).
connect(town(3),forward,town(4)).
connect(town(4),left,town(5)).
connect(town(5),forward,town(6)).
connect(town(6),right,town(7)).
connect(town(7),forward,town(0)).
connect(tavern,forward,town(12)). %tavern always takes you back to
connect(tavern,right,town(12)).   %town no matter where you turn
connect(tavern,left,town(12)).

/*
  Don't move past the gate if its locked
*/
move(Dir) :-
  at(locked, Loc),
  at(you,Loc),
  at(locked, Loc),
  report.

/*
  move(Dir) moves you in direction Dir, then
  prints the description of your new location.
*/
move(Dir) :-
  at(you,Loc),
  connect(Loc,Dir,Next),
  retract(at(you,Loc)),
  assert(at(you,Next)),
  report.

/*
  But if the argument was not a legal direction,
  print an error message and don't move.
*/
move(_) :-
  write('You can\'t go that way.\n'),
  report.

/*
  Shorthand for moves.
*/
forward :- move(forward).
left :- move(left).
right :- move(right).

/*
  Displays a message if there is an item at this location
*/
item :-
  isat(Item, Loc),
  at(you, Loc),
  write('there is '),
  write(Item),
  write(' on the ground!\n'). 

/*
  But if there is no item in the same place,
  nothing happens.
*/
item.

/*
  Picks up the item at that location
*/
pickup :-
  at(you, Loc), /* you are at this location */
  isat(Item, Loc), /* the item is at this location */
  assert(has(you, Item)), /* you pick up the item */
  retractall(isat(Item, Loc)), /* remove this item from that location */
  write('You picked up the '),
  write(Item),
  write('! \n').

/*
  Or there is nothing there
*/
pickup :-
  write('There is nothing here!\n').

/*
  Drop the item you're carrying
*/
drop :-
  at(you, Loc),
  has(you, Item),
  assert(isat(Item, Loc)),
  retract(has(you, Item)),
  write('You dropped the '),
  write(Item),
  write('.\n').

/*
  Or they don't have an item to drop
*/
drop :-
  write('You are not carrying any items!\n').

/*
  You have a sword and the ogre attacks, you kill it!
*/
ogre :-
  at(ogre,Loc),
  at(you,Loc),
  has(you, sword),
  write('An ogre attacks you! You slice off his head just before he can suck your brains out!\n').

/*
  If you and the ogre are at the same place, and
  you don't have a sword then it
  kills you.
*/
ogre :-
  at(ogre,Loc),
  at(you,Loc),
  write('An ogre attacks you and sucks your brain out through '),
  write('your eye sockets. Your body lies broken on the ground.\n'),
  retract(at(you,Loc)),
  assert(at(you,done)).

/*
  But if you and the ogre are not in the same place,
  nothing happens.
*/
ogre.

/*
  They have a coin and are at the dungeon door
*/
guard :-
  at(you, dungeondoor),
  has(you, coin),
  write('"You there!" you yell at the guard.\n'),
  write('The guard\'s smile fades. "What do you want?" comes his grim reply. \n'),
  write('"I think I\'ve found something!" you say, flashing the coin. "Open the door."\n'),
  write('The guard\'s brows furrowed through the slats in the door window. Finally he grumbled '),
  write('and keys jingled as he toyed with his belt. The door opened with a creak and he pushed'),
  write('his bulk through.\n With one hand you '),
  write('punch the guard in the face, knocking him out and escaping the dungeon. \n'),
  move(forward).

/*
  You approach the guard and don't have a coin
*/
guard :-
  at(you, dungeondoor),
  write('"You\'re going to hang tomorrow pig." The guard says, his spitle hitting you in the eye. 

Slowly he moves off. You wonder if he\'s a bit daft and move off.\n\n'),
  move(left).

/*
  Not at the guard, nothing happens.
*/
guard.

/*
  If you have a horseshoe the blacksmith gives you a sword!
*/
blacksmith :-
  at(you, town(6)),
  has(you, horseshoe),
  write('"You found it!" The black smith exclaims when you show him his lost horseshoe. "Here is 

your reward." He hands you a fine crafted sword.\n'),
  retract(has(you, horseshoe)), % he takes the horseshoe back
  assert(has(you, sword)). %you take your reward
/*
  You don't have the horseshoe, the blacksmith says nothing.
*/
blacksmith.

/*
  You have the coin still, and you walk into the tavern and buy a drink
*/
tavern :-
  at(you, tavern),
  has(you, coin),
  write('"Give me a drink." You tell the bartender, ignoring his weary looks, and handing over the 

coin you found in the dungeon.\n'),
  retract(has(you, coin)). % you give him the coin

/*
  You don't have the coin so you leave without a drink.
*/
tavern.

/*
  They walk through the gate with the key
*/

treasure :-
  at(treasure,Loc),
  at(you,Loc),
  has(you, key),
  write('The key you carry is hit by lightening and you die.\n'),
  write('You were so close!\n'),
  retract(at(you,Loc)),
  assert(at(you,done)).
/*
  If you and the treasure are at the same place and they
  don't have a key then they win.
*/
treasure :-
  at(treasure,Loc),
  at(you,Loc),
  write('You find a beaten old chest. Curious you wander over to open it...'),
  write('Colin\'s decapitated head rolls out at you, his eyes empty and staring.\n'),
  retract(at(you,Loc)),
  assert(at(you,done)).
/*
  But if you and the treasure are not in the same
  place, nothing happens.
*/
treasure.

/*
  If you are at the cliff, you fall off and die.
*/
cliff :-
  at(you,cliff),
  write('You fall off and die.\n'),
  retract(at(you,cliff)),
  assert(at(you,done)).
/*
  But if you are not at the cliff nothing happens.
*/
cliff.

/*
  Have the key with you to open the gate
*/
locked :-
  at(locked,Loc),
  at(you,Loc),
  has(you, key),
  retract(at(locked, Loc)), /* unlock the gate */
  write('You unlocked the gate with your key.\n').
/*
 At the gate but don't have a key
*/
locked :-
  at(locked,Loc),
  at(you,Loc),
  write('The gate is locked!\n').
/*
  Not at the gate, nothing happens
*/
locked.

/*
  Main loop.  Stop if player won or lost.
*/
main :-
  at(you,done),
  write('You wake up screaming in bed! Good thing it was all just a dream!!\n').
/*
  Main loop.  Not done, so get a move from the user
  and make it.  Then run all our special behaviors.
  Then repeat.
*/
main :-
  write('\nNext move -- '),
  read(Move),
  call(Move),
  guard,
  blacksmith,
  tavern,
  item,
  ogre,
  treasure,
  cliff,
  locked,
  main.

/*
  This is the starting point for the game.  We
  assert the initial conditions, print an initial
  report, then start the main loop.
*/
go :-
  retractall(at(_,_)), % clean up from previous runs
  retractall(has(_,_)), % remove all items you had before
  retractall(isat(_,_)), % remove empty locations of old items
  assert(at(you,dungeon(0))),
  assert(at(ogre,maze(3))),
  assert(at(treasure,mountaintop)),
  assert(at(locked, gate)),
  assert(at(lockeddoor, dungeondoor)),
  assert(isat(key, path)),
  assert(isat(coin, dungeon(3))),
  assert(isat(horseshoe, town(1))),
  write('\n\n Your name is James Pattern. Last night your friend Colin asked you to the Inn for a 

drink. He talked excitedly of treasure on a mountain top and ogres out to get him. You laugh at him 

good naturedly and think he had a bit too much to drink.\n On your way home later that night you 

hear the scuffling of feet. You spin but see nothing in the dark alley behind you. You continue on 

until something sharp hits you over the head.... You wake up with an aching head and a groan. 

Finally you manage to look around.\n\n'),
  write('WELCOME TO FANTASY QUEST!!!'),
  write('\n\n'),
  write('Legal moves are left, right, forward, pickup, and drop.\n'),
  write('End each move with a period.\n\n'),
  report,
  main.

Explanation

The main loop of this program is located at the very bottom of the script. It starts out by removing all of the locations, item locations, and items the player had on their character before they started playing. Once that has been done it sets up the game by placing all the items and obstacles in the appropriate places. After the game is setup its ready for the user to begin playing. It introduces them to the game by writing text to the screen to detail where the player is.

Legal Moves

Movement: Forward, Left, Right – This moves the character on the game map. To do this, the program first calls the move(Dir) and then checks the game map to see if there are any connections between the player’s current position and a positing direction they are trying to move. If there is a position available it retracts the players old location and asserts their new location to the new position on the map. If a player has entered a movement that is not connected to another part of the map then the game notifies them that they cannot move that direction.

Pickup – This move allows players to pick up items they will encounter as they move through the game map. A player can pick up as many items as they like. Once a player has picked up an item it will remain with them as they navigate the map until they decide to drop it. The pickup code first checks to see if there is an item at the same location the character is located. If there is, the game retracts the item from its location and asserts that the player now has that item in their possession. If the player tries call pickup and there is no item at that location it gives them an error message.

Drop – This allows the players to drop items they have picked up in the game. A player can drop as many items as they have. Once they don’t have any more items it will notify them. However, a player cannot specify which item they mean to pickup or drop. In order to drop an item, the code first checks to see if they have any items. If they have an item it retracts the item as being in their possession and then asserts that the item is now available at the location where it has been dropped. This way if they character was to return to that location at a later time they could again pick up the item.

Item Notification

In order for a player to notice that there are items around the map an item call was put into the code. This checks to see if there are any items at that particular location and then lists any items that it finds. This way the player is notified of the item being available for them to pickup as they play.

Gameplay

You were at the tavern having drinks with a friend. He tells you that he was trying to find treasure but was chased away by an ogre. You have a few drinks with him and then laugh it off and leave. As you’re leaving someone hits you over the head.

Dungeon & Coin – You wake up in a dungeon that is patrolled by a guard. In order to escape from the dungeon you must first find a coin in your cell. Once you have the coin you can go up to the door of the cell. You tell the guard you found something great and flash the coin to catch his interest. He, being a dull witted fellow, falls for it and opens the door. You knock him out and are free.

Blacksmith & Horseshoe – Beyond the dungeon you find yourself in an alley. Outside of the alley you wander back into town. Along the way you stumble upon an expensive looking horseshoe and decide (or not) to pick it up. As you continue around town you’ll find a blacksmith whose looking for a horseshoe he lost and is offering a great reward for it. If you have the horseshoe the blacksmith gives you your reward: a sword. The horseshoe is retracted from your possession and a sword is added to them.

Tavern & Coin – As you continue through town you may eventually wander back into the tavern you met your friend at the night before. If you happen to still have a coin you will buy yourself a drink, otherwise you’ll leave dejectedly.

Gate & Key – As you continue out of town you’ll find yourself in a valley along a path. On the path you will find a key and decide (or not) to pick it up. You will need this key in order to unlock a gate that lies at the base of a mountaintop. Without this key you cannot pass through the gate. However, once the gate is unlocked all is not clear. You must first drop the key before passing through otherwise you’ll be struck by lightning.

Ogre & Sword – Outside of the town you may find yourself stuck in an endless maze. Somewhere hidden in that maze lies an evil ogre waiting to suck your brains out. If you happen to have a sword with you, all is fair and well as you cut off its head before it can touch you. If you weren’t so lucky as to help the blacksmith out you will find yourself dead and buried.

Cliffside – There are other treacherous obstacles outside of the town. If you don’t watch your step you can fall down the cliff and die!

Treasure – Beyond the gate, and the treacherous lightning attracting key you will find the treasure your friend only dreamed about.

Game Over – That’s it! I hope you’ll play!