View Full Version: Actionscript 3

lassie >>Discussions >>Actionscript 3


<< Prev | Next >>

bigmac- 03-27-2008

Lookin' good Chris... This is a pretty solid little code snippit. You're figuring this stuff out! So, your problem is the fact that the Timer does not have a qualified event handler... You know how when you set up mouse event handler methods they need to receive a MouseEvent parameter in order to work? Well, it's the same thing here. Any time that you add an event listener (to anything), the listener method MUST receive an Event as its sole parameter. Here's the simple breakdown: var dsp:EventDispatcher = new EventDispatcher(); dsp.addEventListener(Event.SOME_EVENT, this.handleEvent); function handleEvent(evt:Event):void { // do something } So there's two solutions here, one better than the other. First, the bad one. You COULD do this: //Define the photo's properties function createPhoto(evt:TimerEvent) { // do stuff } //Create the photo every second var tickerTimer:Timer = new Timer(1000); tickerTimer.addEventListener(TimerEvent.TIMER, createPhoto); tickerTimer.start(); That will technically work now that you've made the event handler receive the event. However, now you've turned your createPhoto() method into an event handler. It now requires an event input in order to work. So, that's very limiting should other things want to call this method other than just your timer object. Technically, you could call it using createPhoto(null), but that's just sloppy. So, the better solution is to isolate the jobs of your methods. createPhoto has a job (to create photos), now let's add another method who's job it is to receive the timer event and call the createPhoto method. So, this is a good configuration: //Define the photo's properties function createPhoto() { // do stuff } //Create the photo every second var tickerTimer:Timer = new Timer(1000); tickerTimer.addEventListener(TimerEvent.TIMER, this.onPhotoTimer); tickerTimer.start(); // timer cycle event handler function onPhotoTimer(evt:TimerEvent):void { createPhoto(); } While this creates more code, it's actually a lot more organized an flexible. It'll also be more robust as your application grows.

fatbuoy1- 03-27-2008

Ah gotcha, that makes sense thanks :) I notice you and flash help both use this.someVariable, whats the 'this.' for? So far I havnt used it and it hasnt made a difference that I have noticed. Also, is there a better way of getting a random angle between x and y? My way seems a little sloppy... var photoRotate:Number = -10+(20*Math.random());

fatbuoy1- 03-27-2008

Also, at the moment the rectangles are rotating using the top right hand corner as a pivot... how would I get them to rotate on their own centres? Where im going with this is that ultimately I'm planning on having a website that looks like its a stack of polaroids... clicking on a link to say the 'gallery' section will add another rectangle to the pile, which contains the 'gallery' page .swf in a loader. Hard to describe but I think it could turn out nice.

bigmac- 03-28-2008

Hey Chris... Well, the "this." reference is a matter of style. "this" references the current object (or scope) that the script is running within. So, lets used setting an object's position as an example... if you're running a script on root that targets a movieClip on root, then you must specify: mc.x = 100; mc.y = 150; However, lets say that you write a script that runs inside of (or within the scope of) that movieClip. Since that clip is the script's target, a reference to "this" would target that script. So, within the scope of that movieClip you could use: this.x = 100; this.y = 150; Some people are die-hard about that. They put "this" on every single thing that references a property of the current object. Personally, I think that's a little excessive, since un-targeted properties are automatically targeted to the current object (this). So, the following within that movieClip would work exactly the same as the code above with the "this" references... x = 100; y = 150; So, I generally do not bother including "this" references. I personally think they're a bit excessive, though I understand the die-hard code gurus who say that you should never have targeted properties. So, that's a matter of ethics. However, I do think it's a good idea to specify "this.handleEvent" when defining event listeners. An even listener defines not only the method to call, but the scope to call it within. So, while you can define an event listener without "this.", I just like the reaffirmation of the scope in which the even will fire off.

bigmac- 03-28-2008

Also, is there a better way of getting a random angle between x and y? My way seems a little sloppy... var photoRotate:Number = -10+(20*Math.random()); Nope, you hit this one on the head. That is the exact mathematical process for generating a range between two numbers; and there's nothing sloppy about it!

bigmac- 03-28-2008

Also, at the moment the rectangles are rotating using the top right hand corner as a pivot... how would I get them to rotate on their own centres? Where im going with this is that ultimately I'm planning on having a website that looks like its a stack of polaroids... Yep, I figured that this was leading up to a polaroid stack. :) Cool, cool. So, first change that you're going to need to make is to make these photo objects utilize the Sprite (or MovieClip) class, not the Shape class. I've actually never used the Shape class before, and kind of forgot that it existed until I saw your example. A Shape is basically just a vector drawing object built upon the flash Graphics class. A shape really can't do anything besides get drawn in.. it cannot have mouse actions, and cannot have children added. A Sprite is where it's at. I use a sprite for about 99% of everything that I build. It has the full gammut of Flash interactive capabilities and does not have the needless overhead of a Flash timeline (which I only use once in a blue moon). So, make your photos Sprites, not Shapes. Conveniently, you can still run all the drawing operations on a Sprite by calling upon it's graphics node (ie: "targetSprite.graphics.beginFill(0x000000, 1);"). As for rotating around the center, you should just draw content content so that it is centered around the sprite's registration point. For example: sp.graphics.beginFill(0x000000, 1); sp.graphics.drawRect(-200, -200, 400, 400); sp.graphics.endFill();

fatbuoy1- 03-31-2008

Ok... so iv got my shapes appearing, now im trying to load the pictures in. Remember you said something about using XML and gave me an example of the XML file (with the data split up into nodes for image url, title, caption, etc)? How would I go about loading the data from an XML file in?

bigmac- 03-31-2008

