Thursday, July 23, 2009

Reclaiming my zeal!

I've found an awesome AS3 tutorial! It's on Michael James William's blog and it's all about creating your own 'Avoider' game using Action Script 3... speaking of AS3 - holy cow it's different from AS2, this isn't some minor revision! It's like learning a whole new language. Kinda reminds me of when I was learning C++ because it's more OOP.
Anyways, Mike's (can I call you Mike?) tutorial - which is using FrozenHaddock's Avoider Game tutorial and upgrading it to AS3 - is a great resource for learning AS3, and if you're just starting to play with Flash that's where you want to begin. So go there, check it out! Participate in the comments if you have a problem... I know I will be :)

Included with the later 'chapters' of his tutorial are some 'challenges' - I love this part! The purpose of his tutorial isn't just to walk you through doing everything. Like a good teacher, he sets out some goals for you to try to accomplish on your own, and then provides support if (WHEN) you need it by means of the comments section.

If you haven't gone through the tutorial yet, go do it! I'm going to post what I did on some of the challenges here.

Chapter 7 Challenges
One of the challenges is creating a second button on the menu screen, so that one would start the game with mouse control and the other with keyboard control. I mulled over this for three days!

My first step was to duplicate the startButton in AvoiderGame.fla, I named the instance of the copy - kbStartButton. I also edited the button so that when I hovered my mouse over it it said "Keyboard" and the original startButton says "Mouse"

