Wednesday, July 29, 2009

MJW Avoider Game ep8ch1



...That'd be episode 8, challenge 1

So now that he's shown us the magic of adding sound, he wants us to figure out how to create a Mute button on our own... sheesh. :) This was the easiest challenge, so far. But, so that I can solidify this in my own head, and in case you need help, here goes my thought process:

The first step I wanted to complete, had nothing (directly) to do with sound. I wanted Flash to recognize another button was being pressed. Instead of being original, I picked "m" as my mute button... Feel free to pick L, meaning "Let the music stop", or ß (ALT+0223) for "This music was picked for the beta. If you don't like it you can turn it off."

Going back and referencing my old code, I made these additions:

All of them are in the AvoiderGame.as file.

Create a publicly accessible variable (outside contructor)...
  1. public var mKeyIsBeingPressed:Boolean;)



Initialize it in the contructor...
  1. mKeyIsBeingPressed = false;



Inside the onKeyPress function
  1. if( keyboardEvent.keyCode == 77 )

  2. {

  3.     mKeyIsBeingPressed = true;

  4. }



Michael let you figure out the onKeyRelease function, and a student is not above his teacher, so I'll let you figure that out too.... :P

Then in the onTick function, I used a trace() command as a placeholder
  1. if( mKeyIsBeingPressed )

  2. {

  3.     trace( "You're pressing M!!!" );

  4. }



Don't forget to "Disable Keyboard Shortcuts"

...and then watch your Output window. When you press m, it should fill up with "You're pressing M!!!" over and over...



Ok, so it's working, I have a stream of useless output to prove it. Now I want it to actually do something useful! I created some new global variables:
  1. public var musicPosition:int;

  2. public var musicIsMuted:Boolean;


musicPosition is an integer. It's going to be equal to where the music was muted, so that when it's unmuted it'll play from the same spot. I guess that makes it a pause button... so, sue me.
musicIsMuted is straight forward. It's a true/false value of whether the music is muted.

...and then I initialized them, one in the constructor (musicIsMuted), and one in the onTick function
  1. musicIsMuted = false;


and
  1. if( mKeyIsBeingPressed )

  2. {

  3.     if( musicIsMuted )

  4.     {

  5.  

  6.     }

  7.     else

  8.     {

  9.         musicPosition = Math.floor(bgmSoundChannel.position);

  10.     }

  11. }



Ok, ok.... I did a little more then initialize it. I put together the basic if...else structure I was going to use. If the m key is being pressed, then if the music is already muted, do nothing right now, else check the position (in milliseconds) it was muted at, and put that into our variable, as a whole number (that's what Math.floor() does, if you don't remember)

Now, let's flesh it out some. If the music wasn't muted already, what do we want to do? We want to stop the background music from playing, and we want to change our variable (musicIsMuted) which tells us if the music is playing to true.
  1. else

  2. {

  3.     musicPosition = Math.floor(bgmSoundChannel.position);

  4.     bgmSoundChannel.stop();

  5.     musicIsMuted = true;

  6. }



If the player already muted the music, and now wants it to play again (cause they miss those jazzy synth beats!) then we would want it to play from where it stopped (we can do that by passing the play() function an argument), and change the musicIsMuted variable back to false.
  1. if( musicIsMuted )

  2. {

  3.     bgmSoundChannel = backgroundMusic.play( musicPosition );

  4.     musicIsMuted = false;

  5. }



Now save everything and test your game... Easy, huh?
Oh, wait, you say it keeps rapidly turning off and on? Crud! Well, we can fix that using some tidbits from Michael's sh'm'up tutorial.

Create another global variable:
  1. public var ticksSinceMutePressed:int;



Initialize it in the constructor:
  1. ticksSinceMutePressed = 0;



and change your function to:
  1. if( mKeyIsBeingPressed )

  2. {

  3.     if( ticksSinceMutePressed > 10 )

  4.     {

  5.         if( musicIsMuted )

  6.         {

  7.             bgmSoundChannel = backgroundMusic.play( musicPosition );

  8.             musicIsMuted = false;

  9.         }

  10.         else

  11.         {

  12.             musicPosition = Math.floor(bgmSoundChannel.position);

  13.             bgmSoundChannel.stop();

  14.             musicIsMuted = true;

  15.         }

  16.     ticksSinceMutePressed = 0;

  17.     }

  18. }

  19. ticksSinceMutePressed += 1;



If you haven't read that tutorial already, and can't piece together what I did, head over and check it out. No use in me re-inventing the wheel.

Avoider Game Shmup

That should do it. Now you can hear the 'thump, thump, thump' of the enemys coming on screen without that pesky synth-music playing in the background!

Monday, July 27, 2009

Disappearing Flash Window?

I've had a bizarre problem happen with Flash CS3 twice now since I've been using it. I don't know what causes this but Flash disappears when I "restore" the window (when it's not maximized) It's really bizarre. I mean, I can work with it maximized just fine, but I don't want it to HAVE to be maximized.
I tried:
Right-clicking it's button in the taskbar and selecting "Move", and then using the arrow keys and/or the mouse. Didn't do anything.
Right-clicking it's button in the taskbar and selecting "Size"... Didn't do anything.
I think I tried reinstalling Flash the first time. (I'm in IT - it was like a personal challenge!) - Didn't do anything.
Reset settings in Flash. Doing this caused my preferences to reset, unfortunately it didn't fix my problem. - Didn't do anything useful.
This time I searched online and found the solution on Experts-Exchange.

"I found this config file and renamed it:
C:\Documents and Settings\%username%\Local Settings\Application Data\Macromedia\Flash 8\en\Configuration\panelset.xml

Flash started again and all windows are visible again. The above file was recreated..."


So I tried the same thing, since I'm using CS3 they changed the name of the file on us, it's now called "workspacelayout.xml" - when I renamed it (to .old) and restarted Flash, I was able to restore my window and it actually showed up!
"Happy! Happy! Joy! Joy! Happy! Happy! Joy! Joy! Happy....."

Friday, July 24, 2009

Bee Stings

Wow, I forgot how much bee stings can hurt! I haven't been stung in years, but was driving back from the gym earlier with my window open (I don't have A/C) A bee flew in, landed on me, stung me, and flew back out the window!
Stupid bee...
Yowch!

Thursday, July 23, 2009

Trace()


I cannot over. emphasize. my. love. of. the. Trace. Command (ok, maybe I can overemphasize it)

Seriously though, when it comes to debugging my AS3 code, trace() is invaluable!

For example, when trying to create different start buttons for mouse and keyboard controls I was trying to send navigation events, and changing variables, creating variables... sometimes, at first I wasn't sure if the code I implemented worked so I used trace to spit out some information into the 'output' tab. (It's down between 'Properties' and 'Compiler Errors')

Here's how you use it:

  1. trace( variableName ); // Outputs the value of that variable

  2. trace( "Your Text Here" ); // Outputs 'Your Text Here'

  3. trace( "AvoiderGame.as Line 37 xSpeed = ", xSpeed ); //Outputs 'AvoiderGame.as Line 37 xSpeed = 6' (or whatever the value of xSpeed is...)



Easy Peasy Lemon Squeezy!

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 );

  5.     Mouse.show();

  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 NavigationEvent.as 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 DocumentClass.as 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 AvoiderGame.as - 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 DocumentClass.as and change every instance of

  1. playScreen = new AvoiderGame();



to...

  1. playScreen = new AvoiderGame( useMouseControl );



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