crap. In layman's terms I'm not entirely sure. I've got an arsenal of standardized class architectures put together that I process XML with. So, I really can't remember how to do a basic load operation off the top of my head. :P Looking now... oh... is that all? It's a simple URLLoader? Cool, well that's easy enough. So, just set up a URLLoader to acquire the data, then plug it into an XML object. I'll copy some of the key points here from my standard base class. var xml:XML; var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, this.onXMLLoad); loader.load(new URLRequest("myfile.xml")); function onXMLLoad(evt:Event):void { xml = new XML(evt.target.data); xml.ignoreWhitespace = true; } So, while I can't guarantee that simplification will work, it looks like it should. Once you have the XML data in, you'll probably want to parse it, which is slightly trickier. Tell you what, devise and post your XML schema, then we can discuss data accessors through E4X parsing.

fatbuoy1- 03-31-2008

By XML schema do you mean this? <?xml version="1.0" encoding="UTF-8"?> <portfolio> <image> <url>images/image2.jpg</url> <title>My Awesome Image</title> <caption>Caption about image</caption> </image> <image> <url>images/image2.jpg</url> <title>Another Awesome Image</title> <caption>Caption about other image</caption> </image> </portfolio>

bigmac- 03-31-2008

that's the stuff

fatbuoy1- 03-31-2008

Well i guess im all ready to discuss data accessors through E4X parsing then! :D

bigmac- 03-31-2008

Okay, okay... so much for running out of here quickly :P We'll modify your schema just a little bit for example purposes... <?xml version="1.0" encoding="UTF-8"?> <portfolio> <image url="images/image2.jpg"> <title>My Awesome Image</title> <caption>Caption about image</caption> </image> <image url="images/image2.jpg"> <title>Another Awesome Image</title> <caption>Caption about other image</caption> </image> </portfolio> Check it out, so I've made the URL an attribute of the image node for demonstration purposes. There are some things that attributes are really handy for. You can also create childless nodes that use only attributes, like this: <?xml version="1.0" encoding="UTF-8"?> <portfolio> <image url="image1" title="blah" caption="blah" /> <image url="image2" title="blah" caption="blah" /> </portfolio> Which one is better? It depends... node attributes and child nodes each have pros and cons which we can get into later. In your case, I'd stick to using all child nodes the way you have in your above example; though it's important to be aware of both data models. So, for getting XML data, remember the accessors: child nodes: use dot notation (xml.child.secondChild). attributes use the @ sign (xml.child.@attribute). Now, to be entirely honest I never bother futsing with XML in raw format. I just parse it into a native Flash format so that you don't have to mess with multiple data models. In your case, you have an array of images. Each element is an object with three properties (url, title, caption). So, I'd do this: var xmlData = yourRawXML; var slideshowData:Array = new Array(); // specify a node name to read as a list var imageList:XMLList = xmlData.image; // Iterate through the list of image nodes for each (var imageNode:XML in imageList) { // extract each node's data var u:String = imageNode.@url; var t:String = imageNode.title; var c:String = imageNode.caption; // Add data elements as a new Flash object in array slideshowData.push({url:u, title:t, caption:c}); } The result will give you the XML structure as flash native data that you can read and access with standard Flash data accessors. You could, of course, also run your slideshow off the unparsed XML data as well. I just think its easier to work with Flash data, and it allows your data to be more generally accessible to all things within your application.

fatbuoy1- 04-01-2008

Hmmm... ok I think that makes sense, thanks :) For some reason it doesn't seem to be working, possibly because of the way I'm loading the XML file itself? //Load the XML file var uldr = new URLLoader(); uldr.addEventListener(Event.COMPLETE, xmlCompleteHandler); uldr.load(new URLRequest("examples.xml")); If not, then I musn't have implimented your example code correctly? function xmlCompleteHandler(evt:Event) { //Load list of example images var xmlData = uldr; var examplesData:Array = new Array(); // specify a node name to read as a list var imageList:XMLList = xmlData.portfolio.image; // Iterate through the list of image nodes for each (var imageNode:XML in imageList) { // extract each node's data var u:String = imageNode.url; var t:String = imageNode.title; var c:String = imageNode.caption; // Add data elements as a new Flash object in array examplesData.push({url:u, title:t, caption:c}); } } however, all I really changed was the properties of imageList, from xmlData.image to xmlData.portfolio.image... it doesnt work either way though!

bigmac- 04-01-2008

Hehe, well first let it be known that I haven't -*test*-('")ed any of these code snippits that I've been posting... I've just been compiling lots of little pieces out of my code library to create these simple examples; so I can't guarantee that my examples are bug free. However, they're complete enough that you should be able to debug with some help from Flash Documentation. Also, just read the compiler errors. AS3 errors are extremely specific and will tell you everything you need to know. They seem greek at first, which is all the more reason to pay attention to them. Once you understand what they all mean, you can start trapping error conditions based on error type. If nothing else, post your errors here so we can talk about what they mean. Either way, I do see one glaring error in your code... You are referencing your URLLoader in place of valid XML data, which isn't going to work. Review my earlier example... you've got to retrieve the data loaded by the URLLoader then plug it into an XML object before you can parse it. Like this... function xmlCompleteHandler(evt:Event) { // create XML data object from data retrieved by URLLoader var xmlData = new XML(evt.target.data); }

fatbuoy1- 04-01-2008

Ah yeah, that seems to have done the trick, no error messages, thanks! I won't pretend I really understand whats going on here though, lots of variables and lists and stuff... but should that now load the info contained in the two xml nodes into the examplesData array? How do I pull the data out and make it visible then... do I have to know the index of the node i'm aiming for or have they been named?

Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.