My next steps were in creating an event listener for my 'keyboard control' button (I named the instance kbStartButton (Line 4 in the code below)

  1. public function MenuScreen()

  2. {

  3.     startButton.addEventListener( MouseEvent.CLICK, onClickMouse );

  4.     kbStartButton.addEventListener( MouseEvent.CLICK, onClickKeyboard );


  6. }

You notice, I also changed onClickStart to onClickMouse.
And also in the function...
  1. public function onClickMouse( event:MouseEvent ):void

  2. {

  3.     dispatchEvent( new NavigationEvent( NavigationEvent.MOUSE ) );

  4. }

Plus a new function that we referenced in the event listener (onClickKeyboard)

  1. public function onClickKeyboard( event:MouseEvent ):void

  2. {

  3.     dispatchEvent( new NavigationEvent( NavigationEvent.KEYBOARD ) );

  4. }

We referenced a .MOUSE and a .KEYBOARD navigation event, so go to our file and add:

  1. public static const RESTART:String = "restart";

  2. public static const START:String = "start";

  3. public static const MENU:String = "menu";

  4. public static const KEYBOARD:String = "keyboard";

  5. public static const MOUSE:String = "mouse";

Now, going back to the file, change your constructor to:

  1. public function DocumentClass()

  2. {

  3.     menuScreen = new MenuScreen();

  4.     menuScreen.addEventListener( NavigationEvent.KEYBOARD, onRequestStart );

  5.     menuScreen.addEventListener( NavigationEvent.MOUSE, onRequestStart );

  6.     menuScreen.x = 0;

  7.     menuScreen.y = 0;

  8.     addChild( menuScreen );

  9. }

Go down to the onRequestStart function, and add this to the top:

  1. if(navigationEvent.type == "keyboard")

  2. {

  3.     useMouseControl = false;

  4. }

  5. if(navigationEvent.type == "mouse")

  6. {

  7.     useMouseControl = true;

  8. }

Now, go to - don't worry, we'll be back here in a minute!

Create a variable for choosing the mouse, I called it iChooseMouse

  1. public var iChooseMouse:Boolean;

and change the constructor for AvoiderGame to accept this new variable. While you're at it, add a line that makes useMouseControl equal to iChooseMouse.

  1. public function AvoiderGame( iChooseMouse )

  2. {

  3.     useMouseControl = iChooseMouse;

  4. ...

Now, stroll back to and change every instance of

  1. playScreen = new AvoiderGame();


  1. playScreen = new AvoiderGame( useMouseControl );

Save all your .AS files and give it a test run. Should work!


  1. Awesome! Thanks for the link :)

    I hardly ever get to see someone actually working through a challenge, or any part of the tutorial, so this was really interesting for me.

    Congrats on getting it working. What's next? :P

  2. Replies
    1. Well... haven't gotten back to AS3 like I had hoped... :( Later... yeah, later...

    2. I know what you mean. I want to thank you for the in-game mute toggle key guide through, I had gotten through about 80% of the challenge but was having trouble with the final tidbits. I must admit I'm surprised I received an answer to my post as Michael Williams' tutorial is rather old, as is this blog.

    3. Glad to have been able to help in a little way! Yeah... can't believe it's been three years since I did his tutorial. Time flies... Seems like every time I get around to working on Flash again I go back through his tutorial from the beginning and learn something I didn't get the last time. You'll have to let me know when you post your game so I can check it out.

    4. Will do, I got the base for my game complete now for the...special effects :)

    5. Alright, so...interested in getting back into Flash again? :) I am using a long song (about 4 minutes) as my background music for the game and the song has a long intro I was attempting to figure out a way to set it up so that when the player restarts the game it resumes at the spot in the song when they died. I put musicPosition = Math.floor(bgmSOundChannel.position) into the if avatarHasBeenHit boolean in my main game class file, but I have been unable to figure out what to put in my document class under the restartGame function that will connect them...

    6. Hmm... I'm so ashamed! I used to know EventListeners like the back of my hand! :) I can't seem to remember how to do that. Yeah, I am interested... I'll boot up my other computer and try to see if I can figure it out.

    7. Had a good fourth? Or is northern cal restrictive about fireworks... Anyways I haven't been able to work on my game for 2 days and I start work this weekend but I WILL be working on it with any and all opportunities I have. The game is coming along very nicely though nevertheless, currently working on multiple enemy forms, different spawn rates for each form, and hit points for both the avatar and enemies. Honestly though I fear my game will end up having the same dynamics as a game I recently played on Kongregate, Viricide. Oh well.

    8. I had a good day off - got to spend extra time with my boy. Thankfully he slept thru the explosions! :) Out of a want to remain politically neutral I don't celebrate Independence Day, even though I definitely appreciate the freedoms we have, and respect those who have had to put their lives on the line so I'd have them.
      I'm really wanting to get back to Flash again after all this... I just wish I would actually *finish* a game. :p I think I keep setting the bar too high when I first start! I kept trying to jump into making a platform game, and then I read articles on optimizing a platformer before I even create one in the first place, and it all gets so overwhelming I eventually give up. Happens every time.
      Starting work? Aurgh... the killer of all free time :) I don't have much time this weekend either.

    9. Haha I think I know what you mean about not finishing, I have been keeping a list of errors I need to fix and suggestions for content to add but I as I go through the list I keep getting distracted by other features I can add and the list gets longer rather than shorter. Also sometimes after running out of ways to write code on my own, finding new useful code that I can apply takes awhile. Problem is for me that since I'm new to flash I spend way too much time exploring and finding out new things as opposed to actually organizing my time and editing my game. Still, I find myself continually returning to Michael's tutorials to play around with his code and modify it to benefit my game. Like for example his adding lives to your avatar, I am going to use that to give my enemies hit points. On the subject of his tutorials, a main problem I have been coming across is that for some reason or another his website does not exist and so a lot of his material that he links you to which is made by other people, I can't find :/ For adding different enemy forms I may end up adding a class for each form and having a lot of needless extra coding whereas if his website links worked I'm sure there is a better way :P. Haha well, I guess if it gets the job done it doesn't matter how you got there :)

    10. Yeah, I let the domain expire (oops), and then I apparently corrupted the data when trying to copy the posts over to my blog (double-oops). That was not a good day.

    11. Ouch, that's a shame :( Heh...glad to see you around :) I'll stop trying to bug you on twitter ;) So is there a good place to share my code so if you two have some spare time you could view it and troubleshoot some bugs/glitches with me? I can do most of the code writing on my own using what I learn from outside sources but there will always be a few concepts I can use but don't understand and as a result won't be able to fix if errors pop up.

    12. It's good to get the band together again, even if for just a short time and a few comments :D

  3. @DJD That's kewl though, at least you have a list of things to fix - good idea!
    @MJW Hey Michael! Glad you could join the blog post resurrection party! I'd have to agree... I hate those days, and the feeling in your gut that comes along with them.
    @DJD I don't know where the best place to share the code from would be, you could zip it and email it to me, or if you have a website you could upload it there. However you do it, I'll be interested to take a look.

    1. This comment has been removed by the author.

    2. This comment has been removed by the author.

  4. I don't suppose someone could upload a tutorial somewhere on traer physics...

  5. So, Michael... I have enemies spawning from all directions on all levels, but for the first level I only want var newDownMovingEnemy:Enemy = new Enemy( randomX1, -15 ); So to do this I used if ( currentLevelData.backgroundImage == "lvl1" ) and removeChild'ed all other enemies (i.e. rightmoving, leftmoving, etc.) but this generates a ton of ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. ...any idea why? :/

  6. Cleaning out my inbox, came across this... sorry for missing it!

    1. Haha all good, I have improved it quite a bit beyond that point in its history.