We’ll add the code to wrap the screen to KeyMover's "moveClip" function.
First, however, go back to the fla file and make sure that the registration point of the ball MovieClip is in the upper left hand corner, as our programming statements in the class are going to assume that. If it's not, double-click the MovieClip in the library to edit it. All of the contained graphics should be selected automatically, but if not, make sure you select them all. Then, in the align panel (press CRTL-K for the panel if it's not already around), make sure the "to stage" button is selected. In the first row of buttons, click the align left and align top buttons. Done! Go back to scene 1, and we'll leave the fla file for now.
Now, back to the moveClip function in our KeyMover class. Let’s take on the right arrow key first. The logic goes like this: If the user is pressing the right arrow key, and if the _clip’s x property exceeds the width of the screen, change the _clip’s x property to the left side of the screen (which would be 0), minus the width of the _clip. The width of the screen is contained in stage.stageWidth. As before, we’ll use the _clip’s stage property to get a reference to the stage:
if (rightArrow) { _clip.x += speed; if (_clip.x > _clip.stage.stageWidth) { _clip.x = -(_clip.width); } }
Save the class, go back to the fla and test the movie. You’ll get screen wrapping when you hold down the right arrow key. Pretty cool, eh? The coding for all the other arrow keys follow similar logic. Here's the entire KeyMover class, inlcuding the revised moveClip function, which now provides screen wrapping in all four directions:
package {
import flash.events.KeyboardEvent; import flash.ui.Keyboard; import flash.events.Event; public class KeyMover { private var _clip:MovieClip; private var rightArrow:Boolean; private var leftArrow:Boolean; private var upArrow:Boolean; private var downArrow:Boolean; private var speed:uint = 10; public function KeyMover(clip:MovieClip) { _clip = clip; _clip.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); _clip.stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased); _clip.stage.addEventListener(Event.ENTER_FRAME, moveClip); } private function keyPressed(event:KeyboardEvent) { if (event.keyCode == Keyboard.RIGHT) { rightArrow = true; } if (event.keyCode == Keyboard.LEFT) { leftArrow = true; } if (event.keyCode == Keyboard.UP) { upArrow = true; } if (event.keyCode == Keyboard.DOWN) { downArrow = true; } } private function keyReleased(event:KeyboardEvent) { if (event.keyCode == Keyboard.RIGHT) { rightArrow = false; } if (event.keyCode == Keyboard.LEFT) { leftArrow = false; } if (event.keyCode == Keyboard.UP) { upArrow = false; } if (event.keyCode == Keyboard.DOWN) { downArrow = false; } } private function moveClip(event:Event) { if (rightArrow) { _clip.x += speed; if (_clip.x > _clip.stage.stageWidth) { _clip.x = -(_clip.width); } } if (leftArrow) { _clip.x -= speed; if (_clip.x < -(_clip.width)) { _clip.x = _clip.stage.stageWidth; } } if (upArrow) { _clip.y -= speed; if (_clip.y < -(_clip.height)) { _clip.y = _clip.stage.stageHeight; } } if (downArrow) { _clip.y += speed; if (_clip.y > _clip.stage.stageHeight) { _clip.y = -(_clip.height); } } } } }
That concludes the KeyMover class. There are, of course, other refinements that could be made. For example, I usually prefer to use the Timer class instead of the ENTER_FRAME event to provide continuous action, as you can create motion that’s smoother and way less dependent on the movie’s frame rate, especially if you also use the TimerEvent class's updateAfterEvent() method. But I wanted to keep this tutorial fairly simple and basic, and if you want to, you can go on to create that. Or, hit me up for the class file, and I’d be glad to share it with you.
If you’ve made it this far in the tutorial, and you’ve actually created the two useful classes outlined above (TestClass doesn't count, haha!), here’s a little side benefit for you:. In your fla file that you used for KeyMover, let’s make the ball a member of both of the classes we’ve made. Change the code in the first frame of the fla to this:
import com.mysite.keyboard.KeyMover; import com.mysite.mouse.ClipDragger; var keyMover:KeyMover = new KeyMover(ball); var clipDragger:ClipDragger = new ClipDragger(ball);
Test the movie. You’ll find that now the ball movie clip is being controlled by both classes! You can click and drag the MovieClip, and you can also move it around with the arrow keys. How cool is that? The MovieClip is totally separate from the code that controls it, and it’s being controlled by two separate blocks of code simultaneously!
I hope you’ve enjoyed this tutorial, and I hope I’ve helped spark your imagination as to the potential of using classes in your programming. Because this is truly just the tip of the iceberg! Happy coding!
Brilliant!
Brilliant tutorial! Just what I've been searching high and low for!
You've really got a talent, Jody, for laying this stuff out in a clear, concise manner, with no glaring omissions of the little details that can serve as dead ends to those just getting acquainted with AS3.
Well done. Will you please see if you can get a job writing tutorials for Adobe? Your services are _sorely_ needed! ; )
thanks a lot making thing so
thanks a lot making thing so simple.
Awesome Tut
I like the way you "over-write" your explanations because everyone else skips all sorts of important little details. I found a few missing as I went through your lessons here but could only find this one when I went back through. I would have taken notes but wasn't sure if you'd be cool about the heads-up. After spending the last couple of days going through your lessons, I can tell that you will be appreciative if I point out any changes you can make to improve the lessons.
In this lesson...5. Second useful class: KeyMover find...
The functions referred to, “keyPressed” and “keyReleased” don’t exist yet, and we’ll write them next. But first, since we used the KeyboardEvent class in the above, that class will need to be imported. So add the following line just below the line that imports MovieClip:
the line is missing
I also noticed that the "package" line, line 1 is missing toward the end of this lesson. For those who have been jumping around, trying to apply your lessons to some other code, it's easy to get lost on the steps, so like me, they may do a fair bit of cutting and pasting as they follow along. I generally try to add the code changes as they happen to get the effect on the app registered in my head, then I grab the whole code when you assemble it all to make sure I didn't leave something out. In this case it didn't work right because the package line was missing. Naturally, that was easy to remedy as Flash throws the error in the compiler error window. Still, I thought you would like to know.
See, I'm as wordy as you are!
Keep it up. Thorough instruction is the best instruction. I have learned everything I do using computers from tutorials and I am constantly impressed with the time and energy people like yourself devote to helping others to learn. Your full explanations bring a clarity to the process that many others lack.
I have several more of your lessons to go and plan to donate when I have worked my way through all of them.
At that time, I will have some other questions for you which I hope you will be willing to answer for me.
Again, I can't thank you enough for filling in the gaps in my understanding of Action Script, particularly as it relates to the event flow and class structure!
Barry McMahon
Artist - CoFounder - www.SymTell.com
Thanks for the corrections!
Hey Barry, Thanks for the nice comments! You are indeed correct, I am more than okay with that kind of "heads up." In this case, the tutorial was originally written on actionscript.org. When I started this present site, I had already written a few tutorials on the actionscript.org site. My idea was to start a site of my own, and rather than starting out with no content at all, I would reproduce the tutorials I wrote on that other site, and at the same time I would be making sure that I also retained a copy of my work, as I had no other copies.
This was one of the first few that I copied over from that other site. It was kind of a painstaking process, too. So, the errors you caught are probably a result of the copying and pasting job I did. I try to proofread everything thoroughly, but it's hard to achieve error-free materials. I've just now fixed the things you mentioned.
When I'm writing a tutorial, if I even change my mind about a variable name half way through (something I do all the time when programming) it can wreak havoc.
--Jody
You're Welcome I Know Your Pain
I have work ranging from paintings to flash animations to websites, murals, CDs, blogs, apps and books. I do my best to move various important bits from one place to another properly, yet things have a way of getting lost in translation. I wrote a childrens book where the text originated in word, then I migrated it over to Quark. The word through became trough. I did one proofread, then another, then another, yeah, you get it, even had others proof it. Never found the problem until after it was printed. I couldn't afford to reprint (self-published).
I plan to rerelease that book after your awesome tutorials make a star programmer out of me. Guess that means my grandchildren will be reading it to their grandchildren. Actually, I understand your stuff so far, I'm just trying to do things that are a step beyond. To get there, I really need to know this stuff. Thanks for your help!
Barry McMahon
Artist - CoFounder - www.SymTell.com
Your style vs extending MovieClip
Hi,
Thanks for the well written tutorial. Was worth a donation.
I have a question about style. I have programming experience but not any OOP experience. I am working on a project and trying to break it into appropriate packages. I have a Main class that will call various layout classes which will create arrays of objects.
In other sites (Adobe's VideoGallery example - http://www.adobe.com/devnet/flash/articles/video_gallery.html) they extend MovieClip to create their classes. In your classes you don't extend MovieClip and you pass in a reference (clip:MovieClip). What I see is nice about that is that you have an explicit pointer (?) to the clip being worked on (in the form of _clip). With the other examples I see extending MovieClip I am having a hard time seeing how to add event listeners to the class because they have issues about whether the instance is on stage when the listener is added - some use an init function in the constructor after an addEventListener(Event.ADDED_TO_STAGE, init) call.
Can you speak to what the advantages of extending versus not extending? Its the kind of info I don't see talked about in the books or sites.
- Thanks, Karl
Karl, I really appreciate
Karl, I really appreciate your comment and, of course, your donation!
I wrote this tutorial early on (it was my first one), when I was just beginning to understand Classes, Packages, the Classpath, and OOP myself (especially as to how they work with Flash). It was really starting to come together for me, and I wanted to show others the things I was learning. I wrote it for a tutorial contest that actionscript.org was having, at the end of 2007, and I won the contest! Anyway, what I did was to make a MovieClip instance a property of a class by passing it in to the constructor. I did this for several reasons, but most of all because at the time AS3 was new, and all these people were coming to it from AS2 but not necessarily understanding classes. I wanted to start them with what they already knew, which would be creating stage instances and controlling them with timeline code, to working with stage instances and controlling them with a class instead. It seemed like a natural progression and a good introduction to the concept of a class.
I did get some feedback saying why didn't I just extend the MovieClip class instead. But what I was doing was valid, too. If you extend the MovieClip class, you are using inheritance, and if you create a class that has a MovieClip instance as a property, you are using composition. In the first case, the class IS A MovieClip, and in the second case, the class HAS A MovieClip. I still think the two techniques are equally valid, and you just have to decide which one is best for the job you want to put it to.
Keep reading. My "Better Navigation using Flash AS3 Classes" uses inheritance to make MovieClip "screens." But my scrollbar tutorial uses composition to create the scrollbar. The class itself isn't even a display object! You just create and pass in all the parts as parameters, and the class makes them behave like a scrollbar (composition). Generally composition is better, because it's easier to re-use something that doesn't depend on any particular library symbol in Flash. When you want to re-use a class that was linked to a library symbol, you have to also hunt down the library symbol in some fla file somewhere (now where did I put that??). Or at least make sure that any other symbol you substitute has stage instances with the same instance names as the original. Of course, linking to library symbols is kind of a Flash thing, and is not the only kind of inheritance in AS3, not by a long shot.
Ultimately, you just have to decide what is best for the application you are writing, and whether you intend to re-use the class or not. Also, that's not to say that inheritance will never give you a reusable class, either. Anyway, I still do a lot of thinking myself about the best ways to do things. I have found a few things so far that seem to work for me. I'm always still learning too, and I'll do my best to keep sharing it back as I am able. Hope that helps.
Jody